scrapy-分布式爬虫

news/2025/1/22 14:58:11/文章来源:https://www.cnblogs.com/-hz01/p/18237910

一 介绍

原来scrapy的Scheduler维护的是本机的任务队列(存放Request对象及其回调函数等信息)+本机的去重队列(存放访问过的url地址)

所以实现分布式爬取的关键就是,找一台专门的主机上运行一个共享的队列比如Redis,
然后重写Scrapy的Scheduler,让新的Scheduler到共享队列存取Request,并且去除重复的Request请求,所以总结下来,实现分布式的关键就是三点:

#1、共享队列
#2、重写Scheduler,让其无论是去重还是任务都去访问共享队列
#3、为Scheduler定制去重规则(利用redis的集合类型)

以上三点便是scrapy-redis组件的核心功能

#安装:
pip3 install scrapy-redis#源码:
D:\python3.6\Lib\site-packages\scrapy_redis

二、scrapy-redis组件

1、只使用scrapy-redis的去重功能

 

#一、源码:D:\python3.6\Lib\site-packages\scrapy_redis\dupefilter.py#二、配置scrapy使用redis提供的共享去重队列#2.1 在settings.py中配置链接Redis
REDIS_HOST = 'localhost'                            # 主机名
REDIS_PORT = 6379                                   # 端口
REDIS_URL = 'redis://user:pass@hostname:9001'       # 连接URL(优先于以上配置)
REDIS_PARAMS  = {}                                  # Redis连接参数
REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定连接Redis的Python模块
REDIS_ENCODING = "utf-8"                            # redis编码类型  
# 默认配置:D:\python3.6\Lib\site-packages\scrapy_redis\defaults.py#2.2 让scrapy使用共享的去重队列
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
#使用scrapy-redis提供的去重功能,查看源码会发现是基于Redis的集合实现的#2.3、需要指定Redis中集合的key名,key=存放不重复Request字符串的集合
DUPEFILTER_KEY = 'dupefilter:%(timestamp)s'
#源码:dupefilter.py内一行代码key = defaults.DUPEFILTER_KEY % {'timestamp': int(time.time())}#2.4、去重规则源码分析dupefilter.py
def request_seen(self, request):"""Returns True if request was already seen.```
Parameters
----------
request : scrapy.http.RequestReturns
-------
bool"""
fp = self.request_fingerprint(request) 
# This returns the number of values added, zero if already exists.
added = self.server.sadd(self.key, fp)
return added == 0
```#2.5、将request请求转成一串字符后再存入集合from scrapy.http import Request
from scrapy.utils.request import request_fingerprintreq = Request(url='http://www.baidu.com')
result=request_fingerprint(req)
print(result) #75d6587d87b3f4f3aa574b33dbd69ceeb9eafe7b#2.6、注意:- URL参数位置不同时,计算结果一致;- 默认请求头不在计算范围,include_headers可以设置指定请求头- 示范:from scrapy.utils import requestfrom scrapy.http import Request```
req = Request(url='http://www.baidu.com?name=8&id=1',callback=lambda x:print(x),cookies={'k1':'vvvvv'})
result1 = request.request_fingerprint(req,include_headers=['cookies',])print(result)req = Request(url='http://www.baidu.com?id=1&name=8',callback=lambda x:print(x),cookies={'k1':666})result2 = request.request_fingerprint(req,include_headers=['cookies',])print(result1 == result2) #True
```

2、使用scrapy-redis的去重+调度实现分布式爬取

#1、源码:D:\python3.6\Lib\site-packages\scrapy_redis\scheduler.py#2、settings.py配置# Enables scheduling storing requests queue in redis.
SCHEDULER = "scrapy_redis.scheduler.Scheduler"       # 调度器将不重复的任务用pickle序列化后放入共享任务队列,默认使用优先级队列(默认),其他:PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表)               
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'          # 对保存到redis中的request对象进行序列化,默认使用pickle
SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"   # 调度器中请求任务序列化后存放在redis中的key               
SCHEDULER_QUEUE_KEY = '%(spider)s:requests'    # 是否在关闭时候保留原来的调度器和去重记录,True=保留,False=清空                     
SCHEDULER_PERSIST = True       # 是否在开始之前清空 调度器和去重记录,True=清空,False=不清空                                     
SCHEDULER_FLUSH_ON_START = False    # 去调度器中获取数据时,如果为空,最多等待时间(最后没数据,未获取到)。如果没有则立刻返回会造成空循环次数过多,cpu占用率飙升                                
SCHEDULER_IDLE_BEFORE_CLOSE = 10           # 去重规则,在redis中保存时对应的key                         
SCHEDULER_DUPEFILTER_KEY = '%(spider)s:dupefilter'      # 去重规则对应处理的类,将任务request_fingerprint(request)得到的字符串放入去重队列            
SCHEDULER_DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
 

3、持久化

#从目标站点获取并解析出数据后保存成item对象,会由引擎交给pipeline进行持久化/保存到数据库,scrapy-redis提供了一个pipeline组件,可以帮我们把item存到redis中#1、将item持久化到redis时,指定key和序列化函数 
REDIS_ITEMS_KEY = '%(spider)s:items'
REDIS_ITEMS_SERIALIZER = 'json.dumps'#2、使用列表保存item数据
 
 

4、从Redis中获取起始URL

scrapy程序爬取目标站点,一旦爬取完毕后就结束了,如果目标站点更新内容了,我们想重新爬取,那么只能再重新启动scrapy,非常麻烦
scrapy-redis提供了一种供,让scrapy从redis中获取起始url,如果没有scrapy则过一段时间再来取而不会关闭
这样我们就只需要写一个简单的脚本程序,定期往redis队列里放入一个起始url。#具体配置如下#1、编写爬虫时,起始URL从redis的Key中获取
REDIS_START_URLS_KEY = '%(name)s:start_urls'#2、获取起始URL时,去集合中获取还是去列表中获取?True,集合;False,列表
REDIS_START_URLS_AS_SET = False    # 获取起始URL时,如果为True,则使用self.server.spop;如果为False,则使用self.server.lpop
 
 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/721610.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用itextPDF实现PDF电子公章工具类

使用itextPDF实现PDF电子公章工具类 一、制作公章 在线网站:印章生成器 - Kalvin在线工具 (kalvinbg.cn) 然后对公章进行下载保存盖章图片:二、生成数字签名 2.1: java工具keytool生成p12数字证书文件 Keytool是用于管理和证书的工具,位于%JAVA_HOME%/bin目录。 使用JDK的…

前后端分离的四种开发模式

前后端分离已经成为了开发的主流模式,很多老铁认为前后端分离就是各干各的,其实不然。 前后端分离有多种模式,我们一一详解。1. 前后端完全分离 在这种模式下,前端和后端是完全独立的两个系统。前端使用一种框架(如React、Angular、Vue.js等)来实现用户界面,通过API调用…

2024/6/7

今天进行了数据库相关实验。 (1)查询所有供应商情况,先按城市升序排列,城市相同按供应商名称降序排列。(2)查询所有零件情况,先按零件名称升序排列,零件名称相同按重量降序排列。(3)查询项目名中含有“厂”的项目情况。(4)查询供应商名称中第二个字为“方”的供应商…

美团面试:百亿级分片,如何设计基因算法?

文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵的学习资源 : 免费赠送 :《尼恩Java面试宝典》 持续更新+ 史上最全 + 面试必备 2000页+ 面试必备 + 大厂必备 +涨薪必备 免费赠送 :《尼恩技术圣经+高并发系列PDF》 ,帮你 实现技术自由,…

Bug记录:Content-Type application/json;charset=UTF-8 is not supported异常解决

Content-Type application/json;charset=UTF-8 is not supported异常解决 前提:确定不是因为Content-Type导致的异常,controller层有注解@RequestBody。 报错详情:确定不是因为缺少Jackson依赖或者版本过低:注意到报错信息上边有一条警告日志: .c.j.MappingJackson2HttpMe…

6.7哈希表

哈希表 哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。哈希表是根据关键码的值而直接进行访问的数据结构。数组就是一张哈希表。哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素。…

Day16 | 104.二叉树的最大深度 、111.二叉树的最小深度 、222.完全二叉树的节点个数

104.二叉树的最大深度 (优先掌握递归) 什么是深度,什么是高度,如何求深度,如何求高度,这里有关系到二叉树的遍历方式。 大家 要先看视频讲解,就知道以上我说的内容了,很多录友刷过这道题,但理解的还不够。 题目链接/文章讲解/视频讲解: https://programmercarl.com/0…

计算机简史 第1章 手动计算时代

我们在数字出现之前,人们怎么计数呢?‍ 手指计数 我们在数字出现之前,人们怎么计数呢?如何统计人口,统计今天打到了多少猎物? 最开始,人们曾尝试过用手指和脚趾,一指/趾就是 1,双手就是 10,一人就是 20,为此史上有诸多民族曾使用二十进制。藏文中,「人」字有 20 的…

uni-app项目uview的表单验证在小程序上不生效

前情 uni-app是我比较喜欢的跨平台框架,它能开发小程序/H5/APP(安卓/iOS),重要的是对前端开发友好,自带的IDE让开发体验非常棒,公司项目就是主推uni-app,在uniapp生态中uView是其中非常好的全平台的第三方开源ui库,我在公司项目中果断的使用了它。 坑位 在用uView做小程序…

四层反向代理和七层反向代理

1、概述代理也称网络代理,是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击。 2、四层网络…

Python的基本

python之基本介绍(1)什么是pythonpython 是一门编程语言python是一门面向对象,解释型的动态类型的编程语言 guido van rossunm (吉多*范罗苏姆) 在1989年发明,第一个公开发行版本与1991年; python在市面上的版本:python 2.7 (以前用的非常多)目前用的版本是3.0 版本最…