Posted on 2012-01-20 15:27
小明 閱讀(1977)
評論(2) 編輯 收藏 所屬分類:
開發日志
程序員的核心價值是創造有用的軟件。
----------小明
背景我有時會去特定的網站去下載一些資料,比如去englishpod.com去下載英語聽力資料,或者去某論壇下載美女貼圖:-),但是通用的爬蟲無法滿足需求,一來很多網站需要登錄才能下載,另外我也不想下載不需要的東西,只想下載特定的內容,所以我只能寫一些小程序來去下載。這樣的小程序寫了幾個,重復的部分很多,所以能不能寫一個通用的平臺,讓寫類似的程序更簡單?于是有了現在這個開源項目Snaker:
http://code.google.com/p/ssnaker/
插件設計我的目標之一,是讓寫特定的爬蟲更簡單,一個想法是做成插件式的。有幾個需求:
1. 很容易添加插件
2. 很容易修改插件,不需要重啟程序
3. 特定網站的邏輯都應該在插件中,framework只包含通用部分。
所以插件最好是用一種腳本語言來書寫。平臺層我使用Java來開發,插件腳本我決定用javascript來編寫。為什么用javascript?主要是受到nodejs和greasemonkey的啟發,尤其是greasemonkey那種javascript插件的方式,我覺得非常不錯。
Java和JavaScript的互動我選擇了mozilla的rhino庫來實現腳本的執行。
Java調用Javascript腳本比較簡單:
Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();
Script script = cx.compileString(sourceCode, engine.getName(), 1, null);
script.exec(cx, scope);
} finally {
Context.exit();
}
因為javascript本身并沒有網絡下載的功能,所以我要定義一些方法,讓javascript可以調用java的方法來實現下載,這稱為Host object。具體的方法請參見rhino的官方文檔,我這里貼出一小段code。
下面這個類定義了一個sleep的方法。
Java:
public class JsHelper extends NativeObject {
public JsHelper() {
}
@Override
public String getClassName() {
return "JsHelper";
}
public void jsFunction_sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
logger.error("interrupted",e);
}
}
}
Scriptable tx = cx.newObject(scope, "JsHelper");
scope.put("$", scope, tx);
這樣就可以在javascript中調用了:
$.sleep(1000);
更多的Snaker API設計請參考: