作者:Zarten 知乎专栏:Python爬虫深入详解 知乎ID: Zarten 简介: 互联网一线工作者,尊重原创并欢迎评论留言指出不足之处,也希望多些关注和点赞是给作者最好的鼓励 !
Scrapy-redis概述
scrapy-redis是分布式爬虫较通用简单的框架,我们都知道scrapy框架不支持分布式的,scrapy-redis是以redis为基础的组件。
简单点说,scrapy-redis代替了scrapy中原有的一些队列,而是存在redis中,多台爬虫机器来共享redis里面的一些队列,从而达到一个分布式爬虫效果
Scrapy-redis用法
1.当然是需要在master机器上安装redis
2.在scrapy爬虫机器(Slaver)上安装scrapy-redis 命令为:
pip install scrapy-redis
3.只需在settings.py中相应设置就可以了,任务调度工作scrapy-redis已经帮我们做好了
4.在每个爬虫机器(slaver)上启动scrapy即可
- SCHEDULER = "scrapy_redis.scheduler.Scheduler"
使用scrapy-redis里的调度器对所有爬虫机器统一调度,替换了scrapy里的调度器
- DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
使用scrapy-redis中的去重组件,代替scrapy中的去重队列
- REDIS_HOST = '127.0.0.1'REDIS_PORT = 6379REDIS_PARAMS = { 'password' : 'longqi'}
设置redis配置,不要密码可注释掉
上面通常都是要设置的,下面的可以选择性设置
- ITEM_PIPELINES = { 'scrapy_redis.pipelines.RedisPipeline': 300}
将scrapy中的item存在redis中
- SCHEDULER_PERSIST = True
爬虫结束后不会清空redis中的队列(去重队列),方便断点续爬
- SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'
这个是默认的,不需要设置,优先级排序的队列。若需要设置别的方式如下:
先进先出队列:
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'
后进先出队列:
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'
从redis中启动爬虫
若多机器集群爬虫,可以将start_urls写入redis,从而从redis来启动整个爬虫集群。
步骤:
1.每个爬虫继承RedisSpider
from
2.每个爬虫中添加redis的key:redis_key
将starturls换成rediskey,格式为:爬虫名:start_urls 。注意:不是工程名,是爬虫名
redis_key = '爬虫名:start_urls'
3.启动爬虫集群
4.向redis中的redis_key注入开始的url,若有多个初始url,只需多次注入即可(即多次执行下面代码)
import
注:上面从redis启动时只能传入一个url,若有相应的参数(额外信息传递)可用如下方法
1.在上面现有代码中添加(改写)next_requests方法
def
2.注入初始url及额外信息即可
redis_pool
Scrapyd概述
scrapyd是部署scrapy分布式爬虫的工具,爬虫机器只需安装scrapyd的web服务,远程客户端就可以轻松在这台scrapyd机器上部署scrapy爬虫代码。也可以访问scrapyd的相应的url查看scrapy运行状态和scrapy日志信息。
Scrapyd使用
- scrapyd安装
pip3 install scrapyd
安装完成后,需要修改一下配置文件,更改默认绑定的地址,以便外网可以访问,修改如下:
bind_address = 0.0.0.0
配置文件路径:
linux:
/etc/scrapyd/scrapyd.conf
windows在python的安装路径下:
python路径Libsite-packagesscrapyddefault_scrapyd.conf
启动scrapyd:
scrapyd
访问scrapyd服务:
默认端口为:6800
http://ip:6800 ,界面如下:
scrapyd使用
scrapyd安装并在爬虫机器后台运行起来后,我们就要开始部署scrapy代码和访问等。scrapyd提供了主要2种方式来访问:
- http形式的json API
- scrapydAPI方式
http形式的json API
1.部署scrapy代码
curl http://localhost:6800/addversion.json -F project=myproject -F version=r23 -F egg=@myproject.egg
project:scrapy项目名称
version:版本信息
不过每次这样部署好像有点麻烦,这里有个Scrapyd-client工具来部署非常方便
Scrapyd-client使用
scrapyd-client安装:
pip3 install scrapyd-client
测试是否安装成功(出现帮助信息,正确):
scrapyd-deploy -h
scrapyd-client使用:
在scrapy项目中的scrapy.cfg文件中,设置如下:
设置完成后,用命令行切换到scrapy项目所在路径下:
scrapyd-deploy 名称
Scrapyd版本
设想一下这样的场景:若一个scrapy工程中有若干个爬虫spider正在运行,突然有一个爬虫出现bug不工作了,其他爬虫还在正常工作,这时我们不可能说修复好bug后,停止其他所有爬虫然后删除项目,重新将修改好的项目部署到scrapyd上吧?这时设置版本的重要性不言而喻!
我们可以修复好bug后,重新部署到scrapyd,但这时我们可以打个新的版本号,启动新的版本号的爬虫spider就可以了,其他爬虫还在旧版本里正常运行中。
- 设置版本
设置版本有2种方法:
1.scrapyd-client 工具命令时 后面加参数 --version ,这里版本号最好是有顺序的,像这样:r1 r2 r3
scrapyd-deploy Zarten --version r1
2.在scrapy.cfg文件中
[deploy:Zarten]
url = http://192.168.2.227:6800/
project = scrapy_redis_test
version = r1
后面有介绍如何启动带版本号的项目
2.查看运行状态
curl http://localhost:6800/daemonstatus.json
还有很多http接口,这里将不一一介绍了,我这里将主要介绍下面的scrapydAPI方式,对http接口感兴趣的可以参考这里
scrapydAPI方式
这种方式可以在程序里面方便的控制和查看等操作
- 安装
pip3 install python-scrapyd-api
- 用法
from scrapyd_api import ScrapydAPI
scrapyd = ScrapydAPI('http://localhost:6800')
- API方法
1.add_version(project, version, egg)
部署项目,可以指定版本,这里推荐使用上面介绍的scrapyd-client工具
2.schedule(project, spider, settings=None, **kwargs)
启动远程爬虫机器的scrapy
参数解析:
project:scrapy工程名称
spider:爬虫名称
settings:dict 重写scrapy中的settings
_version:str类型,指定版本号
job_id_Zarten = scrapyd_Zarten.schedule('scrapy_redis_test', 'quotes', _version='r2')
kwargs:自定义额外参数传递给scrapy的init函数
调用方法如下所示:
scrapyd_obj
_init_函数如下所示:
def __init__(self, keyword_id, search_keyword, **kwargs):
self.keyword_id = keyword_id
self.search_keyword = search_keyword
返回值:
返回启动爬虫后的job id
3.job_status(project, job_id)
查看爬虫运行状态
参数解析:
project:scrapy工程名称
job_id:爬虫对应的唯一id,schedule方法会返回此值,如下:
返回值:
返回4种状态:
'running':正在运行
'pending':准备运行
'finished':完成运行
'':若不能找到job_id,返回空
4.cancel(project, job, signal=None)
取消(停止)正在或准备运行的爬虫
参数解析:
project:scrapy工程名称
job:爬虫的job_id
signal:终止的信号,一般为None
返回值:
返回爬虫停止前的状态
注:有时运行中的爬虫不管用API还是命令行都无法停止,这里提供一种解决方案:
直接杀死进程
1.查看spider的pid
2.进入爬虫机器,如果是docker运行,则命令如下
docker exec -it 容器id kill -9 你的pid
5.delete_project(project)
删除爬虫项目
参数解析:
project:scrapy工程名
返回值:
成功返回 True 否则返回 False
6.delete_version(project, version)
删除指定的版本的scrapy的项目
参数解析:
project:scrapy项目名称
version:版本名称
返回值:
成功返回 True 否则返回 False
7.list_projects()
显示当前可用的scrapy项目
返回值:
list 所有scrapy工程名
8.list_spiders(project)
显示指定scrapy项目的所有爬虫
参数解析:
project:scrapy项目名称
返回值:
list 所有爬虫名称
9.list_versions(project)
显示指定scrapy项目的所有版本号
参数解析:
project:scrapy项目名称
返回值:
list 所有可用版本
10.list_jobs(project)
显示指定scrapy项目的所有准备、正在、完成运行的job_id
参数解析:
project:scrapy项目名称
返回值:
dict 所有 pending running finished 的job_id
docker内运行scrapyd
如果不使用docker,则需要在每台爬虫机器中安装scrapyd服务以及爬虫运行所需要的库,若将scrapyd及运行库制作成docker再上传到docker hub,每次只需pull下来运行docker就可以了。
制作docker+scrapyd
一般只需这3个文件即可:
- scrapyd.conf
其实就是复制配置文件(文件位置上面有介绍)过来后,改成 bind_address = 0.0.0.0
[scrapyd]
eggs_dir = eggs
logs_dir = logs
items_dir =
jobs_to_keep = 5
dbs_dir = dbs
max_proc = 0
max_proc_per_cpu = 10
finished_to_keep = 100
poll_interval = 5.0
bind_address = 0.0.0.0
http_port = 6800
debug = off
runner = scrapyd.runner
application = scrapyd.app.application
launcher = scrapyd.launcher.Launcher
webroot = scrapyd.website.Root
[services]
schedule.json = scrapyd.webservice.Schedule
cancel.json = scrapyd.webservice.Cancel
addversion.json = scrapyd.webservice.AddVersion
listprojects.json = scrapyd.webservice.ListProjects
listversions.json = scrapyd.webservice.ListVersions
listspiders.json = scrapyd.webservice.ListSpiders
delproject.json = scrapyd.webservice.DeleteProject
delversion.json = scrapyd.webservice.DeleteVersion
listjobs.json = scrapyd.webservice.ListJobs
daemonstatus.json = scrapyd.webservice.DaemonStatus
- Dockerfile
FROM python:3.6
ADD . /code
WORKDIR /code
COPY ./scrapyd.conf /etc/scrapyd/
EXPOSE 6800
RUN pip3 install -r requirements.txt
CMD scrapyd
- requirements.txt
这里放一些项目所需的库,如果需要更通用点,尽可能多放一些常用的库,这样可以部署更多的项目到scrapyd中。若某个项目中使用的库在docker中找不到,那岂不是要再重新制作docker+scrapyd了?
最后就是制作docker+scrapyd了,具体制作过程查看docker详解那篇文章