ExecutionEngine执行引擎

上一篇分析了CrawlerProcess和Crawler对象的建立过程,在最终调用CrawlerProcess.start()之前,会首先建立ExecutionEngine执行引擎,执行其open_spider和start方法。

ExecutionEngine.open_spiders()

scrapy/core/engine.py#ExecutionEngine:

    @defer.inlineCallbacks
def open_spider(self, spider, start_requests=(), close_if_idle=True):
assert self.has_capacity(), "No free spider slot when opening %r" % \
spider.name
logger.info("Spider opened", extra={'spider': spider})
nextcall = CallLaterOnce(self._next_request, spider)
scheduler = self.scheduler_cls.from_crawler(self.crawler)
start_requests = yield self.scraper.spidermw.process_start_requests(start_requests, spider)
slot = Slot(start_requests, close_if_idle, nextcall, scheduler)
self.slot = slot
self.spider = spider
yield scheduler.open(spider)
yield self.scraper.open_spider(spider)
self.crawler.stats.open_spider(spider)
yield self.signals.send_catch_log_deferred(signals.spider_opened, spider=spider)
slot.nextcall.schedule()
slot.heartbeat.start(5)

首先是nextcall = CallLaterOnce(self._next_request, spider),nextcall在后面注册到Slot对象里:
scrapy/utils/reactor.py#CallLaterOnce:

class CallLaterOnce(object):
def __init__(self, func, *a, **kw):
self._func = func
self._a = a
self._kw = kw
self._call = None
def schedule(self, delay=0):
if self._call is None:
self._call = reactor.callLater(delay, self)
def cancel(self):
if self._call:
self._call.cancel()
def __call__(self):
self._call = None
return self._func(*self._a, **self._kw)

scrapy/utils/reactor.py#Slot:

class Slot(object):
def __init__(self, start_requests, close_if_idle, nextcall, scheduler):
self.closing = False
self.inprogress = set() # requests in progress
self.start_requests = iter(start_requests)
self.close_if_idle = close_if_idle
self.nextcall = nextcall
self.scheduler = scheduler
self.heartbeat = task.LoopingCall(nextcall.schedule)

CallLaterOnce与Slot的共同作用是:
slot代表一次nextcall的执行,实际上就是执行一次engine的_next_request。slot创建了一个hearbeat,即为一个心跳。通过twisted的task.LoopingCall实现。
每隔5s执行一次,尝试处理一个新的request,这属于被动执行。后面还会有主动执行的代码。
slot可以理解为一个request的生命周期。

继续看ExecutionEngine里的代码:

scheduler = self.scheduler_cls.from_crawler(self.crawler)
start_requests = yield self.scraper.spidermw.process_start_requests(start_requests, spider)

创建一个scheduler(scrapy框架里的许多组件如spider/middleware/scheduler都会有from_crawler这个默认方法)。这里的scheduler是从配置里取的,默认为SCHEDULER = ‘scrapy.core.scheduler.Scheduler’;
然后调用scraper的spidermw的process_tart_requests方法来处理start_requests。
scraper的作用前面也有介绍是对下载的网页的解析结果进行itemPipeLine的处理,通常是数据库操作;它的spidermw也就是中间件管理器,其实就是SpiderMiddlewareManager,用它来调用每个注册的中间件的process_start_requests方法来处理初始请求。如果我们要对start_requests进行特殊处理,可以自己实现中间件并实现process_start_requests方法。
继续:

yield scheduler.open(spider)
yield self.scraper.open_spider(spider)

依次调用scheduler的open方法和scraper的open_spider方法。

yield self.signals.send_catch_log_deferred(signals.spider_opened, spider=spider)

发送一个spider_opened消息并记录日志,所有关注这个消息的函数都会被调用(写了此函数的各种中间件),同时会向关注模块注册的函数传递一个spider变量。

最后是下面2行代码:

slot.nextcall.schedule()
slot.heartbeat.start(5)

前面已经分析过nextcall和slot,所以这2行的作用就是调用reactor.callLater(delay, self)并设置心跳为5秒。其实这只是作了初始化操作,进行了函数的安装,实际运行要等到reactor启动,也就是前面分析过的CrawlerProcess调用start时。

ExecutionEngine.start()

    @defer.inlineCallbacks
def start(self):
"""Start the execution engine"""
assert not self.running, "Engine already running"
self.start_time = time()
yield self.signals.send_catch_log_deferred(signal=signals.engine_started)
self.running = True
self._closewait = defer.Deferred()
yield self._closewait

代码很简单:记录启动时间;发送一个"engine_started"消息;设置running标志;创建一个_closewait的Deferred对象并返回。
这个_closewait从前面的代码分析中可知会返回给CrawlerProcess,这个Deferred在引擎结束时才会调用,因此用它来向CrawlerProcess通知一个Crawler已经爬取完毕。
————————————————
版权声明:本文为CSDN博主「csdn_yym」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/csdn_yym/java/article/details/85575921

