欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

scrapy集成scrapy-redis

程序员文章站 2022-04-28 08:36:50
...

背景情况

爬虫由于需要网络请求,一般生产数据都比较慢,如果增加部分浏览器的处理,会更慢,
所以需要增加分布式的处理方案,
比较常见的,是把队列扔到redis中,比较常用的是 scrapy-redis

说明,怎么去搭建一个spider,请查看 https://blog.csdn.net/mingover/article/details/80717974

怎么加入scrapy-redis

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

1,先把代码copy过来,
scrapy-redis不是 用pip安装 的,而是直接把代码copy过来
从githup中下载下来,路径中这个目录copy到我们的目录 中scrapy-redis-master\src\scrapy_redis, 我是 和 scrapy.cfg 平级.

2, settings.py中加上
下面两个是必要的内容,覆盖原来的scheduler

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

3,redis的设定.

依赖了redis,要先pip install redis
scrapy_redis\defaults.py
分析源码的配置,和redis相关的内容
defaults.py:

# Sane connection defaults.
REDIS_PARAMS = {
'socket_timeout': 30,
'socket_connect_timeout': 30,
'retry_on_timeout': True,
'encoding': REDIS_ENCODING
}

connection.py:

SETTINGS_PARAMS_MAP = {
    'REDIS_URL': 'url',
    'REDIS_HOST': 'host',
    'REDIS_PORT': 'port',
    'REDIS_ENCODING': 'encoding',
}

上面是scrapy-redis的源码内容,

配置redis,我们在setting中设定:

REDIS_HOST = "xxx.xxx.xxx.xx"
REDIS_PORT = "xxxx"
REDIS_URL='redis://:密码@XXX:XXX'

如果redis没有密码,REDIS_URL可以不设定.

4 ,业务代码的改动

class ASpider(scrapy.Spider):

改成:

from scrapy_redis.spiders import RedisSpider

class ASpider(RedisSpider):

启动服务&运行

1,第一次启动
启动和之前一样,直接main即可.
不过启动完后,是不会直接运行的,
要在redis中
lpush [spider的名称,如myspider]:start_urls http://xxxx

这里说明了url并不是从代码或配置中拿,是从redis中拿!!

一些关键的 redis key的设定,是在 defaults.py中设定的!

2,关掉后启动,

在运行时,服务会把队列和指纹放在redis中,如果服务关掉了,再启动,服务会从redis拿队列接着跑!!!
在运行时的redis情况:
scrapy集成scrapy-redis

 如果不想接着上一次的任务继续,可以设定 SCHEDULER_FLUSH_ON_START 这个值 为True. 或者,直接把redis中的内容清空.

        kwargs = {
            'persist': settings.getbool('SCHEDULER_PERSIST'),
            'flush_on_start': settings.getbool('SCHEDULER_FLUSH_ON_START'),
            'idle_before_close': settings.getint('SCHEDULER_IDLE_BEFORE_CLOSE'),
        }

启动服务发生了什么?

在main启动的时候,scrapy会触发,
如图,
在 L57行是初始化spider,如设定start_url等
L58是开始,这个时候,会从spider队列中拿数据,如果没有则死循环进行监听redis的内容

scrapy集成scrapy-redis

那监听的时候是先找request队列,还是先找start_url?

去在拿request和拿start_url中各打了断点,进行排查.

request的断点:

next_request, scheduler.py:164
_next_request_from_scheduler, engine.py:149
_next_request, engine.py:122
__call__, reactor.py:41
runUntilCurrent, base.py:896
mainLoop, base.py:1270
run, base.py:1261
start, crawler.py:291
run, crawl.py:58
_run_command, cmdline.py:157
_run_print_help, cmdline.py:90
execute, cmdline.py:150
<module>, main_page.py:10
execfile, _pydev_execfile.py:18
run, pydevd.py:1068
main, pydevd.py:1658
<module>, pydevd.py:1664

start_url的断点:

next_requests, spiders.py:82
schedule_next_requests, spiders.py:115
spider_idle, spiders.py:121
robustApply, robustapply.py:55
send_catch_log, signal.py:30
send_catch_log, signalmanager.py:45
_spider_idle, engine.py:278
_next_request, engine.py:138
__call__, reactor.py:41
runUntilCurrent, base.py:896
mainLoop, base.py:1270
run, base.py:1261
start, crawler.py:291
run, crawl.py:58
_run_command, cmdline.py:157
_run_print_help, cmdline.py:90
execute, cmdline.py:150
<module>, main_page.py:10
execfile, _pydev_execfile.py:18
run, pydevd.py:1068
main, pydevd.py:1658
<module>, pydevd.py:1664

在上面 _next_request, engine.py:122的逻辑可以看出前后 ,就先request,后start_url 的,

关于指纹

关于request生成的指纹用于确认是否已经处理过了.具体的逻辑如下
scrapy集成scrapy-redis
也是通过redis存储

其它的情况

如果发现把start_url扔到redis后没反应,则debug进去看看,有可能 是redis的dbindex 设置错了,
在defaults.py中配置

REDIS_PARAMS = {
....
    'db': 4
}

参考

https://coding.imooc.com/class/92.html

相关标签: scrapy