golang实现并发爬虫二(简单调度器)

上篇文章当中实现了单任务版爬虫。

那么这篇文章就大概说下,如何在上一个版本中进行升级改造,使之成为一个多任务版本的爬虫。加快我们爬取的速度。

话不多说,先看图:

 

其实呢,实现方法就是加了一个scheduler的模块,所有的request都由scheduler去交给worker。

另外呢,这里的worker,也就是上文提到过的fetcher和parser的一个过程。

worker的数量由我们自己在调用engine的时候传入。

每一个worker都是一个groutine。这样可以加快抓取速度,尤其是fetcher那块的。代码如下:

func createWorker(in chan Request, out chan ParseResult) {
    go func() {
        for {
            request := <-in
            res, err := Worker(request)
            if err != nil {
                continue
            }
            out <- res
        }
    }()
}

 

这里的关键呢,就在于scheduler如何分配。

第一种方案是来一个request就给到workChan。

func (s *SimpleScheduler) Submit(r simple_con_engine.Request) {    
    s.workChan <- r
}

但是,这种方案是不行的。

因为worker的速度太快,而这个给到workChan的速度太慢,会导致卡死。

那么,解决办法可以是每来一个request就都开一个groutine,就可以解决这个事情了。代码也就是这样了:

func (s *SimpleScheduler) Submit(r simple_con_engine.Request) {
    go func() { s.workChan <- r }()    
}

 

scheduler做的事情也就是这样了:

 

 

这个就可以并发的去执行爬虫的任务了,通过这个scheduler的调度。

经测当workerCount为1时,其实也就相当于是单任务版爬虫为30秒爬取了2046条数据。

当workerCount为10时,这个使用了简单调度器的爬虫为30秒爬取了25505条数据,实际效率不止增加了10倍

 

 

这个使用scheduler去实现简单调度器的并发版爬虫的源码可有:

有。

https://github.com/anmutu/du_crawler/tree/master/03crawler

 

那么,这个多任务版本的爬虫有什么缺点吗:

有。

当engine给到scheduler的每一个request的时候就会创建一个groutine,这个避免dead lock,但是就会创建无数个groutine,我们的控制力度就小了好多。

 

posted @ 2020-04-19 21:58  公子若不胖天下谁胖  阅读(687)  评论(0编辑  收藏  举报