Подтвердить что ты не робот

Как я могу печатать HTML с помощью Nokogiri?

Я написал веб-искателя в Ruby, и я использую Nokogiri::HTML для разбора страницы. Мне нужно распечатать страницу и во время беспорядка в IRB я заметил метод pretty_print. Однако он принимает параметр, и я не могу понять, что он хочет.

Мой искатель кэширует HTML-страницы веб-страниц и записывает их в файлы на моем локальном компьютере. Я хотел бы "довольно печатать" HTML, чтобы он выглядел красиво и правильно отформатирован, когда я это делаю.

4b9b3361

Ответ 1

Под "довольно печатной" страницей HTML я предполагаю, что вы имели в виду, что хотите переформатировать структуру HTML с правильным отступом. Нокигири этого не поддерживает; pretty_print метод предназначен для библиотеки "pp", и вывод полезен только для отладки.

Есть несколько проектов, которые хорошо понимают HTML, чтобы иметь возможность переформатировать его, не уничтожая пробелы, которые на самом деле значительны (знаменитый HTML Tidy), но по googling я нашел этот пост под названием "Довольно печатать XHTML с помощью Nokogiri и XSLT" .

Это сводится к следующему:

xsl = Nokogiri::XSLT(File.open("pretty_print.xsl"))
html = Nokogiri(File.open("source.html"))
puts xsl.apply_to(html).to_s

Это требует от вас, конечно, загрузки связанного файла xsl в вашу файловую систему. Я пробовал это очень быстро на своей машине, и это работает как прелесть.

Ответ 2

Ответ от @mislav несколько неправильный. Nokogiri поддерживает симпатичную печать, если вы:

  • Разберите документ как XML
  • Поручить Nokogiri игнорировать узлы с пробелами ( "пробелы" ) во время разбора
  • Используйте to_xhtml или to_xml, чтобы указать параметры довольно печати

В действии:

html = '<section>
<h1>Main Section 1</h1><p>Intro</p>
<section>
<h2>Subhead 1.1</h2><p>Meat</p><p>MOAR MEAT</p>
</section><section>
<h2>Subhead 1.2</h2><p>Meat</p>
</section></section>'

require 'nokogiri'
doc = Nokogiri::XML(html,&:noblanks)
puts doc
#=> <section>
#=>   <h1>Main Section 1</h1>
#=>   <p>Intro</p>
#=>   <section>
#=>     <h2>Subhead 1.1</h2>
#=>     <p>Meat</p>
#=>     <p>MOAR MEAT</p>
#=>   </section>
#=>   <section>
#=>     <h2>Subhead 1.2</h2>
#=>     <p>Meat</p>
#=>   </section>
#=> </section>

puts doc.to_xhtml( indent:3, indent_text:"." )
#=> <section>
#=> ...<h1>Main Section 1</h1>
#=> ...<p>Intro</p>
#=> ...<section>
#=> ......<h2>Subhead 1.1</h2>
#=> ......<p>Meat</p>
#=> ......<p>MOAR MEAT</p>
#=> ...</section>
#=> ...<section>
#=> ......<h2>Subhead 1.2</h2>
#=> ......<p>Meat</p>
#=> ...</section>
#=> </section>

Ответ 3

Вы можете попробовать REXML:

require "rexml/document"

doc = REXML::Document.new(xml)
doc.write($stdout, 2)

Ответ 4

Это сработало для меня:

 pretty_html = Nokogiri::HTML(html).to_xhtml(indent: 3) 

Я попробовал версию REXML выше, но это испортило некоторые мои документы. И мне не нравится приводить xslt в новый проект. Оба чувствуют усталость.:)

Ответ 5

Моим решением было добавить метод print на фактические объекты Nokogiri. После того, как вы выполните код в приведенном ниже фрагменте, вы должны просто написать node.print, и он будет довольно печатать содержимое. Нет xslt требуется: -)

Nokogiri::XML::Node.class_eval do
  # Print every Node by default (will be overridden by CharacterData)
  define_method :should_print? do
    true
  end

  # Duplicate this node, replace the contents of the duplicated node with a
  # newline. With this content substitution, the #to_s method conveniently
  # returns a string with the opening tag (e.g. `<a href="foo">`) on the first
  # line and the closing tag on the second (e.g. `</a>`, provided that the
  # current node is not a self-closing tag).
  #
  # Now, print the open tag preceded by the correct amount of indentation, then
  # recursively print this node children (with extra indentation), and then
  # print the close tag (if there is a closing tag)
  define_method :print do |indent=0|
    duplicate = self.dup
    duplicate.content = "\n"
    open_tag, close_tag = duplicate.to_s.split("\n")

    puts (" " * indent) + open_tag
    self.children.select(&:should_print?).each { |child| child.print(indent + 2) }
    puts (" " * indent) + close_tag if close_tag
  end
end

Nokogiri::XML::CharacterData.class_eval do
  # Only print CharacterData if there non-whitespace content
  define_method :should_print? do
    content =~ /\S+/
  end

  # Replace all consecutive whitespace characters by a single space; precede the
  # outut by a certain amount of indentation; print this text.
  define_method :print do |indent=0|
    puts (" " * indent) + to_s.strip.sub(/\s+/, ' ')
  end
end

Ответ 6

Почему бы вам не попробовать метод pp?

require 'pp'
pp some_var