路飞学城—Python爬虫实战密训班 第三章

一、scrapy-redis插件实现简单分布式爬虫

scrapy-redis插件用于将scrapy和redis结合实现简单分布式爬虫:
- 定义调度器
- 定义去重规则: 本质利用redis 集合元素不重复(被调度器使用) # 看源码request_seen函数 安装: pip3 install scrapy-redis

  

1. redis配置文件settings.py

#from scrapy_redis import defaults                         # 查看默认配置
REDIS_HOST = '192.168.11.81'                            # 主机名
REDIS_PORT = 6379 # 端口
# REDIS_URL = 'redis://user:pass@hostname:9001' # 连接URL(优先于以上配置)
# REDIS_PARAMS = {} # Redis连接参数 默认:REDIS_PARAMS = {'socket_timeout': 30,'socket_connect_timeout': 30,'retry_on_timeout': True,'encoding': REDIS_ENCODING,})
# REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定连接Redis的Python模块 默认:redis.StrictRedis
REDIS_ENCODING = "utf-8" # redis编码类型 默认:'utf-8'

连接Redis

from scrapy_redis.scheduler import Scheduler
SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 使用该调度器,scrapy-redis原生调度器被替换掉 from scrapy_redis.queue import PriorityQueue
from scrapy_redis import picklecompat
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue' # 默认使用优先级队列(默认),其他:PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表)
SCHEDULER_QUEUE_KEY = '%(spider)s:requests' # 调度器中请求存放在redis中的key
SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat" # 对保存到redis中的数据进行序列化,默认使用pickle
SCHEDULER_PERSIST = True # 是否在关闭时候保留原来的调度器和去重记录,True=保留,False=清空
SCHEDULER_FLUSH_ON_START = False # 是否在开始之前清空 调度器和去重记录,True=清空,False=不清空。本地测试可以为true,实际工作中False
SCHEDULER_IDLE_BEFORE_CLOSE = 10 # 去调度器中获取数据时,如果为空,最多等待时间(最后没数据,未获取到)。
SCHEDULER_DUPEFILTER_KEY = '%(spider)s:dupefilter' # 去重规则,在redis中保存时对应的key
SCHEDULER_DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter' # 去重规则对应处理的类

设置调度器

from scrapy_redis.pipelines import RedisPipeline

ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 300,
} REDIS_ITEMS_KEY = '%(spider)s:items'
REDIS_ITEMS_SERIALIZER = 'json.dumps' # 指定下序列化

数据持久化

2. 当url太长时,数据库保存占空间,创建唯一标识符

from scrapy.utils import request
from scrapy.http import Request obj1 = Request(url='http://www.baidu.com?id=1&name=3')
obj2 = Request(url='http://www.baidu.com?name=3&id=1') # 当传参一致时,创建的标识符也一样 v = request.request_fingerprint(obj1)
print(v)
v = request.request_fingerprint(obj2)
print(v)

test.py

3. 起始URL相关

from scrapy_redis.pipelines import RedisSpider
class ChoutiSpider(scrapy.RedisSpider):
name = "chouti"
allowed_domains = ["chouti.com"] def parse(self, response):
for i in range(0,10):
yield

chouti.py:不用写起始url,但是这个爬虫不会终止, 不用redis的话 爬虫下载完url后会终止。

4. 小结

1. memcached

2. Django缓存

3. redis
- 连接
- StrictRedis()
- Redis(StrictRedis) # 继承StrictRedis
- 连接池 - 基本操作
.. - 事务 - 发布和订阅 4. scrapy-redis流程
4.1 引擎,获取起始Request对象, 添加(pickle)到调度器
- scrapy内部调度器
- scrapy-redis调度器三个选择:先进先出列表,后进先出列表,有序集合 4.2 调度器通知下载器可以开始下载,去调度器中获取request对象(通过pickle存储request对象),下载器进行下载 4.3 爬虫parse方法,yield返回对象item或request
- item 交给pipeline处理
- request 交给调度去处理,调用DUPEFILTER_CLASS去检查是否已经访问过,来决定request重新放置调度器或者丢弃 scrapy-redis扩种:
- 中间件
- 基于信号的扩展

三、scrapy-redis示例

# DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
#
#
# from scrapy_redis.scheduler import Scheduler
# from scrapy_redis.queue import PriorityQueue
# SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue' # 默认使用优先级队列(默认),其他:PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表)
# SCHEDULER_QUEUE_KEY = '%(spider)s:requests' # 调度器中请求存放在redis中的key
# SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat" # 对保存到redis中的数据进行序列化,默认使用pickle
# SCHEDULER_PERSIST = True # 是否在关闭时候保留原来的调度器和去重记录,True=保留,False=清空
# SCHEDULER_FLUSH_ON_START = False # 是否在开始之前清空 调度器和去重记录,True=清空,False=不清空
# SCHEDULER_IDLE_BEFORE_CLOSE = 10 # 去调度器中获取数据时,如果为空,最多等待时间(最后没数据,未获取到)。
# SCHEDULER_DUPEFILTER_KEY = '%(spider)s:dupefilter' # 去重规则,在redis中保存时对应的key
# SCHEDULER_DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'# 去重规则对应处理的类
#
#
#
# REDIS_HOST = '10.211.55.13' # 主机名
# REDIS_PORT = 6379 # 端口
# # REDIS_URL = 'redis://user:pass@hostname:9001' # 连接URL(优先于以上配置)
# # REDIS_PARAMS = {} # Redis连接参数 默认:REDIS_PARAMS = {'socket_timeout': 30,'socket_connect_timeout': 30,'retry_on_timeout': True,'encoding': REDIS_ENCODING,})
# # REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient' # 指定连接Redis的Python模块 默认:redis.StrictRedis
# REDIS_ENCODING = "utf-8" # redis编码类型 默认:'utf-8'

配置文件

import scrapy

class ChoutiSpider(scrapy.Spider):
name = "chouti"
allowed_domains = ["chouti.com"]
start_urls = (
'http://www.chouti.com/',
) def parse(self, response):
for i in range(0,10):
yield

爬虫文件

四、总结

  WuSir为了给我们介绍分布式爬虫,他首先用了个典型的例子举例。问题是:在不考虑开进程和线程(比如这些都已经做好了)如何提高爬虫的性能?说到这可能大家心里都已经有答案了,没错,我最帅!

 
  好了,回到正题;既然进程和线程都不需要我们考虑的情况下,那么我们的一般选择就应该是多加些机器一起爬,但是随之而来的又有一个问题、单纯的增加机器,不让它们相互协调的工作,这会造成会重复的做相同的无用功,也就是会爬到相同的URL。要是不让它们协调在一起,这个方案也就没意义了。
 
  既然问题已经抛出,那么我们就可以引入答案了,也就是如题所说的:scrapy-redis、使用该模块可以帮助我们实现分布式爬虫。我们需要做的则是对他进行相应的操作和配置或者扩展,来进行使用它即可达到我们的目的。

  

