当前位置 博文首页 > 少年时未觉悟 ,觉悟时不再年少,还危机四伏!:Webmagic 任务 I

    少年时未觉悟 ,觉悟时不再年少,还危机四伏!:Webmagic 任务 I

    作者:[db:作者] 时间:2021-07-16 15:35

    背景

    WebMagic 是一个简单灵活的 Java 爬虫框架,基于 WebMagic,可以快速开发出高效、易维护的爬虫应用。爬虫管理器使用 Task 的 uuid 属性来关联站点和 URL ,以达到对待采集的 URL 进行去重、避免重复采集的问题。

    本文来分析 Spider 类设置爬虫任务编号、和 setScheduler 的顺序对爬虫任务的影响及使用注意事项。

    RedisScheduler 简介

    Scheduler 是 WebMagic 中进行 URL 管理的组件,一般来说,Scheduler 包括两个作用:

    1. 对待抓取的 URL 队列进行管理
    2. 对已抓取的 URL 进行去重

    WebMagic 内置了几个常用的 Scheduler,项目开发中我们都是选用支持分布式部署的 RedisScheduler ,它用 Redis 保存抓取的 URL 信息,以 Task 的 UUID 为主键,可进行多台机器同时合作抓取。

    分析 RedisScheduler 源码可以知道,为了实现管理 URL 和去重的目的,它会以任务的 UUID 为后缀存储三类信息到 Redis :

    1. 待爬 URL 队列:queue_taskUuid
    2. 历史 URL 的 Set 集合:set_taskUuid ,用于判重
    3. Request 额外信息:item_taskUuid,存储额外的 Request 信息的 set

    Spider 创建流程

    使用 Spider + RedisScheduler 的通用代码为:

       Spider spider = Spider.create(pageProcessor);
       spider.addUrl(url).setUUID(taskId)
             .addPipeline(pipeline)
             .setScheduler(new RedisScheduler(SpringUtil.getBean(JedisPool.class)))
             .setExecutorService(threadPool);
       return spider;
    

    因为 RedisScheduler 是通过认为的 uuid 为 key 来存储爬虫中间数据的,根据源码可知,在设置了调度器队列后,调度器队列数据就跟此时的 uuid 绑定了:

        /**
         * set scheduler for Spider
         *
         * @param scheduler scheduler
         * @return this
         * @see Scheduler
         * @since 0.2.1
         */
        public Spider setScheduler(Scheduler scheduler) {
            checkIfRunning();
            Scheduler oldScheduler = this.scheduler;
            this.scheduler = scheduler;
            if (oldScheduler != null) {
                Request request;
                while ((request = oldScheduler.poll(this)) != null) {
                    this.scheduler.push(request, this);
                }
            }
            return this;
        }
    

    设置调度队列时,它会将旧调度器队列中的请求数据添加到新调度队列中

    注意事项

    笔者在测试分布式爬虫的时候,在调用 SpidersetScheduler 后,希望能够分片爬取,就再次设置 Spider 的 uuid 为新值后,爬虫就会一秒中结束,下载页面数为 0 。为什么呢?

    publicSpider setUUID(String uuid) {
            this.uuid = uuid;
            return this;
        }
    

    分析源码,可以看到 setUUID 仅仅重新设置了 id ,并不会更新 Scheduler 中的请求和 task 的关联关系。

    因此需要注意:创建爬虫的流程应该遵守一定的顺序,先设置 uuid ,再设置 Scheduler,一旦固定,就不应该再改变任务编号。

    如果要修改任务编号,则也应该重新设置调度器队列更新该对应关系。

    cs