Ruby で Web クローラーを作成Nokogiri::HTML
し、ページの解析に使用しています。ページを印刷する必要があり、IRB をいじっているときに方法に気付きましたpretty_print
。ただし、パラメーターが必要で、何が必要なのかわかりません。
私のクローラーは Web ページの HTML をキャッシュし、それをローカル マシンのファイルに書き込んでいます。HTML を「きれいに印刷」して、見栄えがよく、適切にフォーマットされているようにしたいと考えています。
Ruby で Web クローラーを作成Nokogiri::HTML
し、ページの解析に使用しています。ページを印刷する必要があり、IRB をいじっているときに方法に気付きましたpretty_print
。ただし、パラメーターが必要で、何が必要なのかわかりません。
私のクローラーは Web ページの HTML をキャッシュし、それをローカル マシンのファイルに書き込んでいます。HTML を「きれいに印刷」して、見栄えがよく、適切にフォーマットされているようにしたいと考えています。
@mislavによる答えはやや間違っています。次の場合、 Nokogiri は pretty-print をサポートします。
to_xhtml
orを使用して、整形パラメータ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>
HTMLページの「きれいな印刷」とは、HTML構造を適切なインデントで再フォーマットすることを意味していると思います。Nokogiri はこれをサポートしていません。メソッドはpretty_print
「pp」ライブラリ用であり、出力はデバッグにのみ役立ちます。
HTML を十分に理解して、実際に重要な空白を破壊せずに HTML を再フォーマットできるプロジェクトがいくつかあります (有名なものはHTML Tidyです) 。 .
これは次のようになります。
xsl = Nokogiri::XSLT(File.open("pretty_print.xsl"))
html = Nokogiri(File.open("source.html"))
puts xsl.apply_to(html).to_s
もちろん、リンクされた XSL ファイルをファイルシステムにダウンロードする必要があります。私は自分のマシンで非常にすばやく試してみましたが、魅力的に機能します。
REXML を試すことができます:
require "rexml/document"
doc = REXML::Document.new(xml)
doc.write($stdout, 2)
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's 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's 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
メソッドを試してみませんpp
か?
require 'pp'
pp some_var