[尝试使用Nokogiri抓取网站时如何解决“未定义方法”

问题描述 投票:1回答:1

我想使用此刮板从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破坏了我的爬虫?

ruby nokogiri scrape
1个回答
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包含许多不正确的标签,例如未关闭的部分标签。

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

  • 纯粹的方法是根据需要修复未关闭的部分标签。

  • 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"

抬头说,这种破解方法并不是真正的HTML理解,如果HTML页面作者更改为使用其他标签,或者在所需的类名之前使用其他类名,您会发现它会失败。

最佳的长期解决方案是与HTML页面的作者联系,并向他展示如何验证HTML。一个不错的网站是http://validator.w3.org/ -验证URL时,该网站会显示100个错误和6条警告,并分别说明每个错误和解决方法。

© www.soinside.com 2019 - 2024. All rights reserved.