笔记-scrapy-去重

1.      scrapy 去重

scrapy 版本:1.5.0

第一步是要找到去重的代码,scrapy在请求入列前去重,具体源码在scheduler.py:

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

红色部分进行去重:

dont_filter在requests类中有提到,用于指定是否对请求进行去重

self.df.request_seen(request)是什么?

self.df = dupefilter,而dupefilter由dupefilter_cls = load_object(settings['DUPEFILTER_CLASS'])指定

文档settings中有提到DUPEFILTER_CLASS

Default: 'scrapy.dupefilters.RFPDupeFilter'

找到scrapy.dupefilters.RFPDupeFilter,其中有request_seen()

def request_seen(self, request):

fp = self.request_fingerprint(request)

if fp in self.fingerprints:

return True

self.fingerprints.add(fp)

if self.file:

self.file.write(fp + os.linesep)

简单来说是通过self.request_fingerprint(request)得到fp,判断是否存在于self.fingerprints中,如果存在,则返回True,否则返回None。

self.fingerprints=set() 它是一个指纹集合。

self.request_fingerprint()是什么?继续找

self.request_fingerprint()实际是调用自utils.request.py的request_fingerprint()

源码如下:

def request_fingerprint(request, include_headers=None):

"""

Return the request fingerprint.

"""

if include_headers:

include_headers = tuple(to_bytes(h.lower())

for h in sorted(include_headers))

cache = _fingerprint_cache.setdefault(request, {})

if include_headers not in cache:

fp = hashlib.sha1()

fp.update(to_bytes(request.method))

fp.update(to_bytes(canonicalize_url(request.url)))

fp.update(request.body or b'')

if include_headers:

for hdr in include_headers:

if hdr in request.headers:

fp.update(hdr)

for v in request.headers.getlist(hdr):

fp.update(v)

cache[include_headers] = fp.hexdigest()

return cache[include_headers]

有点杂,它返回的是request的伪hash码,它对request的method,处理后的url,body进行hash,返回hash值。

1.1.    总结

  1. 去重是在请求入队列之前进行的,dont_filter控制是否进行去重(默认为false去重);
  2. 通过request_seen()判断是否重复,实际过程是计算出request的指纹,去集合中匹配是否存在,;
  3. 使用request_fingerprint计算请求的指纹。

从代码中可以看到去重依赖的是set,这样的话在爬虫中断后会被清空,scrapy提供了一个方案:

将指纹保存到文件中,每次实例化时从文件中读取。

def __init__(self, path=None, debug=False):

self.file = None

self.fingerprints = set()

self.logdupes = True

self.debug = debug

self.logger = logging.getLogger(__name__)

if path:

self.file = open(os.path.join(path, 'requests.seen'), 'a+')

self.file.seek(0)

self.fingerprints.update(x.rstrip() for x in self.file)

笔记-scrapy-去重的更多相关文章

  1. 笔记-爬虫-去重/bloomfilter

    笔记-爬虫-去重/bloomfilter 1.      去重 为什么要去重? 页面重复:爬的多了,总会有重复的页面,对已爬过的页面肯定不愿意再爬一次. 页面更新:很多页面是会更新的,爬取这种页面时就 ...

  2. 笔记-scrapy与twisted

    笔记-scrapy与twisted Scrapy使用了Twisted作为框架,Twisted有些特殊的地方是它是事件驱动的,并且比较适合异步的代码. 在任何情况下,都不要写阻塞的代码.阻塞的代码包括: ...

  3. Scrapy去重

    一.原生 1.模块 from scrapy.dupefilters import RFPDupeFilter 2.RFPDupeFilter方法 a.request_seen 核心:爬虫每执行一次yi ...

  4. python学习笔记 | 列表去重

    ''' @author: 人人都爱小雀斑 @time: 2020/3/10 10:29 @desc: ''' L=[1,5,7,4,6,3,0,5,8,4,4] 方法1:for循环 L1=[] for ...

  5. JS学习笔记——数组去重

    <script type="text/javascript"> //indexOf"是ECMAScript5方法,IE8以下不支持,需多写兼容低版本浏览器代码 ...

  6. scrapy 去重 dont_filter=False

    yield Request(...... dont_filter=False)

  7. scrapy暂停和重启,及url去重原理,telenet简单使用

    一.scrapy暂停与重启 1.要暂停,就要保留一些中间信息,以便重启读取中间信息并从当前位置继续爬取,则需要一个目录存放中间信息: scrapy crawl spider_name -s JOBDI ...

  8. Scrapy 初体验

    开发笔记 Scrapy 初体验 scrapy startproject project_name 创建工程 scrapy genspider -t basic spider_name website. ...

  9. Python Scrapy环境配置教程+使用Scrapy爬取李毅吧内容

    Python爬虫框架Scrapy Scrapy框架 1.Scrapy框架安装 直接通过这里安装scrapy会提示报错: error: Microsoft Visual C++ 14.0 is requ ...

