打印

使用Hpricot处理Html

使用Hpricot处理Html

原文标题:Processing HTML with Hpricot
原文作者:madpilot
原文地址:http://www.sitepoint.com/blogs/2 ... -html-with-hpricot/
译者:cclong
译文首发:http://www.ruby-lang.org.cn/forums/thread-2422-1-1.html


在Web2.0世界里聚合(mashups)和简单API访问使从第三方站点提取数据来重新聚合(re-mash)到新项目中变得多么容易。不幸的是,不是每个人都被它的bug所害。我们开发者不得不做多一点工作来获取我们需要的信息。通常称这技术为“网页抓取”(screen scrape), 你的程序扮演浏览器角色访问第三方服务器并转换接收的HTML。
按道理,这应当非常简单,但只有那些曾经试图通过正则表达式检索标签的人来说,才明白这是件很痛苦的事情。幸运的是,我们ruby程序员有解决麻烦的HTML解释的库:Hpricot library。Hpricot允许开发者通过CSS-selectors和X-Path访问html元素,因此你很轻松就可以明确目标标记,还有它是用C语言写的,因此相当快。

安装
Hpricot 是一个gem,因此安装很简单。

Gem install hpricot


需要调用这个库的时候只需要在ruby文件的顶部添加下面代码:

require 'hpricot' 


使用
让我们看看下面这个HTML片断:

<html> 
	  <head> 
	    <title>Snippet</title> 
	  </head> 
	  <body> 
	    <div id="container"> 
	      <div id="navigation"> 
	        <ul> 
	          <li><a href="/">Home</a></li> 
	          <li><a href="/contact></a></li> 
	        </ul> 
	       </div> 
	       <div id="sub-content"> 
	          <p>This would be some sort of sidebar</p> 
	       </div> 
	       <div id="content"> 
	         <p>This is paragraph 1</p> 
	         <p>This is paragraph 2</p> 
	       </div> 
	     </div> 
	   </body> 
	</html>


我们能轻易从段落中抓取数据(假设这个HTML网页数据已经储藏在@html变量中)

doc = Hpricot(@html) 
pars = Array.new 
doc.search("div[@id=content]/p").each do |p| 
pars << p.inner_html 
end 


是的,这样就解决了上面的问题。现在你数组里已经有2个元素就像从两个p标记里复制的一样。注意到在sub-content层的p标记没有抓取?
不但如此,你还能操纵HTML-如果你需要,它就能派上用场。比如,创建一个快速但粗劣(quick and dirty)的灵巧版本。如果我们想从灵巧版本去掉sub-content层,我们可以这样做:

doc = Hpricot(@html) 
doc.search("div[@id=sub-content]").remove 
puts doc  


输出的HTML结果不再有sub-content层!
添加新类到导航ul元素,也是很简单:

doc = Hpricot(@html) 
doc.search("div[@id=navigation]/ul").set("class", "nav") 


这只是冰山一角-这个库真的非常强大并且容易使用。官方网页有更多(有意义)的例子。
免责声明:你在抓取别人网页数据之前请确认已得到对方负责人的准许。

[ 本帖最后由 cclong 于 2007-12-13 10:25 编辑 ]
本帖最近评分记录
  • skyover R币 +2 辛苦了!好文章。 2007-12-14 09:52

TOP

watir通过操纵浏览器可以实现类似的目标。:D
谢谢大家加入Ruby中文社区!
[寻找您身边的Rubyist.]

TOP

2008-12-05 05:29 Crawled by CCBot/1.0 (+http://www.commoncrawl.org/bot.html) @38.103.63.61