0

「米国大統領のリスト」wikiページで米国大統領を解析したいと思います。

これは、一連の XPath とループを使用して実行できます。しかし、SAx の解析は非常に高速であり、その実装方法を学びたいと思っています。

Nokogiri ドキュメントは、HTML SAX 解析の例を示してくれました。

class MyDoc < Nokogiri::XML::SAX::Document
 def start_element name, attributes = []
   puts "found a #{name}"
 end
end

parser = Nokogiri::HTML::SAX::Parser.new(MyDoc.new)
parser.parse(File.read(ARGV[0], 'rb'))

しかし、取得したいすべての HTML 要素とそのコンテンツを定義するには、どのメソッドを使用すればよいでしょうか?

4

1 に答える 1

0

SAX では、「イベント」ごとにパーサーでコールバック メソッドを定義する必要があります。自分で状態を追跡する必要があります。それは非常に粗雑です。たとえば、ページから大統領の名前を取得するには、次のようにします。

class MyDoc < Nokogiri::XML::SAX::Document
  def start_element name, attributes = []
    if name == "li"
      @inside_li = true
    end
  end

  def characters(chars)
    if @inside_li
     puts "found an <li> containing the string '#{chars}'"
    end
  end

  def end_element name
    if name == "li"
      puts "ending #{name}"
      @inside_li = false
    end
  end
end

上記は、次のステートメントとほぼ同等と考えることができます。

doc.xpath('//li').map(&:text)

次の出力で始まります。

ending li
found an <li> containing the string 'Grover Cleveland'
ending li
found an <li> containing the string 'William McKinley'
ending li
found an <li> containing the string 'Theodore Roosevelt'

ここまでは順調ですが、次のように多くのクラフトも出力されます。

found an <li> containing the string 'Disclaimers'
ending li
found an <li> containing the string 'Mobile view'
ending li
found an <li> containing the string '
                        '
found an <li> containing the string '
                    '
ending li
found an <li> containing the string '
                        '
found an <li> containing the string '
                    '
ending li

したがって、これをより正確にし、気にしない要素を取得しないようにするには、、 などに句をli追加して、現在のコンテナー要素を追跡する必要があります。自分でカウンターを追跡するか、スタックを実装して、表示される要素をプッシュおよびポップする必要があります。それは非常に速く非常に面倒です。ifstart_elementcharacters

SAX は、DOM を気にせず、いくつかの基本的な変換を行うだけのフィルターに最適です。

代わりに、次のような単一の XPath ステートメントを使用することを検討してください。

doc.xpath("//table[contains(.//div, 'Presidents of the United States')]//ol/li").map(&:text)

これは、「'Presidents of the United States' という単語を含む div を含むテーブルを見つけ、その中のすべての順序付けられたリスト項目からテキストを返す」ことを示しています。これは SAX で実行できますが、非常に厄介なコードになります。

上記の XPath の出力:

["George Washington", "John Adams", "Thomas Jefferson", "James Madison", "James Monroe", "John Quincy Adams", "Andrew Jackson", "Martin Van Buren", "William Henry Harrison", "John Tyler", "James K. Polk", "Zachary Taylor", "Millard Fillmore", "Franklin Pierce", "James Buchanan", "Abraham Lincoln", "Andrew Johnson", "Ulysses S. Grant", "Rutherford B. Hayes", "James A. Garfield", "Chester A. Arthur", "Grover Cleveland", "Benjamin Harrison", "Grover Cleveland", "William McKinley", "Theodore Roosevelt", "William Howard Taft", "Woodrow Wilson", "Warren G. Harding", "Calvin Coolidge", "Herbert Hoover", "Franklin D. Roosevelt", "Harry S. Truman", "Dwight D. Eisenhower", "John F. Kennedy", "Lyndon B. Johnson", "Richard Nixon", "Gerald Ford", "Jimmy Carter", "Ronald Reagan", "George H. W. Bush", "Bill Clinton", "George W. Bush", "Barack Obama"]
于 2013-01-11T01:04:00.163 に答える