Nokogiri只抓住可见的inner_text

时间:2012-03-09 18:37:13

标签: ruby nokogiri

有没有更好的方法使用Nokogiri在网页上提取可见文字?目前我使用inner_text方法,但该方法将大量JavaScript视为可见文本。我想要捕获的唯一文本是屏幕上的可见文本。

例如,在IRB中如果我在Ruby 1.9.2-p290中执行以下操作:

require 'nokogiri'
require 'open-uri'
doc = Nokogiri::HTML(open("http://www.bodybuilding.com/store/catalog/new-products.jsp?addFacet=REF_BRAND:BRAND_MET_RX"))
words = doc.inner_text
words.scan(/\w+/)

如果我搜索“功能”这个词,我会看到它在列表中出现了20次,但是如果我转到http://www.bodybuilding.com/store/catalog/new-products.jsp?addFacet=REF_BRAND:BRAND_MET_RX,“功能”这个词就不会出现在可见文本的任何地方。

我可以忽略JavaScript或者有更好的方法吗?

3 个答案:

答案 0 :(得分:6)

你可以尝试:

require 'nokogiri'
require 'open-uri'

doc = Nokogiri::HTML(open("http://www.bodybuilding.com/store/catalog/new-products.jsp?addFacet=REF_BRAND:BRAND_MET_RX"))

doc.traverse{ |x|
    if x.text? && x.text !~ /^\s*$/
        puts x.text
    end
}

我对Nokogiri没有做太多,但我相信这应该找到/输出文档中不是空白的所有文本节点。这至少似乎忽略了javascript,我检查的所有文本都在页面上可见(虽然其中一些在下拉菜单中)。

答案 1 :(得分:1)

您可以忽略JavaScript,并且有更好的方法。你无视Nokogiri的力量。不好。

不是直接给你答案,而是学会用Nokogiri“钓鱼”。

在如下的文件中:

<html>
  <body>
    <p>foo</p>
    <p>bar</p>
  </body>
</html>

我建议从CSS访问器开始,因为人们通常更熟悉它们:

  • doc = Nokogiri::HTML(var_containing_html)将解析并返回doc
  • 中的HTML DOM
  • doc.at('p')将返回一个Node,它基本上指向第一个<p>节点。
  • doc.search('p')将返回所有匹配节点的NodeSet,其作用类似于数组,在本例中为所有<p>个节点。
  • doc.at('p').text将返回节点内的文本。
  • doc.search('p').map{ |n| n.text }将返回<p>个节点中的所有文本作为文本字符串数组。

随着您的文档变得越来越复杂,您需要向下钻取。有时您可以使用CSS访问器(例如'body p'或类似的东西)来执行此操作,有时您需要使用XPath。我不会进入那些,但那里有很棒的教程和参考资料。

Nokogiri's tutorials非常好。通过他们,他们将揭示你需要知道的一切。

此外,Stack Overflow上有很多答案在讨论这类问题。查看页面右侧的“相关”链接。

答案 2 :(得分:0)

忽略 JavaScript 所在的标签 (<script>)。在此过程中,我们还应该忽略 CSS (<styles>)。

require 'nokogiri'
require 'open-uri'

doc = Nokogiri::HTML(URI.open("http://www.bodybuilding.com/store/catalog/new-products.jsp?addFacet=REF_BRAND:BRAND_MET_RX"))
doc.css('style').each(&:remove)
doc.css('script').each(&:remove)

puts doc.text

# Alternatively, for cleaner output:
# puts doc.text.split("\n").map(&:strip).reject(&:empty?)