Web-Harvest是一個Java開源Web數(shù)據(jù)抽取工具。它能夠收集指定的Web頁面并從這些頁面中提取有用的數(shù)據(jù)。其實現(xiàn)原理是,根據(jù)預先定義的配置文件用httpclient獲取頁面的全部內(nèi)容(關于httpclient的內(nèi)容,本博有些文章已介紹),然后運用XPath、XQuery、正則表達式等這些技術(shù)來實現(xiàn)對text/xml的內(nèi)容篩選操作,選取精確的數(shù)據(jù)。前兩年比較火的垂直搜索(比如:酷訊等)也是采用類似的原理實現(xiàn)的。Web-Harvest應用,關鍵就是理解和定義配置文件,其他的就是考慮怎么處理數(shù)據(jù)的Java代碼。當然在爬蟲開始前,也可以把Java變量填充到配置文件中,實現(xiàn)動態(tài)的配置。
(友情提示:本博文章歡迎轉(zhuǎn)載,但請注明出處:陳新漢,http://www.tkk7.com/hankchen)
現(xiàn)在以爬取天涯論壇的所有版面信息為例,介紹Web-Harvest的用法,特別是其配置文件。
天涯的版塊地圖頁面時:http://www.tianya.cn/bbs/index.shtml
[天涯的部分版面列表]
我們的目標就是要抓取全部的版塊信息,包括版塊之間的父子關系。
先查看版塊地圖的頁面源代碼,尋求規(guī)律:
<div class="backrgoundcolor">
<div class="bankuai_list">
<h3>社會民生</h3>
<ul>
<li><a id="item天涯雜談">天涯雜談</a></li>
<li><a id="item國際觀察">國際觀察</a></li>
<li><a id="item天涯時空">天涯時空</a></li>
<li><a id="item傳媒江湖">傳媒江湖</a></li>
…… //省略
</ul>
</div>
<div class="clear"></div>
</div>
<div class="nobackrgoundcolor">
<div class="bankuai_list">
<h3>文學讀書</h3>
<ul>
<li><a id="item蓮蓬鬼話">蓮蓬鬼話</a></li>
<li><a id="item煮酒論史">煮酒論史</a></li>
<li><a id="item舞文弄墨">舞文弄墨</a></li>
……. //省略
</ul>
</div>
<div class="clear"></div>
</div>
……. //省略
通過頁面源碼分析,發(fā)現(xiàn)每個大板塊都是在<div class="bankuai_list"></div>的包括之下,而大板塊下面的小版塊都是下面的形式包含的。
<li><a href="xxx" id="xxx">xxx</a></li>,這些規(guī)律就是webharvest爬數(shù)據(jù)的規(guī)則。
下面先給出全部的配置:(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="http://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
同時,指定了爬蟲的爬數(shù)據(jù)的編碼,這個編碼應該根據(jù)具體的頁面編碼來定,例如上面的入口頁面的編碼就是utf-8。其實,有很多的中文頁面的編碼是gbk或者gb2312,那么這個地方的編碼就要相應設置,否則會出現(xiàn)數(shù)據(jù)亂碼。
2. 定義數(shù)據(jù)的過濾規(guī)則:
<var-def name="ulList">
<xpath expression="http://div[@class='bankuai_list']">
<var name="start" />
</xpath>
</var-def>
上面配置就是根據(jù)XPath從爬得的數(shù)據(jù)中篩選合適的內(nèi)容。這里需要得到所有的<div class="bankuai_list"></div>信息。有關XPath和XQuery的語法請網(wǎng)上查詢。
3. 最后一步就是處理數(shù)據(jù)??梢詫懭?/span>XML文件,也可以使用SetContextVar的方式把收集的數(shù)據(jù)塞到一個集合變量中,供Java代碼調(diào)用(比如:數(shù)據(jù)直接入庫)。
這里是直接寫入XML文件,然后解析XML即可。
注意下面的for循環(huán),這是XQuery的語法,提供遍歷的功能。由于大版面小版塊是一個樹狀結(jié)構(gòu),需要這種遍歷。
<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代碼如下:
/**
* Copyright(C):2009
* @author陳新漢
* Sep4,20093:24:58PM
*/
String configFile="tianya.xml";
ScraperConfiguration config = new ScraperConfiguration(configFile);
String targetFolder="c:\\chenxinhan";
Scraper scraper = new Scraper(config,targetFolder);
//設置爬蟲代理
scraper.getHttpClientManager().setHttpProxy("218.56.64.210","8080");
scraper.setDebug(true);
scraper.execute();
上面代碼執(zhí)行完成后,收集的數(shù)據(jù)文件地址為:c:\chenxinhan\tianya\siteboards.xml
友情提示:本博文章歡迎轉(zhuǎn)載,但請注明出處:陳新漢,http://www.tkk7.com/hankchen