屏幕刮通nokogiri或hpricot

时间:2011-10-17 12:08:25

标签: ruby xpath screen-scraping nokogiri hpricot

我正在尝试获取给定xpath的实际值。我在sample.rb文件中有以下代码

require 'rubygems'
require 'nokogiri'
require 'open-uri'
doc = Nokogiri::HTML(open('http://www.changebadtogood.com/'))
desc "Trying to get the value of given xapth"
task :sample do
  begin
    doc.xpath('//*[@id="view_more"]').each do |link|
      puts link.content
    end
  rescue Exception => e
    puts "error" 
  end
end

输出是:

  

查看更多问题..

当我尝试获取其他不同XPath的值时,例如:
/html/body/div[4]/div[3]/h1/span 然后我收到“错误”消息。

我在Nokogiri尝试了这个。我不知道为什么这只是为少数XPath提供结果。

我在Hpricot中尝试了同样的事 http://hpricot.com/demonstrations

我粘贴了我的网址和XPath,我看到了结果 的 //*[@id="view_more"]
作为
查看更多问题..
[此文本出现在最近问题标题的底部]

但它没有显示结果:
/html/body/div[4]/div[3]/h1/span 对于这个XPath,我期待结果Bad [这是出现在 http://www.changebadtogood.com/作为class =“hero-unit”div的第一个标题。]

1 个答案:

答案 0 :(得分:2)

你的问题与糟糕的XPath选择器有关,与Nokogiri或Hpricot无关。我们来调查一下:

irb:01:0> require 'nokogiri'; require 'open-uri'
#=> true
irb:02:0> doc = Nokogiri::HTML(open('http://www.changebadtogood.com/')); nil
#=> nil
irb:03:0> doc.xpath('//*[@id="view_more"]').each{ |link| puts link.content }
View more issues ..
#=> 0
irb:04:0> doc.at('#view_more').text  # Simpler version of the above.
#=> "View more issues .."
irb:05:0> doc.xpath('/html/body/div[4]/div[3]/h1/span')
#=> []
irb:06:0> doc.xpath('/html/body/div[4]')
#=> []
irb:07:0> doc.xpath('/html/body/div').length
#=> 2

由此我们可以看到只有两个div是<body>元素的子元素,因此div[4]无法选择一个。

您似乎在尝试选择此处的范围:

<h1 class="landing_page_title">
  Change <span style='color: #808080;'>Bad</span> To Good
</h1>

不要依赖于导致此问题的脆弱标记(索引元素的匿名层次结构),而是使用文档的语义结构来为您提供更简单且更健壮的选择器。使用CSS或XPath语法:

irb:08:0> doc.at('h1.landing_page_title > span').text
#=> "Bad"
irb:09:0> doc.at_xpath('//h1[@class="landing_page_title"]/span').text
#=> "Bad"