def handle_spider_output(self, result, request, response, spider):
if not result:
return defer_succeed(None)
it = iter_errback(result, self.handle_spider_error, request, response, spider)
dfd = parallel(it, self.concurrent_items,
self._process_spidermw_output, request, response, spider)
return dfd
def iter_errback(iterable, errback, *a, **kw):
"""Wraps an iterable calling an errback if an error is caught while
iterating it.
"""
it = iter(iterable)
while True:
try:
yield next(it)
except StopIteration:
break
except:
errback(failure.Failure(), *a, **kw)

包装一个iter,使其可以在迭代时出现异常时调用 错误处理函数。

def parallel(iterable, count, callable, *args, **named):
"""Execute a callable over the objects in the given iterable, in parallel,
using no more than ``count`` concurrent calls. Taken from: http://jcalderone.livejournal.com/24285.html
"""
coop = task.Cooperator()
work = (callable(elem, *args, **named) for elem in iterable)
return defer.DeferredList([coop.coiterate(work) for _ in range(count)])

并行处理函数,通过twisted的task来实现的。work是一个生成器,每次迭代时,使work前进一步。defer.DeferredList([coop.coiterate(work) for _ in range(count)])生成count个cooperatertask,定时调用work,直到迭代完成。由此可见,蜘蛛输出是一个deferredlist,一个defer在执行callback时,return是defer时,会停止执行callback,等待到结果执行callback时才能再次继续执行。这样实现了defer的串联执行,外层defer相当于总控制,callback返回defer相当于下层的分支。

def coiterate(self, iterator, doneDeferred=None):
"""
Add an iterator to the list of iterators this L{Cooperator} is
currently running. Equivalent to L{cooperate}, but returns a L{defer.Deferred} that will
be fired when the task is done. @param doneDeferred: If specified, this will be the Deferred used as
the completion deferred. It is suggested that you use the default,
which creates a new Deferred for you. @return: a Deferred that will fire when the iterator finishes.
"""
if doneDeferred is None:
doneDeferred = defer.Deferred()
CooperativeTask(iterator, self).whenDone().chainDeferred(doneDeferred)
return doneDeferred

cooperator什么时候调用start开始执行任务?其实在构造cooperator时started=True,所以CooperativeTask()时,会把task加入cooperator,同时调用cooperator的_reschedule()使其可以参与调度。

def _addTask(self, task):
"""
Add a L{CooperativeTask} object to this L{Cooperator}.
"""
if self._stopped:
self._tasks.append(task) # XXX silly, I know, but _completeWith
# does the inverse
task._completeWith(SchedulerStopped(), Failure(SchedulerStopped()))
else:
self._tasks.append(task)
self._reschedule()
def _tick(self):#每次调度时会遍历没有停止的任务,每个任务会执行onework。
"""
Run one scheduler tick.
"""
self._delayedCall = None
for taskObj in self._tasksWhileNotStopped():
taskObj._oneWorkUnit()
self._reschedule() _mustScheduleOnStart = False
def _reschedule(self):
if not self._started:
self._mustScheduleOnStart = True
return
if self._delayedCall is None and self._tasks:
self._delayedCall = self._scheduler(self._tick)延时call为定时调用tick函数。
EPSILON = 0.00000001
def _defaultScheduler(x):
from twisted.internet import reactor
return reactor.callLater(_EPSILON, x)

通过self._scheduler(self._tick)(_defaultScheduler(x))使twisted的reactor能不断调用tick函数。

