如何从一个或多个节点提取文本
如何正确地从节点中提取文本是我们看到的最受欢迎的问题之一,并且通过滥用 Nokogiri 的搜索方法几乎总是变得更加困难。
Nokogiri 支持使用 CSS 和 XPath 选择器。这些是等价的:
doc.at('p').text # => "foo"
doc.at('//p').text # => "foo"
doc.search('p').size # => 2
doc.search('//p').size # => 2
为方便起见,CSS 选择器扩展了许多 jQuery 的 CSS 扩展 。
at
和 search
是仿制药 at_css
和 at_xpath
沿 css
和 xpath
。Nokogiri 尝试确定是否传入了 CSS 或 XPath 选择器。可以创建一个选择器来欺骗 at
或 search
,因此偶尔会误解,这就是为什么我们有更具体的方法版本。一般来说,我几乎总是使用通用版本,如果我认为 Nokogiri 会误解,只使用特定版本。这种做法属于“ 三德 ” 的第一个条目。
如果你要搜索一个特定节点并想要其文本,请使用 at
或其中一个 at_css
或 at_xpath
变体:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<p>foo</p>
<p>bar</p>
</body>
</html>
EOT
doc.at('p').text # => "foo"
at
相当于 search(...).first
,所以你可以使用更长的版本,但为什么呢?
如果在使用 search
,css
或 xpath
之后连接的文本被连接起来,那么添加 map(&:text)
而不是简单地使用 text
:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<p>foo</p>
<p>bar</p>
</body>
</html>
EOT
doc.search('p').text # => "foobar"
doc.search('p').map(&:text) # => ["foo", "bar"]