先给结论:限流发生时,不要立刻重跑整批任务,而是把已抓到的结果先落盘、标记完成状态,再只对失败或未开始的条目做增量续跑。这样做的原因是,限流通常只影响请求节奏,不会让已经写入本地的数据失效;真正会造成损失的是脚本在异常退出时把内存里的结果一起丢掉,或者下一次运行覆盖了旧文件。
选择续跑还是重跑,取决于结果是否已经持久化,以及条目是否带有可判定的完成标记。
可区分的证据是:查看输出文件的行数与本次已处理条目数是否一致,以及文件里是否存在部分写入的残缺行。如果行数明显少于已处理数,说明写入环节有问题,而不是限流本身造成的。
收到限流响应后,脚本应停止发起新请求,把当前批次的结果和进度状态写入一个独立文件,例如带时间戳的 progress.json,记录已完成的唯一键列表和最后成功的位置。这个动作的结果是:即使后续进程被终止,也能从断点恢复,而不必依赖内存。
接着检查限流响应的类型。如果是明确的频率限制提示,等待一段时间后降低并发数即可;如果是账号或权限层面的拒绝,继续重试不会改善,需要先处理凭据或配额问题。两种情况的下一步不同,混在一起重试会掩盖真正原因。
续跑的实现要点是读取已有结果、构建已完成集合、只处理差集。假设一次任务计划查询 500 个条目,限流前成功写入 180 条,那么续跑应只针对剩余 320 条,而不是重新查询全部 500 条。这是假设示例,用于说明差集比较的方法,不代表任何真实项目的数量。
写入方式建议改为追加模式,并在每条记录中带上查询时间和状态字段。这样后续核对时能区分“当时查到的结果”和“本次新增的结果”,避免新旧数据混在一起无法判断来源。如果工具本身不支持增量,至少要在文件名或目录上体现批次,不要直接覆盖上一批。
有三种例外需要单独处理。第一,查询结果本身依赖实时状态,间隔太久后续跑得到的值已经不可比,此时应重新定义批次边界,而不是把新旧结果拼在一起。第二,限流原因是账号级封禁,续跑前必须先确认访问是否恢复,否则只是重复失败。第三,条目之间有关联依赖,比如后一条需要前一条的输出,那么跳过失败项会导致后续结果不完整,需要按依赖顺序回退到最近的完整节点。
另外,请求量或抓取量突然归零,不能单独证明限流已经解除。它也可能是网络中断、脚本提前退出或目标端返回空结果造成的。要结合响应状态、日志时间戳和已完成条目数一起判断,再决定是否继续。
可执行的做法是:在每次请求成功后立即追加写入并更新进度文件,而不是等整批结束再统一保存;在捕获限流异常时先落盘再退出;续跑入口默认读取进度文件,只有显式指定时才全量重跑。这样做的结果是,限流从“可能丢失全部结果的事故”变成“损失当前一条请求的可恢复中断”,下一步只需按进度补跑即可。