给爬虫加 JOBDIR 就能暂停和恢复,可是磁盘上到底存了什么?续跑会不会重复或遗漏?kill -9 呢?起始请求会不会重发?请求里有不能序列化的东西又怎样?这篇把每种中断方式都做一遍,数清楚丢了多少、重了多少。
finish_reason=shutdown;这次下载了 18 个页面(+ 起始页);scheduler/enqueued=41、dequeued=19
requests.queue/127.0.0.1-f528764d624db129b32c21fbca0cb8d6/0/info.json 73 字节
requests.queue/127.0.0.1-f528764d624db129b32c21fbca0cb8d6/0/q00000 10510 字节
requests.queue/active.json 18 字节
requests.seen 902 字节
spider.state 135 字节requests.queue/ 存磁盘队列,active.json 记录队列状态,requests.seen 是已见请求的指纹(每个 22 字节),spider.state 是 self.state 的 pickle。
第 2 次:finish_reason=finished;下载了 22 个页面,起始页重发了 0 次(自己写的 start() 没有 dont_filter,被 requests.seen 过滤);dupefilter/filtered=1;scheduler/dequeued=22
两次合计:页面 40 次请求,不同页面 40 个(应为 40),两次重叠的页面 0 个
requests.queue/active.json 2 字节
requests.seen 902 字节
spider.state 267 字节优雅停止(一次 Ctrl-C)后用同一个 JOBDIR 再运行,只处理磁盘队列里剩下的请求,不重复已完成的页面,self.state 的内容继续累加。
spider.state 里的内容:count=40、urls 的个数=40;两次运行各自的 page 回调次数 18 和 22(合计 40)
self.state 里的值必须能 pickle,适合存计数、游标等。
第 3 次(自己写的 start()):服务器收到 0 个请求 [];dupefilter/filtered=1;finish_reason=finished 第 4 次(默认 start_urls):服务器收到 1 个请求 ['/'];dupefilter/filtered=40;finish_reason=finished(起始页重发了,子链接全被过滤)
自己写 start() 且不加 dont_filter 时,续跑里起始请求被 requests.seen 过滤;默认 start_urls 自带 dont_filter=True,会重发。
requests.queue/127.0.0.1-f528764d624db129b32c21fbca0cb8d6/0/q00000 10510 字节
requests.seen 0 字节
kill -9 前下载了 22 个页面;恢复后又下载了 40 个;不同页面共 40 个(完整应为 40),缺 0 个;重叠 22 个
恢复那次:finish_reason=finished;scheduler/dequeued=41kill -9 不会写 requests.seen 和 spider.state,恢复等于重头开始,重复抓取但不会丢页面。
meta 里放 threading.Lock():scheduler/unserializable=40;enqueued/memory=40;enqueued/disk=1 第 1 次下载 16 个页面;恢复后又下载 0 个;不同页面共 16 个(完整应为 40)——内存队列里没落盘的请求在中断时丢了
请求(含 meta、回调)不能 pickle 时只进内存队列,中断即丢,指纹却已入库,这些页面不会再被抓。