IT技术博客大学习 共学习 共进步

Ruby 解析 HTML (Nokogiri)

qingbo.blog 2010-06-01 13:05:04 浏览 4,825 次

很多时候我们需要爬取网页并且获取页面上的特定内容,不一定是做坏事比如爬取竞争对手的数据。也许我想定期爬自己的网站,找到页面上的链接,并且看它们指向的网页是不是都还可以访问。爬到一个网页,为了获得上面所有的链接,我以前首先想到的是用正则表达式。但是 HTML 并不一定是良构的 XML (如果每个人都用 XML 的标准写 HTML,那我们直接用标准的 XML parser 就好了),写正则表达式的时候你需要考虑大小写、换行、单引号/双引号/没有引号、某些地方的空格,太头疼了。

更好的办法当然是像在浏览器中使用 JavaScript 一样,在 DOM 树上找东西。我比较习惯用 jQuery,通过 CSS selector 来找页面上的节点非常舒服。

其实大部分的语言都有人实现了 HTML parser. 拿当下比较火的 Ruby 来说,随便一搜就找到两个:HpricotNokogiri.看名字好像都是日本人写的──不奇怪,Ruby 就是日本人发明的。

我在 Mac 上先试用了 Hpricot, 很奇怪我测试的一个文档不能正常处理。于是尝试 Nokogiri,很不错,没有发现问题。如果懂 XPath,Nokogiri 提供了 XPath 方式来寻找文档里的节点。或者你习惯了 CSS selector,在 Nokogiri 中也可以用类似 jQuery 的方法:

require 'nokogiri'

html = '...'
doc = Nokogiri::HTML(html)

# 获取页面上所有的链接
doc.css('a').each do |link|
  puts "#{link.content}, #{link['href']}"
end

# 打出 meta-keywords
puts doc.css('meta[name="keywords"'])[0].content

使用 Nokogiri 相对于正则表达式的优点当然是更简单直观,而且更安全。缺点呢?如果你只是要页面上很少的数据,Nokogiri 可能比正则表达式稍微慢点,因为不管你要的数据有多么少,它都需要分析整个 HTML 文档(不过 Nokogiri 也提供了 SAX 方式的解析)。

有意思的是 Nokogiri 一出来就号称比老牌的 Hpricot 快,然后 Hpricot 不服,很快就开始反击,我也不知道现在到底是什么情况了。有兴趣的可以看它们提供的 benchmark. 不过我想解析的速度再慢,这种过程的瓶颈还是在爬取网页这个环节上,尤其在中国这种网速超慢的条件下 :)

建议继续学习

  1. 每个程序员都应该学习使用Python或Ruby (阅读 17,741)
  2. 我的PHP,Python和Ruby之路 (阅读 12,983)
  3. Ruby 和 Python (阅读 6,943)
  4. 为什么我们要从 NodeJS 迁移到 Ruby on Rails (阅读 6,201)
  5. HTML5是什么东东 我们为什么要关注 (阅读 4,866)
  6. 记上海Python社区聚会,谈Python和Ruby (阅读 4,825)
  7. HTML页面布局基础 (阅读 4,503)
  8. 为什么不压缩 HTML (阅读 4,344)
  9. HTML优化 (阅读 4,045)
  10. Ajax和WEB服务数据格式:XML SOAP HTML (阅读 4,023)