您没有给我们示例HTML,显示您正在使用的标记。这使你很难帮助你。不要那样做;帮助我们帮助你。
机械化使用Nokogiri内部并可以返回给你一个Nokogiri文件,所以你会想要得到它。从那里你在Nokogiri的领域,这将让你更多的控制搜索。
使用Mechanize的links_with
查找文档中的所有匹配链接并将它们返回为Node,AKA NodeSet的数组。那些可能包含很多其他节点,它们负责您看到的选项卡和返回。虽然links_with
很有用,但您必须始终注意什么东西正在返回,以便您能够正确地做出反应。
您看到的问题是因为您在提取文本时没有访问正确的标记,或者您在链接中看到的值与您报告的不完全一致。
考虑一下:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<p>foo</p>
|
<p>bar</p>
</body>
</html>
EOT
从不是确切的一个更高的标签(父)提取文本,你应该将返回在父母的一切:
doc.search('body').text # => "\nfoo\n|\nbar\n"
注意到它捡起线标签之间的破解和|
。这是因为text
返回全部文本节点,而不仅仅是子标签内的那些节点。所以明确你想要什么是重要的。
同样,搜索仅p
标签返回所有在他们里面找到的文本:
doc.search('p').text # => "foobar"
这也不会因为text
平时工作将串联在返回的节点集发现的节点中的所有文本search
,这通常不是很有用。
相反,找到你想要的特定节点,并得到其文本:
doc.at('p').text # => "foo"
at
返回第一个匹配的节点,相当于search('p').first
。
如果你想全部来自p
节点的文字,然后在它们之间迭代:
doc.search('p').map(&:text) # => ["foo", "bar"]
在更复杂的文件中,我们往往要找到标签的层次结构中的特定的里程碑,找到它,然后进一步搜索,但这是一个单独的问题。
把所有一起,这里是一个示例,帮助形象化你遇到什么和如何对付它:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html>
<body>
<a href="http://example.com">
<span class="hubbub">foo</span>
</a>
|
<a href="http://example.com">
<span class="hubbub">bar</span>
</a>
</body>
</html>
EOT
不要做这些:
doc.search('body').text # => "\n \n foo\n \n |\n \n bar\n \n"
doc.search('a').text # => "\n foo\n \n bar\n "
做这些:
doc.search('a span').map(&:text) # => ["foo", "bar"]
或者:
spans = doc.search('a').map{ |link|
link.at('span').text
}
spans # => ["foo", "bar"]
第一种速度更快,因为它依靠libXML2代码来查找'a span'
CSS选择器中定义的匹配span
节点。第二个比较慢,但更灵活,可以使用Ruby的语言迭代并查看标签。
也参见“How to avoid joining all text from Nodes when scraping”。
使用'regex'是我处理这个问题的方式。 – JonB