Scrapy-Redis简单使用

首先,官方GitHub地址

https://github.com/rmax/scrapy-redis

特征
1。分布式抓取/抓取
您可以启动共享单个redis队列的多个spider实例。Y适合广泛的多域抓取。
2。分布式后处理
Scraped项目被推送到redis排队,这意味着您可以在共享项目队列的所需后处理过程中启动。
3。Scrapy即插即用组件
调度程序+复制过滤器,项目管道,基础蜘蛛。

使用环境

redis scrapy scrapy-redis 就够了。
scrapy-redis 分布式爬虫。多台电脑共同运行,数据保存在Redis中。确保服务器端redis开启了远程连接。

用于提醒自己的(不确定对不对),scrapy-redis服务器端只是提供了一个redis服务器。只是提供了一个redis服务器,只是提供了一个redis服务器。
所以只要是要进行爬虫,那它充当的就是一个slave,但是,一个电脑是可以既是master又是slave的。。。

就爬取读书网的新闻测试一下吧。官方建议的 http://www.dmoz.org/ 好像关掉了。这个也没关系,本来这篇博客就是个人复习使用,有看到的大神觉得哪里错了指出来呗。
https://www.dushu.com/

1。开始创建项目。按照基本的scrapy项目那样创建。

-> scrapy startproject myscrapy_redis
-> scrapy genpider myspider

创建完成
2。settings.py文件修改。将官网的文件复制到自己的settings.py文件就好。

# Enables scheduling storing requests queue in redis.
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

# Ensure all spiders share same duplicates filter through redis.
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

# Default requests serializer is pickle, but it can be changed to any module
# with loads and dumps functions. Note that pickle is not compatible between
# python versions.
# Caveat: In python 3.x, the serializer must return strings keys and support
# bytes as values. Because of this reason the json or msgpack module will not
# work by default. In python 2.x there is no such issue and you can use
# 'json' or 'msgpack' as serializers.
#SCHEDULER_SERIALIZER = "scrapy_redis.picklecompat"

# Don't cleanup redis queues, allows to pause/resume crawls.
#SCHEDULER_PERSIST = True

# Schedule requests using a priority queue. (default)
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'

# Alternative queues.
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'
#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'

# 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

# Store scraped item in redis for post-processing.
ITEM_PIPELINES = {
    'scrapy_redis.pipelines.RedisPipeline': 300
}

# The item pipeline serializes and stores the items in this redis key.
#REDIS_ITEMS_KEY = '%(spider)s:items'

# The items serializer is by default ScrapyJSONEncoder. You can use any
# importable path to a callable object.
#REDIS_ITEMS_SERIALIZER = 'json.dumps'

# Specify the host and port to use when connecting to Redis (optional).
#REDIS_HOST = 'localhost'
#REDIS_PORT = 6379

# 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'

# Custom redis client parameters (i.e.: socket timeout, etc.)
#REDIS_PARAMS  = {}
# Use custom redis client class.
#REDIS_PARAMS['redis_cls'] = 'myproject.RedisClient'

# If True, it uses redis' ``SPOP`` operation. You have to use the ``SADD``
# command to add URLs to the redis queue. This could be useful if you
# want to avoid duplicates in your start urls list and the order of
# processing does not matter.
#REDIS_START_URLS_AS_SET = False

# Default start urls key for RedisSpider and RedisCrawlSpider.
#REDIS_START_URLS_KEY = '%(name)s:start_urls'

# Use other encoding than utf-8 for redis.
#REDIS_ENCODING = 'latin1'

没有被注释的就三个地方,替换掉了原来的调度器和去重器。采用scrapy-redis的调度器和去重器。然后指定了item管道 RedisPipeline。

3。修改爬虫文件。与一般scrapy项目的爬虫文件相比。继承的类发生了改变

import scrapy
from scrapy_redis.spiders import RedisSpider


