我想使用此刮板从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并逐步进行:
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条警告,并分别说明每个错误和解决方法。