簡體   English   中英

Nokogiri獲得所有HTML節點

[英]Nokogiri get all HTML nodes

我想使用Nokogiri從HTML文檔中獲取所有節點。 示例HTML輸入字符串:

<html>
  <body>
    <h1>Test</h1>
    <p>test <strong> Jojo </strong></p>
  </body>
</html>

預期產量:

['<html>','<body>','<h1>','</h1>','<p>','<strong>','</strong>','</p>','</body>','</html>']

關閉標簽和正確的順序很重要!

我已經嘗試過這段代碼:

require 'nokogiri'
string_page = "<html><body><h1>Header1</h1></body></html>"
doc = Nokogiri::HTML(string_page)
doc.search('*').map(&:name)
# => ["html", "body", "h1"]

但它不會返回結束標記。

您可以將OuterXml拆分為非自動關閉的所有開放元素的InnerXml,存儲相應的關閉元素(如果有)以檢索它並使用Nokogiri讀取器解析文檔以根據文檔中的順序構建列表。

它要求您的文檔是有效的XML片段,因為它使用XML解析器而不是HTML解析器。

require 'nokogiri'
[ "<html><body><h1>Header1</h1></body></html>",
"<html><body><div><h1>Title</h1><hr /></div><div><p>Lorem Ipsum<br />sit <span class=\"style\">d</span>olor</p></div></body></html>", <<END
<html>
  <body>
      <h1>Test</h1>
      <p>test <strong> Jojo </strong></p>
  </body>
</html>
END
].each { |string_page|
  elem_all = Array.new
  elem_ends = Hash.new
  reader = Nokogiri::XML::Reader(string_page)
  reader.each { |node|
    if node.node_type.eql?(1)
      if node.self_closing?
        elem_all << node.outer_xml
      else
        elem_tags = node.outer_xml.split(node.inner_xml)
        elem_all << elem_tags.first
        elem_ends[node.local_name] = elem_tags[1] unless elem_tags.one?
      end
    end
    elem_all << elem_ends[node.local_name] if node.node_type.eql?(15) and elem_ends.has_key?(node.local_name)
  }

  puts string_page
  puts elem_all.to_s
  puts
}

輸出:

<html><body><h1>Header1</h1></body></html>
["<html>", "<body>", "<h1>", "</h1>", "</body>", "</html>"]

<html><body><div><h1>Title</h1><hr /></div><div><p>Lorem Ipsum<br />sit <span class="style">d</span>olor</p></div></body></html>
["<html>", "<body>", "<div>", "<h1>", "</h1>", "<hr/>", "</div>", "<div>", "<p>", "<br/>", "<span class=\"style\">", "</span>", "</p>", "</div>", "</body>", "</html>"]

<html>
  <body>
      <h1>Test</h1>
      <p>test <strong> Jojo </strong></p>
  </body>
</html>
["<html>", "<body>", "<h1>", "</h1>", "<p>", "<strong>", "</strong>", "</p>", "</body>", "</html>"]

您可以設置自己的結束標記,如下所示:

doc = Nokogiri::HTML(<<EOT)
<html>
  <body>
    <h1>Test</h1>
    <p>test <strong> Jojo </strong></p>
  </body>
</html>
EOT

p doc.search('*').map{|m| [m.name, "/#{m.name}"]}

# => [["html", "/html"], ["body", "/body"], ["h1", "/h1"], ["p", "/p"], ["strong", "/strong"]]

你不是真正解析掃描:

str = <<EOF
<html>
  <body>
    <h1>Test</h1>
    <p>test <strong> Jojo </strong></p>
  </body>
</html>
EOF

str.scan /<.*?>/
#=> ["<html>", "<body>", "<h1>", "</h1>", "<p>", "<strong>", "</strong>", "</p>", "</body>", "</html>"]

暫無
暫無

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

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