(十八)暂停、关闭,再从已提交进度继续
1. 比较两次启动实际发出的请求
先保存两本,关闭 SQLite,再打开同一文件继续:
# 项目文件:demos/resume_run.py
# 两次打开同一个进度库;第二次只采剩余详情,目录页和前两本不再重复请求。
import asyncio
from pathlib import Path
from tempfile import TemporaryDirectory
from crawlsite import running_site
from catalogcrawl.runner import crawl
from catalogcrawl.state import CrawlState
if __name__ == "__main__":
with running_site() as site, TemporaryDirectory() as folder:
path = Path(folder) / "crawl.sqlite3"
start = site.base_url + "/catalog/?page=1"
with CrawlState(path, start) as state:
asyncio.run(crawl(state, interval=0, stop_after=2))
print("暂停", state.stats())
with CrawlState(path, start) as state:
asyncio.run(crawl(state, interval=0))
print("恢复", state.stats())
print("目录请求", site.state.counts["/catalog/"])
print("第一本请求", site.state.counts["/books/b101"])第一次输出中,三页目录都已提交,详情完成 2 项、待处理 4 项,items 为 2。第二次详情完成变为 6、待处理为 0、items 为 6。最后的目录请求仍为 3 次,第一本请求仍为 1 次。
第二次启动从 jobs 的 done=0 选择 b103 至 b106,没有重新翻三页目录,也没有重新读取前两本。恢复依据是库里已经提交的任务状态,不是某个仍然活着的 Python 列表。
2. 区分单项失败与本次暂停
如果 b103 持续返回 503,它在本次尝试三次后仍留待处理,其他五本可以先保存。修好服务后再次启动,只选到 b103;成功提交后六本齐全。缺少 h1 的详情也会留待处理,但它已经拿到 HTML,不做三次相同的网络重试。
程序在两项请求之间退出时,已经提交的结果保留;当前批只是取得了响应、还没有提交时,重启后会再读一次这些待处理项。GET 重读与源站编号去重共同让这次重新尝试得到同一组记录。