【问题标题】:How to fix an "undefined method" when trying to scrape a website with Nokogiri尝试使用 Nokogiri 抓取网站时如何修复“未定义的方法”
【发布时间】:2015-01-13 23:55:36
【问题描述】:

我想从 HMs 网站获取一些数据,使用这个爬虫:

require 'nokogiri'
require 'open-uri'
require 'rmagick'
require 'mechanize'

product = "http://www2.hm.com/es_es/productpage.0250933004.html"
web = Nokogiri::HTML(open(product))
puts web.at_css('.product-item-headline').text

Nokogiri 为每个选择器返回 NIL 并引发 undefined method for nilClass。我不知道这个特定的网站是否有可以避免抓取的东西。

在 URL DOM 中,我可以看到有一个 .product-item-headline 类,我可以在 JavaScript 控制台中获取信息,但不能使用 Nokogiri。

我尝试定位整个正文,这是我唯一打印出来的内容。

var callcoremetrix = function(){cmSetClientID(getCoremetricsClientId(), true, "msp.hm.com", "hm.com");};

也许一些 JavaScript 正在破坏我的抓取?

【问题讨论】:

  • 打开一个 IRB 会话并逐步进行。甚至可能将 HTML 写入文件。仅仅因为 DOM 有一些东西并不意味着它就在你正在喂 Nokogiri 的源中。
  • 问题是如果我尝试在 IRB 中使用 Nokogiri 打开一个 URL,它会认为它是一个文件:Errno::ENOENT: No such file or directory - www2.hm.com/es_es/productpage.0250933004.html
  • 您需要先require 'open-uri'等。
  • 我在 IRB 上仍然遇到同样的错误... irb(main):005:0> puts web.at_css('.product-item-headline').text NoMethodError: undefined method `text ' for nil:NilClass

标签: ruby nokogiri scrape


【解决方案1】:

一个想法是使用IRB并逐步进行:

irb
> require 'open-uri'
> html = open(product).read

HTML 是否包含类名文本?

> html =~ /product-item-headline/
=> 56099

是的,它是这样的:

<h1 class="product-item-headline">

所以试试 Nokogiri:

> require 'nokogiri'
web = Nokogiri::HTML(html)
=> success

阅读 HTML 文本并尝试与您的问题相关的越来越广泛的查询,以使您更接近 HTML 的顶部,看看他们是否找到结果:

web.css("h1") # on line 2217 of the HTML
=> []

web.css(".product-detail-meta") # on line 2215
=> []

web.css(".wrapper") # on line 86
=> []

web.css("body") # on line 84
=> [#<Nokogiri::XML::Element …

这表明您在 HTML 中存在问题。解析在第 84 行和第 86 行之间中断。

让我们猜测第 85 行可能是问题所在:它是一个 &lt;header&gt; 标记,我们碰巧知道它不包含您的目标,因此我们可以将其删除。将 HTML 保存到文件中,然后使用任何文本编辑器删除标记及其所有内容,然后重新解析。

现在可以用了吗?

web.css("h1") # on line 359 of the HTML
=> []

不。所以我们重复这个过程,减少 HTML。

我还喜欢通过删除我知道不包含我的目标的部分来减少 HTML,例如 &lt;head&gt; 区域、&lt;footer&gt; 区域、&lt;script&gt; 区域等。

您可能喜欢使用自动缩进编辑器,因为它可以快速向您显示某些内容与 HTML 不平衡。

最终我们发现HTML中有很多不正确的标签,例如未闭合的部分标签。

您可以通过多种方式解决此问题:

  • 纯粹的方法是修复未闭合的部分标签,任何你想要的方式。

  • hack 方法是将 HTML 缩小到您知道需要的区域,即 h1 标记中。

这是破解方法:

area = html.match(/<h1 class="product-item-headline\b.*?<\/h1>/m)[0]
web = Nokogiri::HTML(area)
puts web.at_css(".product-item-headline").text.strip
=> "Funda de cojín de jacquard"

请注意,hack 方式并不是真正的 HTML 技术,如果 HTML 页面作者更改为使用不同的标签,或者在您想要的类名之前使用另一个类名等,它将失败.

最好的长期解决方案是联系 HTML 页面的作者并向他展示如何验证 HTML。一个很好的网站是http://validator.w3.org/ - 当您验证您的 URL 时,该网站显示 100 个错误和 6 个警告,并解释每个错误以及如何解决它。

【讨论】:

  • 是的,我试过瞄准整个身体,只打印了一个JS。也许在使用 Nokogiri 之前删除所有 js?
  • Nokogiri 可以轻松判断 HTML/XML 是否存在问题。解析像doc = Nokogiri::HTML(...)这样的文档后,使用doc.errors
猜你喜欢
  • 2012-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多