scrapy-redis

1、settings.py         配置链接Redis

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

2、去重

2.1、源码解析

dupefilter.py

# 使用scrapy-redis提供的去重功能,查看源码会发现是基于Redis的集合实现的
# scrapy 使用has_seen()
# 去重: 利用redis集合元素不重复 request_seen
# 返回1 表示添加成功 否则0 失败

def __init__(self):
    pass
    
@classmethod
def from_crawler(cls,crawler):
    pass
    
@classmethod
def from_settings(cls,settings):
    server=get_redis_from_settings(cls,settings)  
            # 连接redis数据库
        pass
    
def request_seen(self,request):           # 利用redis集合元素不重复  request_seen
    fp=self.request_fingerprint(request)  # request的指纹,唯一性
    added=self.server.sadd(self.key,fp)   # k,v 插入redis,返回值added    
                                          # sadd 是个集合
    return added == 0          # 如果added=0,说明已经存在这个请求,就不会再加入队列
                               # 如果added=1,添加成功
            
def request_fingerprint(self,request):   # 获取指纹
    return request_fingerprint(request)
    
def close(self,reason=''):
    self.clear()

def clear(self):
    self.server.delete(self.key)

def log(self,request,spider);
    pass
源码

queue.py    队列 栈 有序集合

# FifoQueue
    #(列表,first in first out 先进后出 )
    # spiderQueue=FifoQueue

# LifoQueue
    #(栈,last in first out 后进先出 )
    # spiderStack=LifoQueue

# PriorityQueue(有序集合)
    # spiderPriorityQueue=PriorityQueue

# 不仅存request 还是存request的优先级 
    # score=-request.priority  目的是 深度优先 score是正数
    # 可以在parse中print(response.request.priority)
def push()
    pass
def pop()
View Code

2.2、只使用去重,连接配置+...

DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
        #使用scrapy-redis提供的去重功能,查看源码会发现是基于Redis的集合实现的

    # 实际工作中:     创建dupe.py
        from scrapy_redis.dupefilter from    RFPDupeFilter
        class MyRFPDupeFilter(RFPDupeFilter):
            pass
        DUPEFILTER_CLASS = "xxxx.dupe.MyRFPDupeFilter"    
View Code

3、调度器

将请求通过pickle序列化,添加到redis:列表或者有序集合,与setting配置
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue' 有关

连接配置 + 下面:
    # 测试看看是否需要这个,不一定
    # DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
    
    
    SCHEDULER = "scrapy_redis.scheduler.Scheduler"       
    SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue' 
        # 默认使用优先级队列(默认广度优先),其他:PriorityQueue(有序集合 广度优先) 、
        # FifoQueue(列表 深度优先)、
        # LifoQueue(列表 深度优先)、 
        # 调度器将不重复的任务用pickle序列化后放入共享任务队列,
               
    SCHEDULER_QUEUE_KEY = '%(spider)s:requests' 
        # 调度器中请求任务序列化后存放在redis中的key  

    SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"    
        # 对保存到redis中的request对象进行序列化,默认使用pickle
                        
    SCHEDULER_PERSIST = True       
        #是否在关闭时候保留原来的调度器和去重记录,True=保留,False=清空 
                                        
    SCHEDULER_FLUSH_ON_START = False    
        #是否在开始之前清空调度器和去重记录,True=清空,False=不清空 
                                  
    SCHEDULER_IDLE_BEFORE_CLOSE = 10           
        #去调度器中获取数据时,如果为空,最多等待时间(最后没数据,未获取到)。
        #如果没有则立刻返回会造成空循环次数过多,cpu占用率飙升 
                          
    SCHEDULER_DUPEFILTER_KEY = '%(spider)s:dupefilter'      
        # 去重规则,在redis中保存时对应的key 
        # import redis
        # conn = redis.Redis(host='127.0.0.1',port=6379)
        # v=conn.keys()
        # print(v)
            
    SCHEDULER_DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter'
    # 如果只用scrapy_redis调度器,就用下面的scrapy本身去重
    # SCHEDULER_DUPEFILTER_CLASS = 'scrapy.dupefilter.RFPDupeFilter'
        # 去重规则对应处理的类,
        # 将任务request_fingerprint(request)得到的字符串放入去重队列       

    DUPEFILTER_DEBUG = False
View Code

4、pipline持久化,item保存到redis

from scrapy_redis.pipelines import RedisPipeline

# settings.py配置   67 行
ITEM_PIPELINES={
    'crapy_redis.pipelines.RedisPipeline':400,
    }
    
# scrapy-redis提供了一个pipeline组件,可以帮我们把item存到redis中
# import redis
# conn = redis.Redis(host='127.0.0.1',port=6379)
# v = conn.keys()  # 取值
# print(v)
# conn.flushall()  # 清空redis数据
# 然后不停的生产(往redis中放数据),接着不停的存到某处(消费者)
# 将item持久化到redis时,指定key和序列化函数 
    # REDIS_ITEMS_KEY = '%(spider)s:items' 
    # REDIS_ITEMS_SERIALIZER = 'json.dumps'
View Code

 

posted @ 2018-06-05 18:12  nick560  阅读(131)  评论(0编辑  收藏  举报