随机推荐

  1. 移动webApp - 1像素实现(点5像素的秘密)

    在移动web项目中,经常会实现以下1像素的边框 移动web设计中,在retina显示屏下网页会由1px会被渲染为2px,那么视觉稿中1px的线条还原成网页需要css定义为0.5px 但是正当我们去用0 ...

  2. DVB数字电视常见信号指标解释

    1. 平均功率与峰值电平       峰值电平在模拟电视广播时用于表征频道信号电平强弱. 模拟电视信号是单极性.不对称的,即电视信号有一个固定黑色参考电平,比黑色亮的信号处在黑色电平线一边,同步脉冲处 ...

  3. centos6.5_64bit-kvm安装部署

    kvm部署安装   目录 kvm部署安装... 1 一.kvm部署... 1 1.关闭selinux和防火墙... 1 2.查看主机是否支持虚拟化... 1 3.安装kvm和其他虚拟化软件包... 1 ...

  4. Spark master节点HA配置

    Spark master节点HA配置 1.介绍 Spark HA配置需要借助于Zookeeper实现,因此需要先搭建ZooKeeper集群. 2.配置 2.1 修改所有节点的spark-evn.sh文 ...

  5. simotion读写CF卡,保存/读取变量

    simotion读写CF卡功能 1 使用西门子的Simotion运动控制器时,有时需要用到 读/写 CF卡的功能.主要来自以下几个方面的需求. 1)用户数据量较大,可保持(retain)存储区的容量不 ...

  6. 【js基础修炼之路】— 我理解的原型链

    提起原型链,大家并不陌生,但是对于新人来说一提到原型方面的东西就会比较懵.在我自一次面试的时候,面试官也给我提了这样的问题,当时就按照我的理解说了一些,但是很肤浅,在此我希望给刚入门的前端小伙伴聊一下 ...

  7. SAP CRM和C4C数据同步的两种方式概述:SAP PI和HCI

    SAP Cloud for Customer(C4C)和SAP其他传统产品进行数据同步的方式,如下图所示,可以使用SAP Netweaver Process Integration或者SAP HANA ...

  8. vuejs非父子组件传值

    当父组件要给孙子,或者孙子与孙子要传值的时候怎么传,一层一层传太麻烦了,vuejs提供了一中模式叫发布订阅模式(观察者模式,bus,总线)来处理非父子组件间的传值 <div id='root'& ...

  9. 2017.9.30 Java中引用类型变量的创建及使用&循环的高级

    今日内容介绍 1.引用类型变量的创建及使用 2.流程控制语句之选择语句 3.流程控制语句之循环语句 4.循环高级 ###01创建引用类型变量公式     * A: 创建引用类型变量公式         ...

  10. caffe新版本的各种软件

    系统重装了,于是,我想装就体验一下最新的各种东西吧. anaconda最新的 cuda最新的 cudnn最新的 本来安装好了没问题.caffe编译也通过了.但是不能用,缺少python opencv和 ...