使用Ruby Mechanize“links_with”来获取文本但获取额外内容

时间:2015-06-03 01:37:40

标签: ruby nokogiri mechanize-ruby

当我使用Mechanize links_with方法获取一组链接时,我只希望文本显示链接但我得到一系列额外字符:

links = @some_page.links_with(text: /V\s.*(BENCH|EARCX)|(BENCH|EARCX).*V/)

links.each do |link|
  link.text
end

链接在我的浏览器中显示为“23409BENCH092834”和“20193BENCH092339”,这正是我想要的,但是当我将它们保存在我的数据库中时,它们会被保存为

\r\n\t\t\t\t\r\n\t\t\t\t\t 23409BENCH092834\r\n\t\t\t\t\r\n\t\t\t\t

这些额外角色来自哪里,它们代表什么?我已尝试在其上使用textto_s,但它并没有消除这些随机字符。

我认为它们可能是转义码但是如果是这样我将如何删除它们?

1 个答案:

答案 0 :(得分:1)

您未能向我们提供示例HTML,显示您正在使用的标记。这使得你很难帮助你。不要那样做;帮助我们帮助您。

Mechanize在内部使用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返回的NodeSet中找到的节点中的所有文本,这通常不是很有用。

相反,找到您想要的特定节点并获取其文本:

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代码来查找span CSS选择器中定义的匹配'a span'节点。第二种是较慢但更灵活,允许您使用Ruby的语言迭代并查看标签。

另请参阅“How to avoid joining all text from Nodes when scraping”。