抓取时如何避免加入来自节点的所有文本
How to avoid joining all text from Nodes when scraping
当我从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"
为什么会发生这种情况,我该如何避免?
这是一个容易解决的问题,是由于没有阅读有关 text
在节点集和节点(或元素)上使用时的行为方式的文档。
NodeSet documentation 表示 text
将:
Get the inner text of all contained Node objects
这就是我们看到的情况:
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 的更宽松版本。
一个节点有几个获取其嵌入文本的别名方法。来自 the documentation:
#content ⇒ Object
Also known as: text
, inner_text
Returns the contents for this Node.
当我从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"
为什么会发生这种情况,我该如何避免?
这是一个容易解决的问题,是由于没有阅读有关 text
在节点集和节点(或元素)上使用时的行为方式的文档。
NodeSet documentation 表示 text
将:
Get the inner text of all contained Node objects
这就是我们看到的情况:
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 的更宽松版本。
一个节点有几个获取其嵌入文本的别名方法。来自 the documentation:
#content ⇒ Object
Also known as:
text
,inner_text
Returns the contents for this Node.