Webmagic源码分析之运行流程

    Webmagic是Java中的一个爬虫开源框架,主要有四大核心组件,分别是:Downloader、PageProcessor、Scheduler、Pipeline,并有Spider进行管理。这四个组件分别对应了爬虫生命周期中的下载、处理、管理、持久化。同时还支持XPath、Jsoup、CSS选择器,方便我们对抓取的页面进行解析。

    Webmagic的源码可以从github上pull下来:https://github.com/code4craft/webmagic

    Webmagic的入门文档可以查看:http://webmagic.io/docs/zh/

    以下是一张从文档中截下来的Webmagic架构图:

     

    接下来将会以Webmagic中的一个例子,来跟踪一下webmagic运行流程的源码。这个例子位于webmagic-core这个核心模块中的us.codecraft.webmagic.processor.example包下,类名为GithubRepoPageProcessor,这是一个关于Github爬虫的代码。

    首先从main函数入手,它创建了一个Spider对象,GithubRepoPageProcessor对象是对抓去结果进行解析的类。addUrl() 函数可以添加我们需要爬去的连接,这个函数的参数是可变的,可以传入多个URL并使用逗号隔开。thread() 函数用于设置Spider线程的数量,表明抓取时启动的线程数,支持多线程并发抓取。run方法用于启动Spider,因为Spider类实现了Runnable接口。这里也可以调用Spider的start()方法用于启动Spider。

    public static void main(String[] args) {
        Spider.create(new GithubRepoPageProcessor()).addUrl("https://github.com/code4craft").thread(5).run();
    }
    thread()函数中首先会调用checkIfRunning()函数来检查Spider的运行状态,如果状态为已运行,那么将会抛出异常。在Spider类中定义了三个常量来表示爬虫的运行状态,分别是初始化、运行、停止。第三行中将参数复制给类变量,用于保存爬虫的线程数。

    public Spider thread(int threadNum) {
        checkIfRunning();
        this.threadNum = threadNum;
        if (threadNum <= 0) {
            throw new IllegalArgumentException("threadNum should be more than one!");
        }
        return this;
    }
    protected void checkIfRunning() {
        if (stat.get() == STAT_RUNNING) {
            throw new IllegalStateException("Spider is already running!");
        }
    }

    由上面checkIfRunning函数中可以看待,stat用来保存爬虫的状态,从它的定义中,我发现它的类型是AtomicInteger,这是JDK1.5之后,在java.util.concurrent.atomic包下新增的原子处理类,主要用于在多线程环境下保证数据操作的准确性,能保证并发访问下的线程安全。

    protected AtomicInteger stat = new AtomicInteger(STAT_INIT);

    protected final static int STAT_INIT = 0;

    protected final static int STAT_RUNNING = 1;

    protected final static int STAT_STOPPED = 2;

    接下来我们来看看run方法的运行流程,当线程启动时,就会调用run方法。第3行调用函数用于检测Spider的状态,第4行的函数用于初始化爬虫的一些组件,这些组件我们可以在创建Spider的时候进行设置,如果没有设置,那么该函数会使用默认的组件进行初始化,其中也包含了对线程池的初始化。

    第6行中用while循环,判断如果当前线程不中断,且Spider的状态为运行状态,也就是在checkRunningStat()方法中成功设置成了运行状态,那么就开始执行爬虫。第7行先从请求队列中拿出一个请求,Scheduler是用于管理爬虫请求的类,如果没有指定,Spider默认使用的是QueueScheduler,即基于内存的队列,其内部的数据结构是使用一个LinkedBlockingQueue来存放我们要爬取的请求。

    当从队列中取出的请求为null,则判断如果线程池的活跃线程数为0,且exitWhenComplete设置为了true,那么就退出while循环。exitWhenComplete是一个boolean类型的值,表示当没有新的爬虫请求时,是否退出。否则的话,将执行waitNewUrl()等待新的请求被加入队列,再继续执行。

    当Request不为null,则执行到第16行,创建一个匿名内部类,实现Runnable()接口,并添加到线程池中去执行。第20行,调用processRequest()函数,将会创建HttpClient去执行请求,并抓取界面进行解析等一系列操作。如果这个过程中没有发生异常,那么一次爬虫的生命周期就成功了,此时会执行第21行onSuccess()。这里涉及到了为Spider添加一个爬虫的监听器,当爬虫执行成功时,在onSuccess()中就会调用这个监听器中的onSucc

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值