【问题标题】:Using the Ruby Mechanize "links_with" to grab text but getting extra content使用 Ruby Mechanize "links_with" 抓取文本但获取额外内容
【发布时间】:2017-04-25 02:12:30
【问题描述】:

当我使用 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,但它并没有摆脱这些随机字符。


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

【问题讨论】:

  • 使用regex 是我的处理方式。

标签: ruby nokogiri mechanize-ruby


【解决方案1】:

您未能向我们提供示例 HTML,以显示您正在处理的标记。这使得帮助你变得非常困难。不要那样做;帮助我们帮助您。

Mechanize 在内部使用 Nokogiri 并可以返回给您一个 Nokogiri 文档,所以您会想要得到它。从那里您进入 Nokogiri 的域,这将使您能够更好地控制搜索。

使用 Mechanize 的 links_with 查找文档中的所有匹配链接,并将它们作为 Node 数组返回,也称为 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 代码来查找在'a span' CSS 选择器中定义的匹配span 节点。第二种速度较慢,但​​更灵活,允许您使用 Ruby 的语言来迭代和查看标签。

另见“How to avoid joining all text from Nodes when scraping”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-14
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多