scrapy-redis源码抛析
#scrapy-redis--->queue.py-->class FifoQueue 队列 LifoQueue(lastinfirstout栈) #self.server父类Base中链接字符串 ---》 LifoQueue _encode_reques---》Base---》_encode_request--》serializer--->picklecompat #picklecompat-->/usr/local/lib/python3.6/site-packages/scrapy_redis/picklecompat.py
# def loads(s):
# return pickle.loads(s)
#
#
# def dumps(obj):
# return pickle.dumps(obj, protocol=-1) #通过pickle做的serializer #server来源
#/usr/local/lib/python3.6/site-packages/scrapy_redis/connection.py # 通过 def get_redis---》defaults.REDIS_CLS--》/usr/local/lib/python3.6/site-packages/scrapy_redis/defaults.py
#redis.StrictRedis--># import redis #redis.Redis --->/usr/local/lib/python3.6/site-packages/redis/client.py --->redis继承了 StrictRedis #def get_redis
# if url:
# return redis_cls.from_url(url, **kwargs)
# else:
# return redis_cls(**kwargs)
# 有url通过url实例化 没有url就直接加括号实例化--》拿到server #调度器
#/usr/local/lib/python3.6/site-packages/scrapy_redis/scheduler.py
#def enqueue_request--->self.queue.push(request) 放东西
#def next_request -----request = self.queue.pop(block_pop_timeout) 取东西
#def enqueue_request--->self.df.request_seen(request)判断是否存在
#/usr/local/lib/python3.6/site-packages/scrapy_redis/dupefilter.py def request_seen
#self.server.sadd往集合里添加 根据self.server.sadd的返回值True就是如果是0就没加进去就是有已经添加了,如果是1就是没看到过并添加了 #这里面
#/usr/local/lib/python3.6/site-packages/scrapy_redis/queue.py LifoQueue pop push # #dupefilter.py pipelines.py scheduler.py是组件里做的事
#default.py默认值
#picklecompat.py用什么进行序列化
#scheduler.py调用的queue.py #spiders.py爬虫 def start_requests--》self.next_requests
# use_set = self.settings.getbool('REDIS_START_URLS_AS_SET', defaults.START_URLS_AS_SET)
# fetch_one = self.server.spop if use_set else self.server.lpop
#就是去redis取启始url 如果用spiders就需要redis中预先存好启始url 如果不用这个spider我们自己需要手动添加启始url
#
#utiles公共的 #链接redis
#如果有url url优先链接 否则就是ip
# 配置到settings里面
#http://www.cnblogs.com/wupeiqi/articles/6912807.html # REDIS_HOST = 'localhost' # 主机名
# 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' #调度器配置
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue' # 默认使用优先级队列(默认),其他:PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表)
SCHEDULER_QUEUE_KEY = '%(spider)s:requests' # 调度器中请求存放在redis中的key
# v='%(spider)s:requests'
# val=v%{'spider':'hahah'}
# val
# 'hahah:requests'
#每个爬虫,都有自己在scrapy-redis中的队列,在redis中对应的一个key
#renjian:requests:{}/[] 选择是{}/[]是根据PriorityQueue(有序集合),FifoQueue(列表)、LifoQueue(列表) 来定的 #放任务的
#renjian:requests:['http://www.baidu.com',]
#jianren:requests:['http://www.chouti.com',]
#/Users/shuanggai/PycharmProjects/git/python/D20171113/scrapy-redis/day115/dabo/dabo/spiders/renjian.py中的name = 'renjian' 用于做格式化 # SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat" # 对保存到redis中的数据进行序列化,默认使用pickle
# SCHEDULER_PERSIST = True # 是否在关闭时候保留原来的调度器和去重记录,True=保留,False=清空
# 测试时清空 线上不清空
# SCHEDULER_FLUSH_ON_START = True # 是否在开始之前清空 调度器和去重记录,True=清空,False=不清空
# SCHEDULER_IDLE_BEFORE_CLOSE = 10 # 去调度器中获取数据时,如果为空,最多等待时间(最后没数据,未获取到)。
#/usr/local/lib/python3.6/site-packages/scrapy_redis/scheduler.py--》def next_request --》self.idle_before_close
#idle_before_close=0,默认是0
#/usr/local/lib/python3.6/site-packages/scrapy_redis/queue.py-->def pop-->data = self.server.blpop(self.key, timeout)
#lpop取回的是元祖 超时就是体现在这里 # SCHEDULER_DUPEFILTER_KEY = '%(spider)s:dupefilter' # 去重规则,在redis中保存时对应的key
# SCHEDULER_DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter' # 去重规则对应处理的类
#访问记录 类型是集合
#/usr/local/lib/python3.6/site-packages/scrapy_redis/dupefilter.py
#def request_seen ---》self.server.sadd
"""
renjian:dupefilter:{}
jianren:dupefilter:{}
"""
#/usr/local/lib/python3.6/site-packages/scrapy_redis/dupefilter.py --》def request_seen---》fp = self.request_fingerprint(request)
#/usr/local/lib/python3.6/site-packages/scrapy/utils/request.py--》def request_fingerprint(request, include_headers=None):
from scrapy.utils.request import request_fingerprint
from scrapy.http import Request
r1=Request(url='http://www.baidu.com?id=1&page=2',headers={'k1':'v1'})
r1_str = request_fingerprint(r1,include_headers=['k1']) #把对象转化成字符串
print(r1_str) #75d6587d87b3f4f3aa574b33dbd69ceeb9eafe7b
r2=Request(url='http://www.baidu.com?page=2&id=1',headers={'k1':'v2'})
r2_str = request_fingerprint(r2,include_headers=['k1'])
print(r2_str)
#默认 是否加请求头和参数位置不同不影响值,但是参数的增加或减少会影响值 除非添加include_headers #重要
## 利用调度器使用scrapy_redis
SCHEDULER="scrapy_redis.scheduler.Scheduler"
#去重的记录使用scrapy_redis
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" #数据持久化
# from scrapy_redis.pipelines import RedisPipeline
# ITEM_PIPELINES = {
# 'dabo.pipelines.DaboPipeline': 300,
# 'dabo.pipelines.XiaoboPipeline': 400,
# }
from scrapy_redis.pipelines import RedisPipeline
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline': 300,
}
REDIS_ITEMS_KEY = '%(spider)s:items'
REDIS_ITEMS_SERIALIZER = 'json.dumps' #启始url
REDIS_START_URLS_AS_SET = False
#True就是集合False就是列表
REDIS_START_URLS_KEY = '%(name)s:start_urls' #/usr/local/lib/python3.6/site-packages/scrapy_redis/spiders.py 获取start_url 所以需要在redis先添加url
#def start_requests-->self.next_requests
# use_set = self.settings.getbool('REDIS_START_URLS_AS_SET', defaults.START_URLS_AS_SET)
# fetch_one = self.server.spop if use_set else self.server.lpop
#conn.lpush('renjian:start_urls','http://www.chouti.com') #/usr/local/lib/python3.6/site-packages/scrapy_redis/pipelines.py--->class RedisPipeline-->def process_item-->deferToThread(self._process_item, item, spider) # class Base(object):
# """Per-spider base queue class"""
#
# def __init__(self, server, spider, key, serializer=None):
# """Initialize per-spider redis queue.
#
# Parameters
# ----------
# server : StrictRedis
# Redis client instance.
# spider : Spider
# Scrapy spider instance.
# key: str
# Redis key where to put and get messages.
# serializer : object
# Serializer object with ``loads`` and ``dumps`` methods.
#
# """
# if serializer is None:
# # Backward compatibility.
# # TODO: deprecate pickle.
# serializer = picklecompat
# if not hasattr(serializer, 'loads'):
# raise TypeError("serializer does not implement 'loads' function: %r"
# % serializer)
# if not hasattr(serializer, 'dumps'):
# raise TypeError("serializer '%s' does not implement 'dumps' function: %r"
# % serializer)
#
# self.server = server
# self.spider = spider
# self.key = key % {'spider': spider.name}
# self.serializer = serializer
#
# def _encode_request(self, request):
# """Encode a request object"""
# obj = request_to_dict(request, self.spider)
# return self.serializer.dumps(obj) # class LifoQueue(Base):
# """Per-spider LIFO queue."""
#
# def __len__(self):
# """Return the length of the stack"""
# return self.server.llen(self.key)
#
# def push(self, request):
# """Push a request"""
# self.server.lpush(self.key, self._encode_request(request))
#
# def pop(self, timeout=0):
# """Pop a request"""
# if timeout > 0:
# data = self.server.blpop(self.key, timeout)
# if isinstance(data, tuple):
# data = data[1]
# else:
# data = self.server.lpop(self.key)
#
# if data:
# return self._decode_request(data)
#
#
#
# if serializer is None:
# # Backward compatibility.
# # TODO: deprecate pickle.
# serializer = picklecompat
# if not hasattr(serializer, 'loads'):
# raise TypeError("serializer does not implement 'loads' function: %r"
# % serializer)
# if not hasattr(serializer, 'dumps'):
# raise TypeError("serializer '%s' does not implement 'dumps' function: %r"
# % serializer)
# def get_redis(**kwargs):
# """Returns a redis client instance.
#
# Parameters
# ----------
# redis_cls : class, optional
# Defaults to ``redis.StrictRedis``.
# url : str, optional
# If given, ``redis_cls.from_url`` is used to instantiate the class.
# **kwargs
# Extra parameters to be passed to the ``redis_cls`` class.
#
# Returns
# -------
# server
# Redis client instance.
#
# """
# redis_cls = kwargs.pop('redis_cls', defaults.REDIS_CLS)
# url = kwargs.pop('url', None)
# if url:
# return redis_cls.from_url(url, **kwargs)
# else:
# return redis_cls(**kwargs)
scrapy-redis源码抛析的更多相关文章
- vue.js源码精析
MVVM大比拼之vue.js源码精析 VUE 源码分析 简介 Vue 是 MVVM 框架中的新贵,如果我没记错的话作者应该毕业不久,现在在google.vue 如作者自己所说,在api设计上受到了很多 ...
- 30s源码刨析系列之函数篇
前言 由浅入深.逐个击破 30SecondsOfCode 中函数系列所有源码片段,带你领略源码之美. 本系列是对名库 30SecondsOfCode 的深入刨析. 本篇是其中的函数篇,可以在极短的时间 ...
- 曹工说Redis源码(4)-- 通过redis server源码来理解 listen 函数中的 backlog 参数
文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis,而怎么才能懂,光看是不够的,建议跟着下面的这一篇,把环境搭建起来,后续可以自己阅读源码,或者跟着我这边一起阅读.由于 ...
- redis源码学习之lua执行原理
聊聊redis执行lua原理 从一次面试场景说起 "看你简历上写的精通redis" "额,还可以啦" "那你说说redis执行lua脚本的原理&q ...
- MVVM大比拼之AngularJS源码精析
MVVM大比拼之AngularJS源码精析 简介 AngularJS的学习资源已经非常非常多了,AngularJS基础请直接看官网文档.这里推荐几个深度学习的资料: AngularJS学习笔记 作者: ...
- MVVM大比拼之knockout.js源码精析
简介 本文主要对源码和内部机制做较深如的分析,基础部分请参阅官网文档. knockout.js (以下简称 ko )是最早将 MVVM 引入到前端的重要功臣之一.目前版本已更新到 3 .相比同类主要有 ...
- Redis源码研究--字典
计划每天花1小时学习Redis 源码.在博客上做个记录. --------6月18日----------- redis的字典dict主要涉及几个数据结构, dictEntry:具体的k-v链表结点 d ...
- 一起学习redis源码
redis的一些介绍,麻烦阅读前面的几篇文章,想对redis的详细实现有所了解,强力推荐<redis设计与实现>(不仅仅从作者那儿学习到redis的实现,还有项目的管理.思想等,作者可能比 ...
- Redis源码分析系列
0.前言 Redis目前热门NoSQL内存数据库,代码量不是很大,本系列是本人阅读Redis源码时记录的笔记,由于时间仓促和水平有限,文中难免会有错误之处,欢迎读者指出,共同学习进步,本文使用的Red ...
随机推荐
- 亚马逊chime启用新顶级.aws域名后缀
自2013年12月亚马逊AWS公有云服务落地中国,亚马逊AWS在中国市场展开了一系列的活动,激发了国内开发者对亚马逊AWS云平台的热情. chime是亚马逊为客户提供视频会议领域的服务,而.aws是由 ...
- 批处理之IPC连接工具
由于自己需要重复一些工作,闲来没事发个搞个批处理玩玩. 功能介绍:建立IPC连接,IPC磁盘映射,断开IPC连接等 @echo off color 0A echo Welcome!!! echo 本机 ...
- JBOSS invoker GETSHELL(PHP版)
<?php $target = @$argv[1]; $procotol = @$argv[2]; if ($argc < 2) { print "[-]:php Jboss.p ...
- AOP理解,待细看
http://jinnianshilongnian.iteye.com/blog/1474325
- 怎么用API网关构建微服务
选择将应用程序构建为微服务时,需要确定应用程序客户端如何与微服务交互.在单体应用程序中,只有一组端点.而在微服务架构中,每个微服务都会暴露一组通常是细粒度的端点.在本文中,我们将讨论一下这对客户端与应 ...
- spring boot: @Retention注解 @Documented 注解 @Inherited 注解
http://www.jb51.net/article/55371.htm Retention注解 Retention(保留)注解说明,这种类型的注解会被保留到那个阶段. 有三个值:1.Retenti ...
- 直方图均衡化的 C++ 实现(基于 openCV)
这是数字图像处理课的大作业,完成于 2013/06/17,需要调用 openCV 库,完整源码和报告如下: #include <cv.h> #include <highgui.h&g ...
- python中正则表达式的一些问题
今天听到一句话,觉得很在理——"当你遇到一个问题,想到用正则表达式解决时,就变成了两个问题" 这也从侧面说明了正则表达式比较难理解.下面我将用通俗易懂的方式总结一下,最近遇到的一些 ...
- 利用CocoaLumberjack框架+XcodeColors插件,调试输出有彩色的信息
效果如下: 步骤: 1. 安装Xcode插件:XcodeColors(方法请参考这里) 2. 为项目添加 CocoaLumberjack 框架(方法请参考这里) 3. 添加代码 (1) 为项目添加 p ...
- memset函数用法及注意事项
头文件 #include<cstring>// or #include<memory.h> ------------------------------------------ ...