class MovieinfoSpider(RedisSpider):
    name = 'movieInfo'

    def parse(self, response):

        # 提取下一页链接   callback为None 继续在该parse中解析
        next_page = response.xpath("//a[contains(text(), '下一页')]/@href")
        print(next_page)
        if next_page:   # 如果存在下一页
            yield scrapy.Request(response.urljoin(next_page.get()))

        # 提取详情页 callback 指向解析详情页
        news_detail_page_list = response.xpath("//div[contains(@class, 'news-item')]/h3/a")
        for news_detail_page in news_detail_page_list:
            yield response.follow(news_detail_page, callback=self.parse_detail)

    def parse_detail(self, response):
        title = response.xpath("//h1/text()").get()
        print(title)
        yield {'title': title}

观察该文件,发现少了 start_urls和start_request()函数,没有了起始任务队列和请求开始函数。因为是scrapy-redis,任务队列存放在redis服务器中,由调度器获取。
不过此时由于设置中没有设置连接,是连不上redis的,所以启动不能成功。

4。修改settings.py
关于slave连接服务器的redis,有两种方式
(1)REDIS_HOST表示ip地址 REDIS_PORT表示端口号,去掉注释将地址端口号修改成自己的即可。

REDIS_HOST = '192.168.0.104'
REDIS_PORT = 6379

(2)#REDIS_URL = ‘redis://user:pass@hostname:9001’ 用户名密码 ip端口,可以将这一行注释去掉修改成自己的, 比如

REDIS_URL = 'redis://192.168.0.104:6379'

方式2 如果设置了 会替换掉方式1的设置。。。

调度器从redis服务器中取请求,管道向redis存数据时。使用的默认key值。
任务队列的key 爬虫名:starturls, 比如爬虫名字是 myspider那么key就是
myspider:start_urls

# Default start urls key for RedisSpider and RedisCrawlSpider.
#REDIS_START_URLS_KEY = '%(name)s:start_urls'

item数据的key 爬虫名:items 如 myspider:items

# The item pipeline serializes and stores the items in this redis key.
#REDIS_ITEMS_KEY = '%(spider)s:items'

注:如果不做修改, 那么爬虫文件运行时,调度器会从redis服务器中获取key 为myspider:start_urls的set中值。

5。如果不喜欢默认的key值,可以自己进行替换。
替换方式一, settings中设置。比如直接settings中设置请求队列的key

REDIS_START_URLS_KEY = 'myspider:start_urls'

如此就将默认的key设置成了myspider:start_urls,我没有改变默认值,如果想改变,可以自行尝试。item存储的key也是一样的。
替换方式二,爬虫文件中设置 redis_key属性。比如,这样修改了请求队列的key,至于item存储的key,好像只能从settings中修改。

redis_key = 'myspider:start_urls'

6。可以将项目部署到不同机器上,只要能连接上服务器的redis。然后启动爬虫。
启动方式与一般scrapy相同。不同的是,该种方式启动后会一直运行,调度器会一直监听redis服务器的任务队列keys中是否有元素。

-> scrapy crawl myspider

同时运行
启动了一个虚拟机,和windows下程序一同启动爬虫。可以看到,程序一直在等待。因为初始时,我们的根本就没有该key值,可以用redis-cli连接redis服务器,放入一个初始值。myspider:start_urls 就是一个key

redis-cli->lpush myspider:start_urls https://www.dushu.com/news/

放入初始值
同时爬取网页
7。运行过程中 可以中断运行,而在此启动时,会继续获取值,且不会有重复。
三个数据
第一个就是查重的,每个请求都会生成一个唯一序列字符串标识,当再次受到该请求,发现redis库中已存在该标识,就不再发送该请求。
第二个就是已经存储的item
第三个是带请求的request队列
(看官方文档还是其他博客)似乎说有四个key,这个 我就不清楚了,但是三个key应该也可以解释去重 调度 item管道了。

8。继续运行。。。直到停止(并不是指程序运行结束,而是长时间没有获取新请求)。
其实如果没出错 最后redis中存储的数据数量挺有意思的。。。
120个item,正好是 15*8页, 而去重的列表有127条数据。。。也就是说,除了初始的请求没有生成序列,其他的每个网页请求都生成了一个唯一标识。。。
这算数应该会算吧。。。

发布了59 篇原创文章 · 获赞 11 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/dandanfengyun/article/details/104212713
今日推荐