Snaker开发笔记(1)-实现插件

程序员的核心价值是创造有用的软件。
                         ----------小明

背景
我有时会去特定的网站去下载一些资料,比如去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设计请参考:

http://code.google.com/p/ssnaker/wiki/HowToWriteCrawlerEngineScript


你可能感兴趣的:(Snaker开发笔记(1)-实现插件)