小明思考

Just a software engineer
posts - 124, comments - 36, trackbacks - 0, articles - 0
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

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

Posted on 2012-01-20 15:27 小明 阅读(1962) 评论(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(), 1null);
            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设计请参考:

评论

# re: Snaker开发笔记(1)-实现插件  回复  更多评论   

2012-01-20 21:36 by nkjava
程序挺好,只是注释写得不多

# re: Snaker开发笔记(1)-实现插件  回复  更多评论   

2012-01-23 23:13 by tb
挺好的

只有注册用户登录后才能发表评论。


网站导航: