笔记-scrapy-去重
笔记-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. 总结
- 去重是在请求入队列之前进行的,dont_filter控制是否进行去重(默认为false去重);
- 通过request_seen()判断是否重复,实际过程是计算出request的指纹,去集合中匹配是否存在,;
- 使用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-去重的更多相关文章
- 笔记-爬虫-去重/bloomfilter
笔记-爬虫-去重/bloomfilter 1. 去重 为什么要去重? 页面重复:爬的多了,总会有重复的页面,对已爬过的页面肯定不愿意再爬一次. 页面更新:很多页面是会更新的,爬取这种页面时就 ...
- 笔记-scrapy与twisted
笔记-scrapy与twisted Scrapy使用了Twisted作为框架,Twisted有些特殊的地方是它是事件驱动的,并且比较适合异步的代码. 在任何情况下,都不要写阻塞的代码.阻塞的代码包括: ...
- Scrapy去重
一.原生 1.模块 from scrapy.dupefilters import RFPDupeFilter 2.RFPDupeFilter方法 a.request_seen 核心:爬虫每执行一次yi ...
- 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 ...
- JS学习笔记——数组去重
<script type="text/javascript"> //indexOf"是ECMAScript5方法,IE8以下不支持,需多写兼容低版本浏览器代码 ...
- scrapy 去重 dont_filter=False
yield Request(...... dont_filter=False)
- scrapy暂停和重启,及url去重原理,telenet简单使用
一.scrapy暂停与重启 1.要暂停,就要保留一些中间信息,以便重启读取中间信息并从当前位置继续爬取,则需要一个目录存放中间信息: scrapy crawl spider_name -s JOBDI ...
- Scrapy 初体验
开发笔记 Scrapy 初体验 scrapy startproject project_name 创建工程 scrapy genspider -t basic spider_name website. ...
- Python Scrapy环境配置教程+使用Scrapy爬取李毅吧内容
Python爬虫框架Scrapy Scrapy框架 1.Scrapy框架安装 直接通过这里安装scrapy会提示报错: error: Microsoft Visual C++ 14.0 is requ ...
随机推荐
- 关于如何等待一个元素的出现而不用一些笨拙粗暴的time.sleep()方法
我相信这是一个非常大众化的需求,我们需要等待某一个元素的出现以此来让我们的脚本进入到下一个Step,这个等待方法最好能够设置超时时间,然后找到后迅速callback.我们也很幸运!如果你仔细看Sele ...
- phpStudy:使用localhost无法访问的解决方案
今天遇到新的问题,很有意思,当使用Localhost时,发现报403错误: 百度找到问题所在:没有权限问题 所以我们打开phpStudy,找到配置文件“vhosts-conf”,看到的情况是这样的 接 ...
- 二叉索引树,LA2191,LA5902,LA4329
利用了二进制,二分的思想的一个很巧妙的数据结构,一个lowbit(x):二进制表示下的最右边的一个1开始对应的数值. 那么如果一个节点的为x左孩子,父亲节点就是 x + lowbit(x),如果是右孩 ...
- 课程设计__继承与派生,重载<<
///继承与派生 #include <iostream> using namespace std; class Point { public: Point (,):x(a),y(b) {} ...
- 字符串反转,栈模拟(ZOJ1151)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=151 这里可以用栈模拟,也可以用STL,reverse();函数. 但 ...
- shell脚本监控URL并自动发邮件
1.安装sendmail:yum install -y sendmail 2.安装mail:yum install -y mail 3.安装mutt:yum install -y mutt 4.启动s ...
- PHP获取当前页面完整路径URL
//PHP获取当前页面完整路径URL 1 <?php function getFullUrl(){ # 解决通用问题 $requestUri = ''; if (isset($_SERVER[' ...
- string find简析
原文链接 #include <string>#include <iostream>using namespace std; void main(){ ////find函数返回类 ...
- DTcms网站伪静态逻辑
我们之前写伪静态就是web.config里面配置好.-->配置伪静态(URL重写),DTcms网站写的伪静态跟之前的不一样,他是静态页面和代码现实了分离.http://demo.dtcms.ne ...
- 11_1_GUI
11_1_GUI 1. AWT AWT(Abstract Window Toolkit)包括了很多类和接口,用于Java Application的GUI(Graphics User Interface ...