限流发生时,最该保护的不是"已抓到的条数",而是"这批结果能不能和未抓部分区分开"。如果脚本没有记录每个请求对应的对象标识和状态,限流后你既不知道哪些已完成、哪些被截断,也无法安全重跑。一个可行做法是:在触发限流的那一刻立即停止写入主结果集,把内存或临时文件中尚未落盘的数据单独存为待确认块,再根据每个对象的完成标记决定是补跑还是放弃。下面以一份"待检测的页面清单"为对象,说明具体怎么落地。
限流后常见的两种做法是:立刻重试直到成功,或者把当前内存数据全部写盘后收工。两者成立的条件不同。
判断依据不是"哪个更快",而是你的结果集是否带对象级完成标记。有标记,重试和收工都安全;没有标记,先补标记再谈策略。
假设你手里有一份 800 条 URL 的清单,脚本逐条调用工具接口获取页面指标。建议在写入结果时,每条记录至少带三个字段:对象标识(如 URL 或页面 ID)、处理状态(待处理 / 已完成 / 被限流中断)、结果摘要。状态字段是关键,它让"限流中断"变成一个可查询的值,而不是靠时间戳猜测。
具体动作:在脚本的请求循环里,把"请求成功并解析完成"作为写入 已完成 的唯一条件;捕获到限流响应时,把当前对象标记为 被限流中断 并立即跳出循环。这样主结果集里不会混入半成品。这个动作的直接结果是:下次续跑时,你只需筛选状态不等于 已完成 的记录,重跑范围从 800 条缩小到实际中断的那几条到几十条。
落盘顺序决定你能恢复到哪一步。以下按保护强度从低到高排列,选择取决于你的工具是否支持幂等调用。
如果你的工具调用不幂等(重复调用会改变状态或产生副作用),就必须选第二种或第三种,不能依赖重试覆盖。
限流不一定只因为请求过快。同样的现象还可能来自:账号或密钥的当日配额耗尽、并发数超过工具允许的上限、请求参数触发了更严格的校验路径。这几种原因的合理应对不同——前者可以等待窗口恢复,配额耗尽需要换时段或调整调用量,并发超限则要降低并行度。
可区分的证据:如果限流响应里带有重置时间或剩余配额字段,优先按它判断;如果没有,用一个小样本(例如 5 条)在降低并发后重试,观察是否仍被限流。样本仍被限流,倾向配额或权限问题;样本通过,倾向并发或速率问题。这个判断结果直接决定下一步是等待、降并发,还是先检查调用配置。
假设清单 800 条,脚本并发 10,跑到第 320 条时触发限流。若已按对象记录状态,此时主结果集有 300 条 已完成、1 条 被限流中断、其余 499 条 待处理。续跑时把并发降到 2,只处理状态非 已完成 的 500 条。若未记录状态,你只能看到"结果文件里有 300 条左右",无法确认第 301 条是否完整,续跑要么全量重来,要么冒险跳过——两种代价都高于先补状态字段。这里的数字仅用于说明比较方法,不代表任何工具的实际表现。
把状态字段补上、把限流中断写成显式值、把续跑范围限定在非完成记录,这三步做完之后,限流从一个"要重来的事故"变成一个"可续跑的断点"。下一步该做什么,取决于你核对出的限流原因:能等到重置就续跑,不能等就先调整并发或调用量再续跑。