我试图使用Nokogiri从HTML文档中获取所有节点。如果你们认为它更容易,我可以使用别的东西。
我有这个HTML:
<html>
<body>
<h1>Header1</h1>
<h2>Header22</h2>
<ul>
<li>Li1</li>
<ul>
<li>Li1</li>
<li>Li2</li>
</ul>
</ul>
</body>
</html>
字符串版本:
string_page = "<html><body><h1>Header1</h1><h2>Header22</h2><ul><li>Li1</li><ul><li>Li1</li><li>Li2</li></ul></ul></body></html>"
我创建了一个对象:
page = Nokogiri.HTML(string_page)
我试图遍历它:
result = []
page.traverse { |node| result << node.name unless node.name == "text" }
=> ["html", "h1", "h2", "li", "li", "li", "ul", "ul", "body", "html", "document"]
但我不喜欢的是元素的顺序。我需要一个具有相同顺序的数组:
["html", "body", "h1", "h2", "ul", "li", "ul", "li", "li" ]
我不需要关闭标签。
有没有人有更好的解决方案来实现这个目标?
答案 0 :(得分:2)
如果要按顺序查看节点,请使用类似'*'
的XPath选择器,这意味着&#34;所有内容&#34;,从根节点开始:
require 'nokogiri'
string_page = "<html><body><h1>Header1</h1></body></html>"
doc = Nokogiri::HTML(string_page)
doc.search('*').map(&:name)
# => ["html", "body", "h1"]
但是,我们通常不关心迭代每个节点,我们通常也不想这样做。我们想要查找某个类型的所有节点或单个节点,因此我们在标记中查找地标并从那里开始:
doc.at('h1').text # => "Header1"
或:
html = "<html><body><table><tr><td>cell1</td></tr><tr><td>cell2</td></tr></h1></body></html>"
doc = Nokogiri::HTML(html)
doc.search('table tr td').map(&:text) # => ["cell1", "cell2"]
或:
doc.search('tr td').map(&:text) # => ["cell1", "cell2"]
或:
doc.search('td').map(&:text) # => ["cell1", "cell2"]
注意:没有理由使用更长的示例HTML字符串;它只会使问题变得混乱,所以请使用一个最小的例子。
参见&#34; How to avoid joining all text from Nodes when scraping&#34;还