2012年3月15日 星期四

使用網路爬蟲(Crawler)擷取網頁資料:以 niocchi 為例

這個標題寫得很像論文的標題 XD
不過總之目標是要抓網頁內容下來。

Open Source 的 Web Crawler 可以參考 [1]
網路上比較多人使用的好像是 Heritrix,不過我看了一下他的資料還是不太會用 XD
Crawler4j 原本要使用,但後來也不知道怎麼用,所以又繼續 survey 了
最後我選擇的是 niocchi....原因嘛...其實沒什麼特別的原因 XD
主要優點大概是它號稱使用 NIO 來進行 crawling,還有它最後更新時間是 2011 年!XD

niocchi 官方網站可參考 [2]。

不過 niocchi 老實說網路上資源不多,而且沒有 document 可以看...
但下載回來的 source code 裡面有包含簡單的範例就是了
要進階的需求就要慢慢自己研究要怎麼使用了。
我這邊的需求就是我把 URL 加到列表裡以後,爬蟲要自己幫我爬下來
預定是要把爬下來的資料直接做 HTML 分析,然後直接就進行資料儲存
不會透過 FileWriter 之類的把爬下來的東西寫到磁碟上。
但剛開始還是先把它寫出來才方便確認爬下來的資料是否正確 XD

niocchi 的結構可以參考官網上的圖:


圖中右下角的 Worker 是用來處理爬下來的資料的
所以每爬完一個網頁,Worker 都會被觸發去進行資料處理
當然要把 HTML 寫進檔案也是在這裡處理了。
以下先給個簡單的 Worker 範例:

public class MyWorker extends Worker{
  private String tempararyPath = null;

  public MyWorker (Crawler crawler, String path) {
    super(crawler);
    this.tempararyPath = path;
  }

  @Override
  public void processResource(Query query) {
    DiskResource resource = (DiskResource) query.getResource();
    // 指定要把 HTML 寫在哪個檔案,這裡檔名是用當前時間命名
    File savedFile = new File(this.tempararyPath + Calendar.getInstance().getTimeInMillis());
    // 檢查檔名是否與其他檔案重複,若有重複就等待 0.1 秒後再嘗試
    while (savedFile.exists()) {
      try {
        Thread.sleep(100);
        savedFile = new File(this.tempararyPath + Calendar.getInstance().getTimeInMillis());
      } catch (InterruptedException e) {}
    }
    
    if(resource.getBodyLength() > 0) {
      try {
        // 將擷取下來的 Resource 寫入指定的檔案
        resource.save(savedFile.getAbsolutePath());
      } catch (IOException e) {
        System.out.println("Cannot save resource: " + e.getMessage());
      }
    }
  }
}

接著是爬網頁的動作:

public class CrawlObject {
  public void startCrawling () {
    LogMessage.postLog(LogLevel.DEBUG, "Initialized");
    
    try {
      Crawler crawler = new Crawler(new GenericResourceFactory(), 1) ;
      crawler.setUserAgent("firefox 9") ;
      crawler.setTimeout( 30000 ) ;

      // 初始化 UrlPool,指定有哪些 URL 要讓 Crawler 去爬
      LinkedList<String> list = new LinkedList<String>();
      list.add("http://tw.yahoo.com"); // 指定要爬的 URL
      URLPool urlPool = new TimeoutURLPool( new SimpleListURLPool(list.iterator()));

      // 初始化 Worker,指定爬下來的 Resource 要如何處理
      Worker worker = new MyWorker(crawler, "/home/TOMCAT/download/");
      // 啟動 Worker
      worker.start();
      // 啟動 Crawler
      crawler.run(urlPool);
      // 讓主程序等待 Crawler 的執行緒執行結束
      worker.join();
    } catch (IOException e) {
      e.printStackTrace();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

然後主程式去執行 CrawlObject.startCrawling() 就可以爬了
爬下來的網頁會存放在 /home/TOMCAT/download 資料夾裡
而且同樣的程式碼在 Windows 底下依然可以運作 XD
只是檔案在我的 eclipse 上會存到 D:\home\TOMCAT\download


參考資料:
1、Java-Source.net
2、http://www.niocchi.com/

1 則留言:

YC 提到...

想問有詳細的步驟嗎??我最近才剛學eclipse