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 ...
随机推荐
- JVM内存管理基础概念
.内存的不同形态 物理内存 虚拟内存 .内存的使用形式 内核空间 用户空间 .java虚拟机运行时数据划分 PC寄存器:保存当前程序运行时的内存地址. Java栈:总是和线程关联,每个线程拥有一个ja ...
- 设置浏览器地址栏URL前面显示的图标
其实很简单,你只做个ico图标,命名为favicon.ico,把它传到你的页面下面. 并在相应的页面里加上代码 在页面<heah></heah>之间加, <link r ...
- java导包
下载响应的zip文件,就可以导入了,导入src目录也是可以的.
- Ajax接触及对跨域的简单理解
[Ajax]Ajax技术能够向服务器请求额外的数据而无须卸载页面能带来更好的用户体验.Ajax技术的核心是XMLHttpRequest对象(简称XHR),XHR向服务器发送请求和解析拂去其响应提供了流 ...
- web自动化:前端页面组成
一.web页面的组成 1. 常用:HTML + CSS + Javascript 2. HTML:定义页面的呈现内容 3. CSS:Cascading Style Sheets,层叠样式表 控制你的网 ...
- LSM树——LSM 将B+树等结构昂贵的随机IO变的更快,而代价就是读操作要处理大量的索引文件(sstable)而不是一个,另外还是一些IO被合并操作消耗。
Basic Compaction 为了保持LSM的读操作相对较快,维护并减少sstable文件的个数是很重要的,所以让我们更深入的看一下合并操作.这个过程有一点儿像一般垃圾回收算法. 当一定数量的ss ...
- DocString
文档字符串:写注释专用的, 在函数的第一个逻辑行的字符串是这个函数的 文档字符串 .注意,DocStrings也适用于模块和类,我们会在后面相应的章节学习它们. 文档字符串的惯例是一个多行字符串,它的 ...
- 常用集合ArrayList浅度解析
首先,先看一下java中对ArrayList的定义代码: public class ArrayList<E> extends AbstractList<E> implement ...
- Android 禁止屏幕旋转、避免转屏时重启Activity
一.禁止屏幕旋转 在AndroidManifest.xml的每一个需要禁止转向的Activity配置中加入android:screenOrientation属性: 可选项: landscape = 横 ...
- PageRank算法原理及实现
PageRank算法原理介绍 PageRank算法是google的网页排序算法,在<The Top Ten Algorithms in Data Mining>一书中第6章有介绍.大致原理 ...