有没有更好的方法使用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或者有更好的方法吗?
答案 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
。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?)