Web-Harvest是一个Java开源Web数据抽取工具。它能够收集指定的Web页面并从这些页面中提取有用的数据。其实现原理是,根据预先定义的
配置文件用httpclient获取页面的全部内容(关于httpclient的内容,本博有些文章已介绍),然后运用XPath、XQuery、正则表
达式等这些技术来实现对text/xml的内容筛选操作,选取精确的数据。前两年比较火的垂直搜索(比如:酷讯等)也是采用类似的原理实现的。Web-
Harvest应用,关键就是理解和定义配置文件,其他的就是考虑怎么处理数据的Java代码。当然在爬虫开始前,也可以把Java变量填充到配置文件
中,实现动态的配置。
现在以爬取天涯论坛的所有版面信息为例,介绍Web-Harvest的用法,特别是其配置文件。
天涯的版块地图页面时:http://www.tianya.cn/bbs/index.shtml
[天涯的部分版面列表]
我们的目标就是要抓取全部的版块信息,包括版块之间的父子关系。
先查看版块地图的页面源代码,寻求规律:
<div class="backrgoundcolor">
<div class="bankuai_list">
?????? <h3>社会民生</h3>
?????? <ul>
?????????????
<li><a
href="http://www.tianya.cn/publicforum/articleslist/0/free.shtml"
id="item天涯杂谈">天涯杂谈</a></li>
?????????????
<li><a
href="http://www.tianya.cn/publicforum/articleslist/0/worldlook.shtml"
id="item国际观察">国际观察</a></li>
?????????????
<li><a
href="http://www.tianya.cn/publicforum/articleslist/0/news.shtml"
id="item天涯时空">天涯时空</a></li>
?????????????
<li><a
href="http://www.tianya.cn/publicforum/articleslist/0/no06.shtml"
id="item传媒江湖">传媒江湖</a></li>
????????????? …… //省略
</ul>
</div>
<div class="clear"></div>
</div>
<div class="nobackrgoundcolor">
<div class="bankuai_list">
?????? <h3>文学读书</h3>
????????????? <ul>
????????????????????
<li><a
href="http://www.tianya.cn/techforum/articleslist/0/16.shtml"
id="item莲蓬鬼话">莲蓬鬼话</a></li>
????????????????????
<li><a
href="http://www.tianya.cn/publicforum/articleslist/0/no05.shtml"
id="item煮酒论史">煮酒论史</a></li>
????????????????????
<li><a
href="http://www.tianya.cn/publicforum/articleslist/0/culture.shtml"
id="item舞文弄墨">舞文弄墨</a></li>
???????????????????? ……. //省略
????????????? </ul>
</div>
<div class="clear"></div>
</div>
……. //省略
通过页面源码分析,发现每个大板块都是在<div class="bankuai_list"></div>的包括之下,而大板块下面的小版块都是下面的形式包含的。
<li><a href="xxx" id="xxx">xxx</a></li>,这些规律就是webharvest爬数据的规则。
下面先给出全部的配置:(tianya.xml)
<config charset="utf-8">
???????? <var-def name="start">
??????????? <html-to-xml>
?????????????????? <http url="http://www.tianya.cn/bbs/index.shtml" charset="utf-8" />
??????????? </html-to-xml>
???????? </var-def>
???????? <var-def name="ulList">
??????????? <xpath expression="//div[@class='bankuai_list']">
?????????????????? <var name="start" />
??????????? </xpath>
???????? </var-def>
??????? <file action="write" path="tianya/siteboards.xml" charset="utf-8">
?????????????? <![CDATA[ <site> ]]>
?????????????? <loop item="item" index="i">
?????????????????? <list><var name="ulList"/></list>
?????????????????? <body>
?????????????????????? <xquery>
?????????????????????????? <xq-param name="item">
??????????????????????????? <var name="item"/>
?????????????????????????? </xq-param>
?????????????????????????? <xq-expression><![CDATA[
?????????????????????????????????? declare variable $item as node() external;
?????????????????????????????????? <board boardname="{normalize-space(data($item//h3/text()))}" boardurl="">
?????????????????????????????????? {
???????????????????????????????????????? for $row in $item//li return
????????????????????????????????????????????
<board boardname="{normalize-space(data($row//a/text()))}"
boardurl="{normalize-space(data($row/a/@href))}" />
????????????????????????????????? }
????????????????????????????????? </board>
?????????????????????????? ]]></xq-expression>
?????????????????????? </xquery>
?????????????????? </body>
?????????????? </loop>
?????????????? <![CDATA[ </site> ]]>
??????? </file>
</config>
这个配置文件分为三个部分:
1.????? 定义爬虫入口:
<var-def name="start">
?? <html-to-xml>
??????? <http url="http://www.tianya.cn/bbs/index.shtml" charset="utf-8" />
????? </html-to-xml>
?? </var-def>
?????? 爬虫的入口URL是:http://www.tianya.cn/bbs/index.shtml
?????? 同时,指定了爬虫的爬数据的编码,这个编码应该根据具体的页面编码来定,例如上面的入口页面的编码就是utf-8。其实,有很多的中文页面的编码是gbk或者gb2312,那么这个地方的编码就要相应设置,否则会出现数据乱码。
2.????? 定义数据的过滤规则:
<var-def name="ulList">
??? <xpath expression="//div[@class='bankuai_list']">
??????? <var name="start" />
?????? </xpath>
</var-def>
?????? 上面配置就是根据XPath从爬得的数据中筛选合适的内容。这里需要得到所有的<div class="bankuai_list"></div>信息。有关XPath和XQuery的语法请网上查询。
3.????? 最后一步就是处理数据。可以写入XML文件,也可以使用SetContextVar的方式把收集的数据塞到一个集合变量中,供Java代码调用(比如:数据直接入库)。
这里是直接写入XML文件,然后解析XML即可。
注意下面的for循环,这是XQuery的语法,提供遍历的功能。由于大版面小版块是一个树状结构,需要这种遍历。
<board boardname="{normalize-space(data($item//h3/text()))}" boardurl="">
{
?????? for $row in $item//li return
<board boardname="{normalize-space(data($row//a/text()))}" boardurl="{normalize-space(data($row/a/@href))}" />
}
</board>
相关的Java代码如下:
String configFile="tianya.xml";
ScraperConfiguration config = newScraperConfiguration(configFile);
String targetFolder="c:\\chenxinhan";
Scraper scraper = new Scraper(config,targetFolder);
//设置爬虫代理
scraper.getHttpClientManager().setHttpProxy("218.56.64.210","8080");
scraper.setDebug(true);
scraper.execute();
上面代码执行完成后,收集的数据文件地址为:c:\henxinhan\tianya\siteboards.xml
?
转自:http://hi.baidu.com/xghrbc1001/blog/item/3e959dd36bf93bc1a8ec9a24.html