twisted的task之cooperator和scrapy的parallel()函数的更多相关文章

  1. scrapy item处理----cooperator和parallel()函数

    twisted的task之cooperator和scrapy的parallel()函数 本文是关于下载结果返回后调用item处理的过程实现研究. 从scrapy的结果处理说起 def handle_s ...

  2. 重新想象 Windows 8 Store Apps (43) - 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)

    [源码下载] 重新想象 Windows 8 Store Apps (43) - 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel) 作者:webabcd 介绍重新想象 W ...

  3. scrapy之parallel

    Limiting Parallelism jcalderone May 22nd, 2006 This blog has moved! Read this post and its comments ...

  4. 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)

    Task - 基于线程池的任务(在 System.Threading.Tasks 命名空间下) 多 Task 的并行执行 Parallel - 并行计算(在 System.Threading.Task ...

  5. scrapy yield 回调函数不执行解决方案

    yield Request(url=parse.urljoin(response.url, p_url),callback=self.parse_detail) 回调函数不执行: 加上: dont_f ...

  6. scrapy框架Request函数callback参数为什么是self.parse而不是self.parse( )

    加括号是调用函数,不加括号是指的是函数地址,此处只需要传入函数的地址,等待程序到时调用即可

  7. twisted task.cpperator

    twisted task.cpperator 1.      twisted task.cpperator 1.1.    简介-cooperator 官方文档: https://twistedmat ...

  8. scrapy 源码解析 (三):启动流程源码分析(三) ExecutionEngine执行引擎

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

  9. Scrapy 爬虫 使用指南 完全教程

    scrapy note command 全局命令: startproject :在 project_name 文件夹下创建一个名为 project_name 的Scrapy项目. scrapy sta ...

随机推荐

  1. Backup&recovery备份和还原 mysql

    1.mysqldump 在日常工作中,我们会使用mysqldump命令创建sql格式的转储文件来备份数据库.或者我们把数据导出后做数据迁移,主备搭建等操作.mysqldump是一个逻辑备份工具,复制原 ...

  2. 软件开发者路线图梗概&书摘chapter7

    软件工程是一门技艺 原因:理解不足以系统化 技能:为交付可以工作的软件 重要的原因:了解不足以将它写成可供别人直接运用并得到相同成果的格式 大多数程序员低于平均水平 工艺:一套高度重视技能的训练和传统 ...

  3. [C++]_ELVE_Windows下QT5.12连接MySql8.0解决方案

    #0x01 准备 1)要保证QT和MySQL都是一样的位数,我的就是都安装的64位. 2)安装Qt5.12,这里主要提一点,在安装时候,有个选择插件那块,尽量都选上,里面有个database选项,记得 ...

  4. AWS Tagging Strategies

    How should I tag my AWS resources? Amazon Web Services (AWS) allows customers to assign metadata to ...

  5. Kali无法启动、无法安装

    好久未用Kali,换了个电脑后拷贝过去,发现打开登录界面无限循环,后删除下载新的vm镜像,发现无法开机,界面如下: 后经过各种尝试,发现为vmware版本太低的原因造成,升级vmware到版本14,可 ...

  6. 【转】linux scp远程拷贝文件及文件夹

    转自:http://www.jb51.net/LINUXjishu/73131.html 1.拷贝本机/home/administrator/test整个目录至远程主机192.168.1.100的/r ...

  7. 使用PROC TRANSPOSE过程步对数据集进行转置时如何保持日期变量的时间顺序

    有一个数据集如下所示: 如果直接进行转置. SAS程序: proc transpose data=test out=outx1 (drop=_name_); by id; var amount; id ...

  8. excle删除重复项的行,自定义删除第几个

    在B1输入 =COUNTIF(A$1:A1,A1) 下拉,会有数字1.2.1.2 第二步,选中B列升序排序,排序后,将B列为1的整行删除即可. 再补充下,这样是以姓名为条件来筛选,不会影响你的数据.你 ...

  9. zxing生成二维码和条码

    /*** * 生成二维码方法 * @param str 生成内容 * @param widthHeight 宽度和高度 * @return * @throws WriterException */ p ...

  10. 基于STM8的IIC协议---STM8-第五章

    1. 综述 I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备. 它是由数据线SDA和时钟SCL构成的串行总线,可 ...