当我从HTML或XML中抓取几个相关节点以提取文本时,所有文本都会连接成一个长字符串,从而无法恢复单个文本字符串。
例如:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<p>foo</p>
<p>bar</p>
<p>baz</p>
</body>
</html>
EOT
doc.search('p').text # => "foobarbaz"
但我想要的是:
["foo", "bar", "baz"]
刮取XML时也是如此:
doc = Nokogiri::XML(<<EOT)
<root>
<block>
<entries>foo</entries>
<entries>bar</entries>
<entries>baz</entries>
</block>
</root>
EOT
doc.search('entries').text # => "foobarbaz"
为什么会发生这种情况,我该如何避免呢?
答案 0 :(得分:3)
这是一个容易解决的问题,因为没有阅读有关text
在NodeSet和Node(或元素)上使用时的行为的文档。
NodeSet documentation说text
会:
获取所有包含的Node对象的内部文本
我们看到的是:
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<p>foo</p>
<p>bar</p>
<p>baz</p>
</body>
</html>
EOT
doc.search('p').text # => "foobarbaz"
,因为:
doc.search('p').class # => Nokogiri::XML::NodeSet
相反,我们希望获取每个节点并提取其文本:
doc.search('p').first.class # => Nokogiri::XML::Element
doc.search('p').first.text # => "foo"
可以使用map
完成:
doc.search('p').map { |node| node.text } # => ["foo", "bar", "baz"]
Ruby允许我们使用:
更简洁地编写doc.search('p').map(&:text) # => ["foo", "bar", "baz"]
无论我们是使用HTML还是XML,都是一样的,因为HTML是一个更轻松的XML版本。
Node有几种别名方法可以获取其嵌入文本。来自the documentation:
#content ⇒ Object
也称为:
text
,inner_text
返回此节点的内容。