欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(五)Scrapy的抓取流程——Scheduler

程序员文章站 2022-04-11 08:02:45
...

在Engine中,是通过Engine实例化的slot对象进行对scheduler对象的初始化,和任务状态的记录。

# engine.py中ExecutionEngine的crawl方法
def crawl(self, request, spider):
    assert spider in self.open_spiders, \
        "Spider %r not opened when crawling: %s" % (spider.name, request)
    self.schedule(request, spider)
    self.slot.nextcall.schedule()# 这里的schedule调用的是_next_request方法
                                # _next_request中调用_next_request_from_scheduler,取出request并下载
    
# engine.py中ExecutionEngine的schedule方法
def schedule(self, request, spider):
    self.signals.send_catch_log(signal=signals.request_scheduled,
            request=request, spider=spider)
    if not self.slot.scheduler.enqueue_request(request):
        self.signals.send_catch_log(signal=signals.request_dropped,
                                    request=request, spider=spider)

Scheduler的功能就是对请求的调度,包括过滤,请求的入队和出队操作。也正是因为原始Scheduler是基于内存的调度,所以并不支持分布式。而request请求就是通过enqueue_request方法进入调度器的调度队列。

在engine中,scheduler进行了from_crawler的初始化和open。

(1)from_crawler
通过load_project方法导入配置文件中指定的scheduler类,调用类方法from_crawler定义了过滤器和队列返回新生成的scheduler实例。
(五)Scrapy的抓取流程——Scheduler
在默认设置文件里可以看到这些队列默认使用什么类。memory是基于内存的deque,disk则是通过文件进行存储,优先级队列是直接使用自带的queuelib中的PriorityQueue实现。

SCHEDULER = 'scrapy.core.scheduler.Scheduler'
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleLifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.LifoMemoryQueue'
SCHEDULER_PRIORITY_QUEUE = 'queuelib.PriorityQueue'

(2)open
open方法中对队列进行了初始化,self.mqs是优先级队列对象基于内存,self.dqs是基于文件的队列。然后会开启调度器的过滤器(这儿注释可以返回一个deferred对象,无具体实现)。
(五)Scrapy的抓取流程——Scheduler

(3)enqueue_request
本章最开始engine.py中ExecutionEngine的schedule方法就对enqueue_request进行了调用。经过过滤条件后,将request放入scheduler的队列中。
(五)Scrapy的抓取流程——Scheduler

(4)next_request
最开始的代码块中提到的engine中的_next_request_from_scheduler就是调用该方法,从队列中取出request
(五)Scrapy的抓取流程——Scheduler
在取出request之后,下一步就是对请求的下载。
(五)Scrapy的抓取流程——Scheduler