路飞学城—Python爬虫实战密训班 第三章的更多相关文章

  1. 路飞学城—Python爬虫实战密训班 第二章

    路飞学城—Python爬虫实战密训班 第二章 一.Selenium基础 Selenium是一个第三方模块,可以完全模拟用户在浏览器上操作(相当于在浏览器上点点点). 1.安装 - pip instal ...

  2. 路飞学城Python爬虫课第一章笔记

    前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 之前看阮一峰的博客文章,介绍到路飞学城爬虫课程限免,看了眼内容还不错,就兴冲冲报了名,99块钱满足以下条件会返还并送书送视频. 缴 ...

  3. 路飞学城-Python爬虫集训-第三章

    这个爬虫集训课第三章的作业讲得是Scrapy 课程主要是使用Scrapy + Redis实现分布式爬虫 惯例贴一下作业: Python爬虫可以使用Requests库来进行简单爬虫的编写,但是Reque ...

  4. 路飞学城-Python爬虫集训-第一章

    自学Python的时候看了不少老男孩的视频,一直欠老男孩一个会员,现在99元爬虫集训果断参与. 非常喜欢Alex和武Sir的课,技术能力超强,当然讲着讲着就开起车来也说明他俩开车的技术也超级强! 以上 ...

  5. 路飞学城-Python爬虫集训-第二章

    本次爬虫集训的第二次作业是web微信. 先贴一下任务: 作业中使用到了Flask. Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSGI 工具箱采用 Werkzeug ,模 ...

  6. 路飞学城-Python开发集训-第3章

    学习心得: 通过这一章的作业,使我对正则表达式的使用直接提升了一个level,虽然作业完成的不怎么样,重复代码有点多,但是收获还是非常大的,有点找到写代码的感觉了,遗憾的是,这次作业交过,这次集训就结 ...

  7. 路飞学城-Python开发集训-第1章

    学习体会: 在参加这次集训之前我自己学过一段时间的Python,看过老男孩的免费视频,自我感觉还行,老师写的代码基本上都能看懂,但是实际呢?....今天是集训第一次交作业的时间,突然发现看似简单升级需 ...

  8. 路飞学城-Python开发集训-第4章

    学习心得: 学习笔记: 在python中一个py文件就是一个模块 模块好处: 1.提高可维护性 2.可重用 3.避免函数名和变量名冲突 模块分为三种: 1.内置标准模块(标准库),查看所有自带和第三方 ...

  9. 路飞学城-Python开发集训-第2章

    学习心得: 这章对编码的讲解超级赞,现在对于编码终于有一点认知了,但还没有大彻大悟,还需要更加细心的琢磨一下Alex博客和视频,以前真的是被编码折磨死了,因为编码的问题而浪费的时间很多很多,现在终于感 ...

随机推荐

  1. JuJu团队1月4号工作汇报

    JuJu团队1月4号工作汇报 JuJu   Scrum 团队成员 今日工作 剩余任务 困难 飞飞 将model嵌入GUI 美化UI 无 婷婷 调试代码 提升acc 无 恩升 -- 写python版本的 ...

  2. CSP-J/S2019试题选做

    S D1T2 括号树 设\(f[u]\)表示根到\(u\)的路径上有多少子串是合法括号串.(即题目里的\(k_u\),此变量名缺乏个性,故换之) 从根向每个节点dfs,容易求出\(c[u]\):表示从 ...

  3. <BitMap>大名鼎鼎的bitmap算法

    BitMap 抛砖引玉 首先,我们思考一个问题:如何在3亿个整数(0~2亿)中判断某一个数是否存在?现在只有一台机器,内存只有500M 这个问题像不像我们之前提到过的一个在0-10个数中,判断某一个数 ...

  4. Windows驱动开发-_DRIVER_OBJECT结构体

    每个驱动程序会有唯一的驱动对象与之对应,并且这个驱动对象是在驱动加载的时候,被内核中的对象管理程序所创建的,内核对一个驱动只加载一个实例,是由内核中的I/O管理器负责加载的,驱动程序需要在Driver ...

  5. $('#myModal').modal('show') //显示$('#myModal').modal('hide')隐藏

    你这样试试,这是官方文档的写法 $('#myModal').modal('show') //显示$('#myModal').modal('hide')隐藏 //重复点击的隐藏显示有一个很更方便的写法$ ...

  6. pandas包 —— drop()、sort_values()、drop_duplicates()

    一.drop() 函数 当你要删除某一行或者某一列时,用drop函数,它不改变原有的df中的数据,而是返回另一个dataframe来存放删除后的数据. 1.命令: df.drop() 删除行:df.d ...

  7. leeetcode1171 Remove Zero Sum Consecutive Nodes from Linked List

    """ Given the head of a linked list, we repeatedly delete consecutive sequences of no ...

  8. 关于可持久化Trie

    我认为 可持久化Trie 主要指 可持久化01Trie 如洛谷P4735 将每个数的异或前缀和转化为二进制,添加前缀0至相同位数,然后从最高位开始插入,类似主席树,每一层都对需要更新的点加入一个新的点 ...

  9. JuJu alpha

    JuJu alpha阶段总结博客 JuJu   设想与目标   我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 在cao ying researcher给的资料中定 ...

  10. docker-compose(grafana influxdb) + telegraf 快速搭建简单监控

     灵活实现方案:   1:     telegraf 为go 语言写得占用内存小 收集主机各项监控数据 定时写入 时序DB   influxdb ------------------------&qu ...