• webmagic加上了注解支持



    今天有个网友在博客回帖,能不能用注解来写一个爬虫?想了想,因为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: "+title);
            System.out.println("content: "+content);
            System.out.println("tags: " + 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分支上,后续测试稳定后回合并到主干。

  • 相关阅读:
    加法原理和乘法原理
    布尔矩阵
    Codeforces Round #603 (Div. 2) A. Sweet Problem
    Codeforces Round #603 (Div. 2) D. Secret Passwords 并查集
    poj1611The Suspects并查集
    poj 2236 Wireless Network 并查集
    求斐波那契数的python语言实现---递归和迭代
    python语言实现阶乘的两种方法---递归和迭代
    栈实现二进制转十进制
    栈的基本操作
  • 原文地址:https://www.cnblogs.com/timssd/p/5150097.html
Copyright © 2020-2023  润新知