核心做法是把“查询”和“保存”拆成两步:每拿到一条结果就立即落盘,限流只影响后续请求,不会让已经到手的记录消失。下面用一个假设情境把决策过程走一遍。
假设你写了一个脚本,对一个域名列表逐个发起网站快照查询,每查完一个就把结果写进内存里的列表,全部跑完再统一写文件。前 200 个域名很顺利,第 201 个开始连续返回限流提示,脚本抛出异常退出。此时内存里的 200 条结果随进程一起消失,你只知道“被限流了”,却不知道已经查到哪、查到了什么。
这个结果与直觉相反的地方在于:限流本身只是让你变慢,真正让你损失的是“先攒后写”的写法。要判断损失来自限流还是来自脚本结构,看一个证据就够了——进程退出后磁盘上有没有留下任何中间文件。如果没有,问题在保存时机,不在请求频率。
具体动作是改成逐条追加写入:每完成一次网站快照查询,就把这条记录以追加方式写入本地文件,同时记录查询时间和目标标识。这样即使第 201 个请求被限流,前 200 条已经在磁盘上。
这个动作会直接改变下一步:你可以安全地中断脚本、等待一段时间、再从第 201 个继续,而不必从头重跑。判断是否值得这么做,看两个条件——目标数量是否明显大于单次稳定请求量,以及单条查询结果是否难以复现(例如结果随时间变化)。两个条件都成立时,逐条落盘几乎总是划算的;如果只查十几个目标且结果稳定,一次性写入也够用。
看到请求连续失败,不要立刻断定是频率超限。以下原因都会产生相似现象,需要用可核对的证据区分:
把失败原因归类后,处理方式完全不同:频率问题靠退避等待,目标问题靠跳过并记录,脚本问题靠修异常处理。混在一起改,往往改了频率却没解决真正的失败源。
在逐条落盘的基础上,加一层简单退避:遇到限流提示时,暂停一段时间再重试同一条,重试仍失败就跳过并单独记录,继续处理后面的目标。这样一次运行不会因为个别目标而整体停摆。
断点续跑依赖落盘文件里的目标标识。下次启动时先读取已完成的标识集合,跳过它们,只处理剩余目标。这里的假设是目标标识稳定且唯一;如果标识会变,续跑判断就会失真,此时应改用更稳定的键,或接受少量重复查询。
不需要等到全量跑完。可以取一小批目标,人为在中途触发一次限流(例如临时调高并发),然后检查三件事:磁盘上是否已有部分结果、重启后是否从断点继续、被跳过的目标是否被单独记录。三项都通过,说明已有结果在限流下是安全的。
需要注意的是,请求量或失败数归零并不能单独证明处理正确——也可能是脚本提前退出、目标列表为空或写入路径出错。要结合落盘文件的实际内容来判断,而不是只看控制台输出。把这套验证跑通,再放大到全量目标,限流就只是让任务变慢,而不会让已有结果归零。