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. 机器学习基础一(TP,TN,FP,FN等)

    TP:预测为正向(P),实际上预测正确(T),即判断为正向的正确率 TN:预测为负向(N),实际上预测正确(T),即判断为负向的正确率 FP:预测为正向(P),实际上预测错误(F),误报率,即把负向判 ...

  2. 学习php

    一.php是什么? 1.PHP:Hypertext Preprocessor(超文本预处理语言),是一种开源脚本语言. 2.PHP是脚本语言 3.PHP最流行的网站开发语言 4.PHP官网:http: ...

  3. [Jave - JDBC] executeUpdate & executeQuery & execute

    1. executeUpdate 用於執行INSERT.UPDATE.DELETE語法,以及 DDL語句(如CREATE TABLE 和DROP TABLE). 返回值為受影響的行數or更新計數(整數 ...

  4. c# 中 利用 CookieContainer 对 Cookie 进行序列化和反序列化校验

    private void Form1_Load(object sender, EventArgs e) { var cookieStr = @".CNBlogsCookie=1BE76122 ...

  5. MySQL Hardware--Linux 文件句柄限制

    Linux会限制文件句柄数量,默认为1024,当超过该阈值后,会报"to many open files" ## 使用ulimit -a查看当前打开文件句柄限制 ulimit -a ...

  6. Thing in java 第四章,控制执行流程,练习题答案

    /** * Created by Sandy.Liu on 2018/7/19. * Thinking in java, version 4, chapter 4, practice 1 * Writ ...

  7. Day 18 常用模块(二)

    一.随机数:RANDOM 1.(0,1)小数:random.random() 2.[1,10]整数:random.randint(1,10) 3.[1,10)整数:random.randrang(1, ...

  8. python selenium Chrome模拟手机浏览器(十七)

    在做移动端页面测试时可以利用Chrome mobile emulation 辅助完成页面的适配问题,但是目前手机市场上的型号居多我们也没有办法通过人工的模式一一的去适配,所以这里考虑到通过自动化的模式 ...

  9. Skin Microstructure Deformation with Displacement Map Convolution项目小结

    经常有人问我你最近在干什么,但一句话真的很难说明白,最近两个月一直在尝试将Skin Microstructure Deformation with Displacement Map Convoluti ...

  10. linux 线程同步

    参考链接:https://blog.csdn.net/daaikuaichuan/article/details/82950711#font_size5font_2 一,互斥锁 #include &l ...