Crawler4j的使用
(以下內容全部為轉載,供自己查閱用)
下載地址:
http://code.google.com/p/crawler4j/
Crawler4j的使用
網上對於crawler4j這個爬蟲的使用的文章很少,Google到的幾乎沒有,只能自己根據crawler4j的源碼進行修改。這個爬蟲最大的特點就是簡單易用,他連API都不提供。剛開始的時候實在恨不能適應。好在他的源碼也提供了幾個例子。對於一般的應用大可以直接修改它的例子。
使用方法很簡單,直接用Eclipse打開工程。可以看到src下有三個demo例子。說一下最簡單的simple例子。
使用crawler4j的關鍵的繼承WebCrawler類實現自己的爬蟲類MyCrawler,然后根據需要覆蓋WebCrawler的幾個函數就可以了。
public boolean shouldVisit(WebURL url) // 根據url進行網頁的解析,對返回為TRUE的網頁進行抓取。
public void visit(Page page) // 解析網頁內容,page類包含了豐富的方法,可以利用這些方法得到網頁的內容和屬性。
Crawler包
Crawler.CrawController 控制爬蟲,先addseed,再開啟多個爬蟲,並不斷監聽各個爬蟲存活狀態。
Crawler.WebCrawler 爬蟲
1. Run():不斷循環,每次從Frontier拿50條url,對每條url,processPage(curUrl)。
2. processPage(curURL):用PageFetcher.fetch爬取網頁,如果curURL有redirect,則將redirect url的url加入Frontier,以后再調度;如果爬取正常,則先進行parse,生成Page,將新urls降入Frontier(新加入url的深度此時確定),調用visit(Page){用戶自定義操作}。
Crawler.Configurations 讀取crawler4j.properties中的信息
Crawler.PageFetcher 啟動IdleConnectionMonitorThread,用fetch(Page, ignoreIfBinary),爬取單個Page頁面。是一個static類。
Crawler.Page 一個頁面
Crawler.PageFetchStatus 單個頁面爬取的配置,如返回爬取狀態數字所代表的含義等等。
Crawler.HTMLParser 對HTML源碼進行parse,存入Page中。
Crawler.LinkExtractor 抽取出一個HTML頁面中包含的所有link。
Crawler.IdleConnectionMonitorThread 用來監聽連接器(用來發送get請求,獲取頁面),其connMgr則負責HTML請求的發送。
url包
url.WebURL 代表一條url,內含docid, depth, url值
url.URLCanonicalizer 將url進行normalize
Frontier包
Frontier.Frontier
Init() 如果resumable,則從env所指home中讀取已處理過得urls,scheduleAll加入調度workQueue中。
Frontier.workQueues 要處理的頁面集,如果resumable,在構造時會打開對應env中的database(PendingURLsDB),獲取上一次遺留的未處理的urls。
Frontier.inprocessPages 當前正在處理的頁面集,繼承workQueues,存入InProcessPagesDB數據庫。
Frontier.DocIDServer 對應數據庫DocIDs,記錄已經見過的頁面url。
處理流程:newurl--->workQueues--->inprovessPages--->delete
Robotstxt包,用來判斷url是否被允許。
Util包,用來提供一些小工具。
注意點:
1. seed頁面深度為0。
2. url去重利用的是DocIDServer.newdocid(url),如果該值大於0,則表示該url以前見過。通過這個機制,所有以前見過的頁面都可以被記錄識別。
3. 當設定resumable后,程序跑完后就會把PendingURLsDB和DocIDs保存下來。
4. 如果不設定resumable,在運行程序前,會把env對應的home目錄清空。
------------------------------------------------------------------------------
由於最近做實驗需要使用到大量的新聞語料庫,在網上找了一些都不是自己想要的,所以決定自己寫個小程序去爬取New York Times(NYT)上的網頁新聞。
用Java寫的爬蟲程序有很多,我找了一個叫crawler4j的開源爬蟲,這是一個多線程的爬蟲,功能比較簡單,源代碼也比較容易看懂,由於我要對爬蟲爬取鏈接進行一些修改,就直接下了crawler4j的源碼加到我自己的工程中。
然后對爬下來的網頁進行處理,使用的是htmlparser這個工具,得到了我要的新聞的Title、Publication Time、Discription、正文等信息。為了更好的組織這些信息,我把這些信息存儲到XML文檔中。
花了兩個晚上的時間,爬蟲程序可以跑起來了,寫程序的時候遇到了幾個問題。
1. 在xml中是使用 "\n" 來表示換行的,而在windows中是使用 "\r\n" 來表示換行符的,所以你要是把含有換行符的文本保存到xml文檔時他會自動的把 "\r" 轉換成轉義符 "& #13;" ,要處理掉這個的話,你可以直接把文本里的 "\r" 給刪了就行了。
2. 使用Java中的String.replaceAll(regex, replacement)這個函數時又犯了一個很低級的錯誤,就是如果執行str.replaceAll(regex, replacement) 時並沒有改變str本身的值,所以說要替換str自身的某些字符串時需要執行 str=str.replaceAll(regex, replacement) ,沒有意識的這個問題的后果就是花了很長時間在糾結我的程序哪兒出問題了,已經是第二次犯這個錯誤了,以后不能再犯了啊。
3. 爬取國外的網站資源太慢了,程序開了兩個小時左右才爬取了3000篇新聞,慢的可憐啊,希望多開幾個線程看看能不能提升一點效果,要是是由於網速的原因的話,可能效果不大。
----------------------------------------------------------------------------
Crawler4j的退出問題
這個問題在網上找了好久也沒有好的解決方案,網上的說法是這個爬蟲只支持手動強制關閉。無奈只能自己看他的源代碼,好在他的源代碼也不多。目前的解決方案是。。。直接上代碼吧
一、edu.uci.ics.crawler4j.crawler.CrawlController類
public CrawlController(String storageFolder) throws Exception {
。。。
// 新建一個監控線程,不知管什么用
// PageFetcher.startConnectionMonitorThread();
}
public <T extends WebCrawler> void start(Class<T> _c, int numberOfCrawlers) {
。。。
// 設置停止標志
sign_stop = false;
while (true) {
。。。
}
// 停止線程
if(sign_stop){
for (int i = 0; i < crawlers.size(); i++) {
crawlers.get(i).setStop(true);
}
return;
}
if (!someoneIsWorking) {
。。。
}
public void stop() {
sign_stop = true;
}
二、edu.uci.ics.crawler4j.crawler.WebCrawler類
// 停止標志
private boolean stop;
public void run() {
onStart();
stop = false;
while (!stop) {
。。。
}
}