我想从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破坏了我的伤害?
答案 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个警告,并解释每个网站以及如何解决它。