对爬虫的请求进行调度管理

允许接收requests并且会调度一个request去下载,且具有去重机制

优先级和队列不会被调度器执行(调度器不管优先级的问题),用户使用字段给每个Request对象,可以根据这些优先级去安排想要的优先级顺序

调度器使用两个优先级队列实例。设置在内存队列和磁盘队列中工作。当磁盘队列存在的时候,默认使用磁盘队列。当磁盘队列不能处理request的时候,使用内存队列

配置磁盘队列和内存队列,以允许requests存放进磁盘队列和内存队列中

总之,调度器是一个持有优先级队列和fallback逻辑的对象,并且可以处理去重策略

def __init__(self, dupefilter, jobdir=None, dqclass=None, mqclass=None,
logunser=False, stats=None, pqclass=None, crawler=None):
self.df = dupefilter#去重策略
self.dqdir = self._dqdir(jobdir)#磁盘队列工作目录
self.pqclass = pqclass
self.dqclass = dqclass
self.mqclass = mqclass
#日志,状态,爬虫
self.logunser = logunser
self.stats = stats
self.crawler = crawler

def from_crawler(cls, crawler):
settings = crawler.settings#导入crawler配置
#settings配置的去重策略的类配置
dupefilter_cls = load_object(settings['DUPEFILTER_CLASS'])
dupefilter = create_instance(dupefilter_cls, settings, crawler)
#优先级队列
pqclass = load_object(settings['SCHEDULER_PRIORITY_QUEUE'])
#优先级在优先级队列中抛过的警告
if pqclass is PriorityQueue:
warnings.warn("SCHEDULER_PRIORITY_QUEUE='queuelib.PriorityQueue'"
" is no longer supported because of API changes; "
"please use 'scrapy.pqueues.ScrapyPriorityQueue'",
ScrapyDeprecationWarning)
from scrapy.pqueues import ScrapyPriorityQueue
pqclass = ScrapyPriorityQueue
#磁盘队列
dqclass = load_object(settings['SCHEDULER_DISK_QUEUE'])
#内存队列
mqclass = load_object(settings['SCHEDULER_MEMORY_QUEUE'])
#日志:记录不可序列化的requests日志
logunser = settings.getbool('LOG_UNSERIALIZABLE_REQUESTS',
settings.getbool('SCHEDULER_DEBUG'))
#return最终生成的对象
return cls(dupefilter, jobdir=job_dir(settings), logunser=logunser,
stats=crawler.stats, pqclass=pqclass, dqclass=dqclass,
mqclass=mqclass, crawler=crawler)

#open一个爬虫,开启调度器
def open(self, spider):
self.spider = spider
self.mqs = self._mq()
self.dqs = self._dq() if self.dqdir else None
return self.df.open()

#当磁盘队列没有值的时候关闭调度器
def close(self, reason):
if self.dqs:
state = self.dqs.close()
self._write_dqs_state(self.dqdir, state)
return self.df.close(reason)

#如果requests已重复并已爬取的队列中,就抛出日志,并return false
def enqueue_request(self, request):
if not request.dont_filter and self.df.request_seen(request):
self.df.log(request, self.spider)
return False
dqok = self._dqpush(request)
if dqok:
self.stats.inc_value('scheduler/enqueued/disk', spider=self.spider)
else:
self._mqpush(request)
self.stats.inc_value('scheduler/enqueued/memory', spider=self.spider)
self.stats.inc_value('scheduler/enqueued', spider=self.spider)
return True

#从内存队列取request,如果取出来就抛出信号,如果没取出来就从磁盘队里中取,取出来也抛出信号,最终在确认一遍是否取出,取出的话就加入到以采队列中,并return 出去
def next_request(self):
request = self.mqs.pop()
if request:
self.stats.inc_value('scheduler/dequeued/memory', spider=self.spider)
else:
request = self._dqpop()
if request:
self.stats.inc_value('scheduler/dequeued/disk', spider=self.spider)
if request:
self.stats.inc_value('scheduler/dequeued', spider=self.spider)
return request

最新文章

  1. Tomcat 8熵池阻塞变慢详解(putty)
  2. C# 通用验证类 支持 WPF,MVC,Winform
  3. grep -w
  4. [Flex] Accordion系列 - Header图标的设置
  5. javascript中for/in循环及使用技巧
  6. URL重写的优缺点分析
  7. 实用的eclipse adt 快捷键
  8. Wireshark 基本介绍和学习 TCP 三次握手
  9. 把第三方的exe程序嵌入C#界面上
  10. Vim 入门:基础
  11. 简单的class及运算符重载
  12. Java基础恶补——内存泄露、内存溢出
  13. Javascript内置对象、原生对象、宿主对象关系
  14. linux 3.10 的中断收包笔记
  15. .net 代理类(WebService代理类的详解 )
  16. # 2017-2018-2 20155319『网络对抗技术』Exp2:后门原理与实践
  17. linux下查看当前目录属于哪个分区?
  18. Esper学习之九:EPL语法(五)
  19. 正确理解 SqlConnection 的连接池机制[转]
  20. Oracle11g用户、权限、角色、概要文件管理及审计

热门文章

  1. Java实现 LeetCode70 爬楼梯
  2. Java实现 LeetCode 59 螺旋矩阵 II
  3. java实现第七届蓝桥杯抽签
  4. Java实现第八届蓝桥杯承压计算
  5. Linux 源码包安装过程
  6. UVIYN的基本设置
  7. https如何进行加密传输
  8. 数据误操作,删库跑路?教你使用ApexSQLLog工具从 SQLServer日志恢复数据!
  9. 手把手教你安装Ubuntu系统增强工具
  10. vue踩过的坑('url' is assigned a value but never used no-unused-vars)