scrapy 源码解析 (三):启动流程源码分析(三) ExecutionEngine执行引擎的更多相关文章

  1. Spring IOC容器启动流程源码解析(四)——初始化单实例bean阶段

    目录 1. 引言 2. 初始化bean的入口 3 尝试从当前容器及其父容器的缓存中获取bean 3.1 获取真正的beanName 3.2 尝试从当前容器的缓存中获取bean 3.3 从父容器中查找b ...

  2. 【图解源码】Zookeeper3.7源码分析,包含服务启动流程源码、网络通信源码、RequestProcessor处理请求源码

    Zookeeper3.7源码剖析 能力目标 能基于Maven导入最新版Zookeeper源码 能说出Zookeeper单机启动流程 理解Zookeeper默认通信中4个线程的作用 掌握Zookeepe ...

  3. Android Activity启动流程源码全解析(1)

    前言 Activity是Android四大组件的老大,我们对它的生命周期方法调用顺序都烂熟于心了,可是这些生命周期方法到底是怎么调用的呢?在启动它的时候会用到startActivty这个方法,但是这个 ...

  4. Android Activity启动流程源码全解析(2)

    接上之前的分析 ++Android Activity启动流程源码全解析(1)++ 1.正在运行的Activity调用startPausingLocked 一个一个分析,先来看看startPausing ...

  5. Spark(四十九):Spark On YARN启动流程源码分析(一)

    引导: 该篇章主要讲解执行spark-submit.sh提交到将任务提交给Yarn阶段代码分析. spark-submit的入口函数 一般提交一个spark作业的方式采用spark-submit来提交 ...

  6. Spring IOC 容器预启动流程源码探析

    Spring IOC 容器预启动流程源码探析 在应用程序中,一般是通过创建ClassPathXmlApplicationContext或AnnotationConfigApplicationConte ...

  7. Spark(五十一):Spark On YARN(Yarn-Cluster模式)启动流程源码分析(二)

    上篇<Spark(四十九):Spark On YARN启动流程源码分析(一)>我们讲到启动SparkContext初始化,ApplicationMaster启动资源中,讲解的内容明显不完整 ...

  8. scrapy 源码解析 (二):启动流程源码分析(二) CrawlerProcess主进程

    CrawlerProcess主进程 它控制了twisted的reactor,也就是整个事件循环.它负责配置reactor并启动事件循环,最后在所有爬取结束后停止reactor.另外还控制了一些信号操作 ...

  9. scrapy 源码解析 (五):启动流程源码分析(五) Scraper刮取器

    Scraper刮取器 对ExecutionEngine执行引擎篇出现的Scraper进行展开.Scraper的主要作用是对spider中间件进行管理,通过中间件完成请求.响应.数据分析等工作. Scr ...

随机推荐

  1. ESP8266局域网智能家居 路由器下作服务器模式串口透传 无线通信控制 arduino uno示例 模板参考

    准备工作 下载一个Arduino IDE, 下载8266的库文件 ESP8266服务器模式串口透传编译 功能说明 1.直接使用路由器中转数据 2.手机放热点模式直接传输数据 两者有访问IP地址的差别, ...

  2. 几款一元单片机对比:CMS8S5880、STM8S003、N76E003

    大概17年开始,STM8S003的价格被贸易商炒货,变得很不稳定,一度上涨到2~3元,因为市场需求大增,小家电.无线充和一些简单功能的产品,本人就有在空气净化器.433M触摸开关.数据收发模块.红外控 ...

  3. 四分位数与pandas中的quantile函数

    四分位数与pandas中的quantile函数 1.分位数概念 统计学上的有分位数这个概念,一般用p来表示.原则上p是可以取0到1之间的任意值的.但是有一个四分位数是p分位数中较为有名的. 所谓四分位 ...

  4. Ray射线检测和Recources.Load

    记录射线检测常用的方法,以及Rocources.Load的常用用法 使用代码实现鼠标点击在鼠标点击处生成制定gameObject RayCastHit hit; void Update() { Ray ...

  5. WeChair项目Alpha冲刺(4/10)

    团队项目进行情况 1.昨日进展    Alpha冲刺第四天 昨日进展: 前端完成小程序登录态的定义 LoginController编写初步完成同时修改并更新了代码,但是在将编码好的项目部署到服务器上时 ...

  6. 键盘侠Linux干货| 使用SSH方式推送文件至github仓库

    前言 作为一名优秀的计算机从业人员,相信大家github应该都知道吧.(优秀的代码托管工具) 但是由于平常使用的https方式克隆的本地仓库,每次git push时都需要输入帐号密码才能将我们修改的文 ...

  7. ASP.NET WebAPI框架解析第一篇

    ASP.NET WebAPI有两种寄宿模式,一种是WebHost,一种是SelfHost,为什么可以有两种模式的原因在于WebAPI有一个相对独立的消息处理管道,只要给这个消息管道传递一个封装好的对象 ...

  8. opencv C++构造并访问单通道和多通道Mat。

    一:构造并访问单通道. int main(){ cv::Mat m=(cv::Mat_<int>(3,2)<<1,2,3,4,5,6); for(int i=0;i<m. ...

  9. 尚硅谷maven视频教程笔记

    07.尚硅谷_Maven_部署Maven核心程序.avi 第一步先安装jdk 第二步下载maven 特别需要注意的是maven不能存储在有中文和空格的目录下面 3.调试是否安装成功,在cmd中输入 m ...

  10. ant+jmeter+jenkins接口自动化测试一

    [Jmeter篇]jmeter+Ant+Jenkins接口自动化测试集成(一) 橙子探索测试发表于橙子探索测试订阅 90 一.简介 1.什么是ant? ant是构建工具,把代码从某个地方拿来,编译,再 ...