今天有个网友在博客回帖,能不能用注解来写一个爬虫?想了想,因为Javaer总习惯结果有个对象Model(我在自己用的时候也是这样),ResultItems的key-value形式难免会有点麻烦,何不将抽取和Model合为一体呢?好了!现在爬osc博客只有这点代码了!而且这个对象本身是可以继续使用的!

@TargetUrl("http://my.oschina.net/flashsword/blog/*")
public class OschinaBlog {

@ExtractBy("//title")
    private String title;

@ExtractBy(value = "div.BlogContent",type = Fetcher.Type.Css)
    private String content;

@ExtractBy(value = "//div[@class='BlogTags']/a/text()", multi = true)
    private List<String> tags;

}

这里这个TargetUrl有两个意思:一个是符合这个url的交由这个Page处理,另一个是符合这样的url都会被抓取。怎么样?是不是很巧妙?另外为了方便,这里使用了类似正则的通配符形式(其实最终会编译成正则,只不过把”.“转义成了”\.“)。

考虑到一些更复杂的情况,例如:一个页面可能对应多个实体类(列表页视图),后面又做了一些更新,比如下面是一段抽取oschina问答的所有回答的代码:

@TargetUrl("http://www.oschina.net/question/\\d+_\\d+*")
@HelpUrl("http://www.oschina.net/question/*")
@ExtractBy(value = "//ul[@class='list']/li[@class='Answer']", multi = true)
public class OschinaAnswer{

@ExtractBy("//img/@title")
    private String user;

@ExtractBy("//div[@class='detail']")
    private String content;

public static void main(String[] args) {
        OOSpider.create(Site.me().addStartUrl("http://www.oschina.net/question/567527_120597"), OschinaAnswer.class).run();
    }
}

咦?当自己写完这堆处理代码的时候,才发现webmagic完全变成了Spiderman的一个注解版本。再看了一下Spiderman的sample,人家还内置了一套表达式引擎!

没关系,回到设计的初衷上来。Spiderman的设计是一个All-in-one的框架,提倡不写代码;而webmagic则是一个easy to build-in的框架,目标就是用代码实现爬虫,只不过少写点代码。不支持表达式引擎?没关系!复杂的逻辑,咱们可以写代码嘛!于是很简单的定义了一个AfterExtractor接口,在抽取完后,会调用这个接口:

@TargetUrl("http://my.oschina.net/flashsword/blog/*")
public class OschinaBlog implements AfterExtractor {

@ExtractBy("//title")
    private String title;

@ExtractBy(value = "div.BlogContent", type = ExtractBy.Type.Css)
    private String content;

@ExtractBy(value = "//div[@class='BlogTags']/a/text()", multi = true)
    private List<String> tags;

@Override
    public void afterProcess(Page page) {
        System.out.println("title:\t"+title);
        System.out.println("content:\t"+content);
        System.out.println("tags:\t" + tags);
    }

public static void main(String[] args) {
        OOSpider.create(Site.me().addStartUrl("http://my.oschina.net/flashsword/blog/145796"), OschinaBlog.class).run();
    }
}

public void afterProcess(Page page) 这个函数能做PageProcessor所有能做的事情。我想这段代码也不用咱说明了吧。个人还是比较满意的。

使用这个方式,结合JFinal,轻易实现了结果持久化到数据库的任务,代码:http://www.oschina.net/code/snippet_190591_23456。

值得一提的是,以上代码都没有修改底层的核心模块划分,以前手写PageProcessor的方式依然是有效的。看来一个良好的前期规划是很有必要的!

代码目前在https://github.com/code4craft/webmagic annotation分支上,后续测试稳定后回合并到主干。

