如何从一个或多个节点提取文本

如何正确地从节点中提取文本是我们看到的最受欢迎的问题之一,并且通过滥用 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 扩展

atsearch 是仿制药 at_cssat_xpath 沿 cssxpath 。Nokogiri 尝试确定是否传入了 CSS 或 XPath 选择器。可以创建一个选择器来欺骗 atsearch,因此偶尔会误解,这就是为什么我们有更具体的方法版本。一般来说,我几乎总是使用通用版本,如果我认为 Nokogiri 会误解,只使用特定版本。这种做法属于“ 三德 ” 的第一个条目。

如果你要搜索一个特定节点并想要其文本,请使用 at 或其中一个 at_cssat_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,所以你可以使用更长的版本,但为什么呢?

如果在使用 searchcssxpath 之后连接的文本被连接起来,那么添加 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"]

有关其他信息,请参阅 NodeSetNodetext 文档。