之前做过一年的爬虫,当年功力不够,写的代码都是一点一点往上加。后来看了下据说是最优秀的爬虫scrapy
的结构,山寨了一个Java版的爬虫框架webmagic
。
这个框架也分为Spider、Schedular、Downloader、Pipeline几个模块。此外有一个Selector,整合了常用的抽取技术(正则、xpath),支持链式调用以及单复数切换,因为受够了各种抽取的正则,在抽取上多下了一点功夫。
废话不多,上代码。在webmagic里直接实现PageProcessor接口,即可实现一个爬虫。例如对我的点点博客http://progressdaily.diandian.com/进行抓取:
public class DiandianBlogProcessor implements PageProcessor {
private Site site;
@Override
public void process(Page page) {
//a()表示提取链接,as()表示提取所有链接
//getHtml()返回Html对象,支持链式调用
//r()表示用正则表达式提取一条内容,rs()表示提取多条内容
//toString()表示取单条结果,toStrings()表示取多条
List<String> requests = page.getHtml().as().rs("(.*/post/.*)").toStrings();
//使用page.addTargetRequests()方法将待抓取的链接加入队列
page.addTargetRequests(requests);
//page.putField(key,value)将抽取的内容加入结果Map
//x()和xs()使用xpath进行抽取
page.putField("title", page.getHtml().x("//title").r("(.*?)\\|"));
//sc()使用readability技术直接抽取正文,对于规整的文本有比较好的抽取正确率
page.putField("content", page.getHtml().sc());
page.putField("date", page.getUrl().r("post/(\\d+-\\d+-\\d+)/"));
page.putField("id", page.getUrl().r("post/\\d+-\\d+-\\d+/(\\d+)"));
}
@Override
public Site getSite() {
//site定义抽取配置,以及开始url等
if (site == null) {
site = Site.me().setDomain("progressdaily.diandian.com").setStartUrl("http://progressdaily.diandian.com/").
setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");
}
return site;
}
}
然后实现抓取代码:
public class DiandianProcessorTest {
@Test
public void test() throws IOException {
DiandianBlogProcessor diandianBlogProcessor = new DiandianBlogProcessor();
//pipeline是抓取结束后的处理
//ftl文件放到classpath:ftl/文件夹下
//输出默认放到/data/temp/webmagic/ftl/[domain]目录下
FreemarkerPipeline pipeline = new FreemarkerPipeline("wordpress.ftl");
//Spider.me()是简化写法,其实就是new一个啦
//Spider.pipeline()设定一个pipeline,支持设置多个pipeline,多个pipeline会进行链式调用
//FileCacheQueueSchedular保存url,支持断点续传,临时文件输出到/data/temp/webmagic/cache目录
//Spider.run()执行
Spider.me().pipeline(pipeline).schedular(new FileCacheQueueSchedular(diaoyuwengProcessor.getSite(), "/data/temp/webmagic/cache/")).
processor(diaoyuwengProcessor).run();
}
}
跑一遍之后,将所有输出的文件,合并到一起,并加上wp的头尾,就是wordpress-backup.xml了!
代码已开源https://github.com/code4craft/webmagic<strike>有什么邪恶用途你懂的…</strike>