Scrapyd 和 ScrapydAPI 的使用
在上一章中,我们学习了 Scrapy 框架,利用它可以快速开发一个爬虫程序。Scrapyd又是什么呢?跟Scrapy相比,Scrapyd多了一个字母d,这个d其实就是部署(deploy)的意思,所以Scrapyd就是为了方便管理和部署Scrapy爬虫程序而诞生的。本节中,我们先简单了解下Scrapyd及其用法。
了解 Scrapyd
Scrapyd 是一个运行Scrapy爬虫的服务程序,它提供一系列HTTP接口来帮助我们部署、启动、停止和删除爬虫程序。Scrapyd支持版本管理,同时还可以管理多个爬虫任务,利用它我们可以非常方便地完成Scrapy爬虫项目的部署任务调度。
准备工作
请确保本机或服务器已经正确安装好了 Scrapyd, 安装命令如下:
pip3 install scrapyd
更详细的安装流程可以参考: https://setup.scrape.center/scrapyd 。
安装并完成 Scrapyd 相应的配置之后, 我们直接输入 scrapyd 即可启动对应的服务, 命令如下:
scrapyd
运行之后, 会有类似如下的输出:
[Launcher] Scrapyd 1.2.1 started: max_proc=8, runner='scrapyd.runner'
这就代表 Scrapyd 已经启动成功了。
访问 Scrapyd
Scrapyd 默认会在6800端口上运行。访问服务器的6800端口,我们就可以看到一个WebUI页面了。本案例中,我们依然在A(192.168.2.3)服务器上启动Scrapyd服务。启动完成之后,我们打开 http://192.168.2.3:6800/ ,即可看到类似如图17-1所示的页面。
图 17-1 Scrapyd 页面
如果可以成功访问到此页面,那么证明 Scrapyd 配置就没有问题了。
如果访问失败,那 Scrapyd 监听的地址很有可能是 127.0.0.1,这是默认配置。此时可以修改 scrapyd.conf 文件,将 bind_address 修改为 0.0.0.0,具体可以参见 https://scrapyd.readthedocs.io/en/stable/config.html#config 。
比如,可以在当前命令行行在目录下新建一个 scrapyd.conf 文件,将其内容进行如下修改:
[scrapyd]
bind_address = 0.0.0.0
http_port = 6800
这样就指定了 Scrapyd 可以被公开访问,同时运行在 6800 端口。修改完成之后,再次重启 Scrapyd, 它应该就可以被访问到了。
Scrapyd 的功能
Scrapyd 提供了一系列 HTTP 接口来实现各种操作,这里我们可以将接口的功能梳理一下,以 Scrapyd 所在的 IP 192.168.2.3 为例来进行说明。
|
此处使用 curl 命令来模拟 HTTP 的各种请求,你也可以使用其他工具(如 Postman、Python 等)来进行请求,效果都是一样的。另外,这里使用的 IP 是 A 主机的 IP,请自行替换为你的 Scrapyd 服务所在主机的 IP。 |
daemonstatus.json
这个接口负责查看 Scrapyd 当前的服务和任务状态,我们可以用 curl 命令来请求这个接口,具体如下:
curl http://192.168.2.3:6800/daemonstatus.json
这样我们就会得到如下结果:
{"status": "ok", "finished": 90, "running": 9, "node_name": "vm1", "pending": 0}
返回结果是JSON字符串,其中status是当前运行状态,finished代表当前已经完成的Scrapy任务,running代表正在运行的Scrapy任务,pending代表等待被调度的Scrapyd任务,node_name就是主机的名称。
addversion.json
这个接口主要用来部署 Scrapy 项目。在部署的时候,我们首先要将项目打包成 egg 文件,然后传入项目名称和部署版本。
我们可以用如下方式实现项目部署:
curl http://192.168.2.3:6800/addversion.json -F project=<project_name> -F version=v1 -F egg=@<project_name>.egg
这里 -F 即代表添加一个参数,同时我们还需要将项目打包成 egg 文件放到本地。另外,还需要将 <project_name> 替换成真实的项目名称。
这样发出请求之后,我们可以得到类似如下结果:
{"status": "ok", "spiders": 3}
这个结果表明部署成功,并且其中包含的 Spider 的数量为 3。
|
Spider 的数量视具体的项目为准,不同的项目包含的 Spider 数量可能不同,此处样例为 3。 |
使用此方法部署可能比较麻烦,后文会介绍更方便的工具来实现项目的部署。
schedule.json
部署完成之后,项目其实就存在于 Scrapyd 之上了,那么怎么来运行这个 Scrapy 项目呢?此时可以借助 schedule.json 这个接口,它负责调度已部署好的 Scrapy 项目。
我们可以用如下方式实现任务调度:
curl http://192.168.2.3:6800/schedule.json -d project=<project_name> -d spider=<spider_name>
这里需要传入两个参数:project 即 Scrapy 项目名称,spider 即 Spider 名称。
返回结果类似如下:
{"status": "ok", "jobid": "6487ec79947edab326d6db28a2d86511e8247444"}
其中 status 代表 Scrapy 项目启动情况,jobid 代表当前正在运行的爬取任务代号。
类似于执行了如下命令:
scrapy crawl <spider_name>
这就相当于 Scrapyd 启动了对应项目的一个 Spider。Spider 是由 Scrapyd 运行的,运行之后就相当于运行了一个任务,其任务标识号就是 jobid,我们可以根据这个 jobid 来查看或操作该 Spider 的运行状态。
cancel.json
这个接口可以用来取消某个爬取任务。如果这个任务是 pending 状态,那么它将会被移除;如果这个任务是 running 状态,那么它将会被终止。
我们可以用下面的命令来取消任务的运行:
curl http://192.168.2.3:6800/cancel.json -d project=<project_name> -d job=6487ec79947edab326d6db28a2d86511e8247444
这里需要传入两个参数:project 即项目名称,job 即爬取任务的代号,其值就是上文所说的 schedule.json 接口返回的 jobid 的内容。
返回结果如下:
{"status": "ok", "prevstate": "running"}
其中 status 代表请求执行情况,prevstate 代表之前的运行状态。
listprojects.json
这个接口用来列出部署到 Scrapyd 服务上的所有项目的描述信息。
我们可以用下面的命令来获取 Scrapyd 服务器上的所有项目描述:
curl http://192.168.2.3:6800/listprojects.json
这里不需要传入任何参数。
返回结果类似如下:
{"status": "ok", "projects": ["project1", "project2"]}
其中 status 代表请求执行情况,projects 是项目名称列表。
listversions.json
这个接口用来获取某个项目的所有版本号。版本号是按顺序排列的,其最后一个条目是最新版本号。
我们可以用如下命令来获取项目的版本号:
curl http://192.168.2.3:6800/listversions.json?project=<project_name>
这里需要用到参数 project,就是项目的名称。
返回结果如下:
{"status": "ok", "versions": ["v1", "v2"]}
其中 status 代表请求执行情况,versions 是版本号列表。
listspiders.json
这个接口用来获取某个项目最新的一个版本的所有 Spider 名称。
我们可以用如下命令来获取项目的 Spider 名称:
这里需要用到参数 project,就是项目的名称。
返回结果类似如下:
{"status": "ok", "spiders": ["spider1"]}
其中 status 代表请求执行情况,spiders 是 Spider 名称列表。
listjobs.json
这个接口用来获取某个项目 当前运行的所有任务详情。
我们可以用如下命令来获取所有任务详情:
curl http://192.168.2.3:6800/listjobs.json?project=project
这里需要用到参数 project,就是项目的名称。
返回结果如下:
{"status": "ok", "pending": [{"id": "78391cc0fcaf11e1b0090800272a6d06", "spider": "spider1"}], "running": [{"id": "422e608f9f28cef127b3d5ef93fe99399", "spider": "spider1", "start_time": "2020-07-12 10:14:03.594664"}], "finished": [{"id": "2f16646cfcaf11e1b0090800272a6d06", "spider": "spider1", "start_time": "2020-07-12 10:14:03.594664", "end_time": "2020-07-12 10:24:03.594664"}]}
其中 status 代表请求执行情况,pending 代表当前正在等待的任务,running 代表当前正在运行的任务,finished 代表已经完成的任务。
ScrapydAPI 的使用
以上这些接口用起来可能还不是很方便,没关系,ScrapyAPI 库对这些接口又做了一层封装,使用 pip3 即可安装它:
pip3 install python-scrapyd-api
下面我们来看看 ScrapydAPI 的使用方法,其核心原理和 HTTP 请求方式并无二致,只不过用 Python 封装后使用更加便捷。
我们可以用如下方式建立一个 ScrapydAPI 对象:
from scrapyd_api import ScrapydAPI
scrapyd = ScrapydAPI('http://192.168.2.3:6800')
然后就可以调用它的方法来实现对应接口的操作了,例如部署操作可以使用如下方式:
egg = open('project.egg', 'rb')
scrapyd.add_version('project', 'v1', egg)
这样我们就可以将项目打包为 egg 文件,然后把本地打包的 egg 项目部署到远程 Scrapyd 了。
另外,ScrapydAPI 还实现了所有 Scrapyd 提供的 API 接口,名称都是相同的,参数也是相同的。
例如,我们调用 list_projects 方法即可列出 Scrapyd 中所有已部署的项目:
scrapyd.list_projects()
['project1', 'project2']
另外,其他方法在此不再一一列举了,名称和参数都是相同的,更加详细的操作可以参考其官方文档: http://python-scrapyd-api.readthedocs.io/ 。