尝试使用Nokogiri刮取网站时未定义的方法

时间:2015-01-13 23:55:37

标签: ruby nokogiri scrape

我想从HM网站获取一些数据,我正在使用这个刮刀。这是一个例子:

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类,我可以在JS控制台中获取信息,但我不能与Nokogiri一起使用。它找不到它。有什么想法吗?

修改

我尝试定位全身文字,这是我打印的唯一内容。

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

也许有些js破坏了我的伤害?

1 个答案:

答案 0 :(得分:3)

一个想法是使用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行可能是问题:它是<header>标记,我们碰巧知道它不包含您的目标,因此我们可以将其删除。将HTML保存到文件,然后使用任何文本编辑器删除标记及其所有内容,然后重新解析。

现在有用吗?

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

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

我还希望通过删除我知道不包含目标的内容来减少HTML,例如<head>区域,<footer>区域,<script>区域等。

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

最终我们发现HTML有许多不正确的标签,例如未关闭的标签。

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

  • 纯粹的方法是以任何方式修复未关闭的部分标签。

  • 黑客的方法是将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"

首先确定黑客方式并不是真正的HTML精通,如果HTML页面作者更改为使用其他标记,或者在您想要的类名之前使用其他类名,则可以看到它将失败等等。

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