簡體   English   中英

SAX使用Nokogiri HTML解析器解析一堆死去的總統嗎?

[英]SAX parsing a bunch of dead presidents with Nokogiri HTML parser?

我想在“美國總統名單 ”維基頁面上分析美國總統。

我可以用一堆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元素及其內容?

使用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元素,您必須通過向start_elementcharacters等添加更多if子句來跟蹤所處的容器元素。具有相同名稱的元素,您必須自己跟蹤計數器,或實現堆棧以壓入和彈出您看到的元素。 它變得非常混亂。

SAX最適合您不關心DOM的過濾器,而您只是在進行一些基本的轉換。

相反,請考慮使用單個XPath語句,例如

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

它說:“查找包含div並帶有'Presidents of America's的表,並從其中的所有已排序列表項中返回文本”。 這可以在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"]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM