scrapy-redis基础和介绍

我是基于最新版本(0.6版)的 scrapy-redis 来胡说八道的


一、scrapy-redis(0.6)依赖的环境

Scrapy >= 1.0.0                #终于过了1版本,这个太重要了,总算坑小了点,感谢那些为了解决各种scrapy与scrapy-redis不兼容做出了贡献的开发者和博主。
redis-py >= 2.10.0
redis server >= 2.8.0

0.6版本的主要更新内容是更新代码以支持Scrapy 1.0; 增加了-a domain=... option for example spiders.

官方源代码

二、scrapy-redis的作用和特点

作用:scrapy-redis为Scrapy提供Redis-backed组件

特点: 可以启动多个爬虫实例共享一个单一的 redis队列。最适合广泛的多域爬虫。

分布式的post处理。scrapy到的items放入一个redis队列意味着可以分享这个items队列,并在其中启用足够多的post处理进程。

三、scrapy和scrapy-redis的区别与组件的意义

scrapy 是一个通用的爬虫框架
scrapy-redis是为了更方便地实现scrapy分布式爬取,而提供了一些以redis为基础的组件( 仅有组件)
scrapy-redis提供了下面四种组件(components):( 四种组件意味着这四个模块都要做相应的修改)
Scheduler Duplication Filter Item Pipeline Base Spider

scrapy改造了python本来的collection.deque形成了自己的scrqueue( 得意自己取得名字) 传送门: queuelib/queuelib/queue.py源码
scrapy多个spider不能共享待爬取队列scrqueue, 即scrapy本身不支持爬虫分布式,解决是把这个 scrqueue换成redis数据库也是指redis队列),从同一个redis-server存放要爬取的request,便能让多个spider去同一个数据库里读取。

scrapy中跟“待爬队列”直接相关的就是调度器“ Scheduler”,它负责对新的request进行入列操作(加入scrqueue),取出下一个要爬取的request(从scrqueue中取出)等操作。它把待爬队列按照优先级建立了一个字典结构,比如:
{
priority0:队列0
priority1:队列2
priority2:队列2
}
然后根据request中的priority属性,来决定该入哪个队列。而出列时,则按priority较小的优先出列。为了管理这个比较高级的队列字典,Scheduler需要提供一系列的方法。原来的Scheduler已经无法使用(被替换掉了,注意上一个红色字段),所以使用scrapy-redis的 scheduler组件。

scrapy中用集合实现这个request去重功能,scrapy中把已经发送的request指纹放入到一个集合中,把下一个request的指纹拿到集合中比对,如果该指纹存在于集合中,说明这个request发送过了,如果没有则继续操作。( 源码传送)这个核心的判重功能是这样实现的:
</pre></div></blockquote><pre name="code" class="plain">def request_seen(self, request):
    #self.figerprints就是一个指纹集合
    fp = self.request_fingerprint(request)
    if fp in self.fingerprints:#这就是判重的核心操作。
        return True
    self.fingerprints.add(fp)
    ......

在scrapy-redis中去重是由Duplication Filter组件来实现的。

四、最快的安装和启用

安装:

$ pip install scrapy-redis 
或者 
$ git clone https://github.com/darkrho/scrapy-redis.git
$ cd scrapy-redis
$ python setup.py install
  在 settings.py 中启用组件们:
</pre></blockquote><pre name="code" class="plain"># Enables scheduling storing requests queue in redis.
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
</pre></div></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="white-space:pre"></span><pre code_snippet_id="1682225" snippet_file_name="blog_20160513_16_2220405" name="code" class="python"># Don't cleanup redis queues, allows to pause/resume crawls.
SCHEDULER_PERSIST = True
</pre></div></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="white-space:pre"></span><pre code_snippet_id="1682225" snippet_file_name="blog_20160513_19_5349541" name="code" class="python"># Schedule requests using a priority queue. (default)
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderPriorityQueue'
</pre></div></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="white-space:pre"></span><pre code_snippet_id="1682225" snippet_file_name="blog_20160513_22_4193298" name="code" class="python"># Schedule requests using a queue (FIFO).
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderQueue'
</pre></div></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="white-space:pre"></span><pre code_snippet_id="1682225" snippet_file_name="blog_20160513_25_5337568" name="code" class="python"># Schedule requests using a stack (LIFO).
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderStack'
</pre></div></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="white-space:pre"></span><pre code_snippet_id="1682225" snippet_file_name="blog_20160513_28_6547876" name="code" class="python"># Max idle time to prevent the spider from being closed when distributed crawling.
# This only works if queue class is SpiderQueue or SpiderStack,
# and may also block the same time when your spider start at the first time (because the queue is empty).
SCHEDULER_IDLE_BEFORE_CLOSE = 10
</pre></div></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="white-space:pre"></span><pre code_snippet_id="1682225" snippet_file_name="blog_20160513_33_5980278" name="code" class="python"># Store scraped item in redis for post-processing.
ITEM_PIPELINES = {
    'scrapy_redis.pipelines.RedisPipeline': 300
}
</pre></div></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="white-space:pre"></span><pre code_snippet_id="1682225" snippet_file_name="blog_20160513_38_8651283" name="code" class="python"># Specify the host and port to use when connecting to Redis (optional).
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
</pre></div></blockquote><blockquote style="margin:0 0 0 40px; border:none; padding:0px"><div><span style="white-space:pre"></span><pre code_snippet_id="1682225" snippet_file_name="blog_20160513_42_1638716" name="code" class="python"># Specify the full Redis URL for connecting (optional).
# If set, this takes precedence over the REDIS_HOST and REDIS_PORT settings.
REDIS_URL = 'redis://user:pass@hostname:9001'


五、通过redis来喂饱爬虫们~

scrapy_redis.spiders.RedisSpider类启用了爬虫通过redis得到urls,这些在redis队列中的爬虫将会一个接一个的被处理,!!如果第一个request产生了更多的request,爬虫会先处理这些请求,再从redis队列中抓取其他url。

上面偷懒,这里举个栗子:创建 couxiaoxiao.py

from scrapy_redis.spiders import RedisSpider
</pre></div><div><pre code_snippet_id="1682225" snippet_file_name="blog_20160513_47_2390110" name="code" class="python">class MySpider(RedisSpider):
    name = 'myspider'
</pre></div><div><pre code_snippet_id="1682225" snippet_file_name="blog_20160513_50_2662327" name="code" class="python">    def parse(self, response):
        # do stuff
        pass

运行爬虫
scrapy runspider myspider.py
向redis中装入url们
redis-cli lpush myspider:start_urls http://xiaowangzhi.com

六、内容待续。。。有关注的技术方向请评论



  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值