webmagic加上了注解支持的更多相关文章

  1. webmagic学习-使用注解编写爬虫

    写在前面: 官方文档:http://webmagic.io/docs/zh/posts/ch5-annotation/README.html WebMagic支持使用独有的注解风格编写一个爬虫,引入w ...

  2. 启用Servlet 3.0新特性——注解支持

    Servlet 3.0版本新增注解支持,可是在实际使用中,添加的注解总是不起作用.经过检查,原来是“web.xml”文件的顶级标签“<web-app/>”中的一个叫做“metadata-c ...

  3. Android注解支持(Support Annotations)

    注解支持(Support Annotations) Android support library从19.1版本开始引入了一个新的注解库,它包含很多有用的元注解,你能用它们修饰你的代码,帮助你发现bu ...

  4. Android注解支持(Support Annotations) (转)

    原文地址:http://www.flysnow.org/2015/08/13/android-tech-docs-support-annotations.html 注解支持(Support Annot ...

  5. Android注解支持Support Annotations详解

    ###注解支持(Support Annotations)Android support library从19.1版本开始引入了一个新的注解库,它包含很多有用的元注解,你能用它们修饰你的代码,帮助你发现 ...

  6. [Android]AndroidBucket增加碎片SubLayout功能及AISubLayout的注解支持

    以下内容为原创,转载请注明: 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3709957.html 之前写过一篇博客,是使用Fragment来实现T ...

  7. spring注解支持

    Spring基于注解实现Bean定义支持如下三种注解: Spring自带的@Component注解及扩展@Repository.@Service.@Controller JSR-250 1.1版本中中 ...

  8. 分布式限流组件-基于Redis的注解支持的Ratelimiter

    原文:https://juejin.im/entry/5bd491c85188255ac2629bef?utm_source=coffeephp.com 在分布式领域,我们难免会遇到并发量突增,对后端 ...

  9. centos下安装ffmpeg加上fdk-aac的支持

    本文参考自:https://blog.csdn.net/jklinux/article/details/72367829 安装包可以从这里下载https://download.csdn.net/dow ...

随机推荐

  1. mysql备份数据库几种方法

    方法一 cmd 到mysql bin文件夹下用 例如以下命令 mysqldump --opt -h192.168.0.156 -uusername -ppassword --skip-lock-tab ...

  2. CodeForces Round #173 (282E) - Sausage Maximization 字典树

    练习赛的时候这道题死活超时....想到了高位确定后..低位不能对高位产生影响..并且高位要尽可能的为1..就是想不出比较好的方法了实现... 围观大神博客..http://www.cnblogs.co ...

  3. MVCC浅析(转)

    在并发读写数据库时,读操作可能会不一致的数据(脏读).为了避免这种情况,需要实现数据库的并发访问控制,最简单的方式就是加锁访问.由于,加锁会将读写操作串行化,所以不会出现不一致的状态.但是,读操作会被 ...

  4. hdu1503

    #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #inc ...

  5. iOS进阶面试题----经典10道

    OneV‘s Den在博客里出了10道iOS面试题,用他的话是:"列出了十个应聘Leader级别的高级Cocoa/CocoaTouch开发工程师所应该掌握和理解的技术" .  在这 ...

  6. java web解决表单重复提交问题

    我们大家再进行web开发的时候,必不可少会遇见表单重复提交问题.今天就来给总结如何解决表单提交问题,欢迎大家交流指正. 首先我们在讨论如何解决表单重复提交问题之前先来解决三个问题:1.什么叫表单重复提 ...

  7. 使用boost io_service时,需要注意的东西

    boost::asio 在创建io_service时,可以指定线程数,如果没有指定,默认是一个线程,也就是io_service run的那个线程,如果没有任务运行,该线程会退出. 如果在创建的时候指定 ...

  8. [置顶] js中如何复制一个对象,如何获取所有属性和属性对应的值

    在js中如何复制一个对象,例如如下一个js对象. 如果知道这个对象的所有属性自然就可以重新new一个,然后对每个属性赋值,就可以做到,但如果不知道呢?如何创建一个内容相同 的对象呢? var obj= ...

  9. VC++笔记七

    动态链接库修改文件名问题? eg:GetRadarFS.dll->RadarModel.dll; 注意修改:打开文件GetRadarFs.def 修改 LIBRARY  "GetRad ...

  10. Ubuntu 14.04LTS Gnome GUI初体验及163更新源配制

    Ubuntu 14.04 LTS于前天(2014.4.17)公布, 我今天将我的系统升级到最新, 体验了下最新的UI系统. 我选择了Ubuntu Gnome 的GUI界面.我曾经的系统是12.04lt ...