结论先给:如果限流是间歇性的、已有结果已经落盘且能按链接唯一标识去重,那么正确动作是暂停脚本、保留原始响应、用断点续跑补齐缺口,而不是立刻换IP或加大并发;如果限流伴随整批请求返回同一错误码、且本地结果没有记录请求参数,那么继续跑只会污染数据,应先停下来重建可恢复的调用记录。下面说明两种条件的分界,以及一个会让上述结论失效的反例。
限流本身通常只影响“还没拿到的部分”,真正危险的是脚本在收到限流响应后仍然把空值、错误页或默认值写进结果文件。判断方法很直接:打开最近一次落盘的结果,检查被限流的那批记录里,字段是“缺失”还是“被写成了某个看似正常的值”。前者可以续跑,后者必须先隔离这批记录。
可以按下面三点区分:
这三点的检查结果决定下一步:能分辨缺失与错误、且有请求参数记录的,可以直接进入断点续跑;不能分辨的,先别补数据,先把已有结果冻结成只读副本。
遇到限流,第一动作不是调参,而是把当前进程的调用状态写下来。具体做法是让脚本在捕获到限流响应时,把“已完成的链接标识列表”和“当前待处理的链接标识列表”分别写入两个文件,然后退出,而不是在循环里重试。
这样做的结果会直接影响下一步:有了已完成列表,续跑时就能跳过这些链接,避免重复请求触发更严格的限制;有了待处理列表,就能估算剩余请求量,决定是分批慢跑还是先人工处理高价值链接。若脚本没有这个能力,退而求其次的做法是把结果文件复制一份并记录复制时间,至少保证已有成果不会被后续运行覆盖。
需要提醒的是,暂停期间不要用同一套凭据高频试探。间歇性限流往往和短时间窗口内的请求量有关,持续试探会让窗口一直处于触发状态,反而延长恢复时间。
续跑的核心是“只补缺口、不重算全量”。可以按链接的唯一标识(例如规范化后的URL)建立索引,续跑前先加载已有结果,命中索引的直接跳过。对于之前被限流写坏的记录,应先标记为待复核,而不是直接覆盖。
一个假设的例子:假设已有结果里1000条链接,其中约80条在限流期间被写入了空标题。续跑时如果直接全量重跑,这80条可能被修正,但另外920条会再发一次请求,等于把请求量放大近一倍。更稳的做法是只针对那80条发起请求,其余跳过。这个例子里“80”只是说明比较方法,不是任何工具的实际数据。
续跑还应控制单批规模,并在每批结束后落盘一次。这样即使再次遇到限流,损失也只限于当前这一小批,不会把整轮结果拖回起点。
反例:如果限流响应和“链接不存在”“对方站点拒绝访问”返回的是同一个错误码,并且本地结果没有保存原始响应体,那么按唯一标识跳过已完成记录的做法就会失效——因为你无法区分“这条已经成功拿到”和“这条当时被限流挡掉了”。此时续跑要么漏补真实缺口,要么把原本有效的记录当成缺口反复请求。
遇到这种情况,正确顺序是先补上原始响应的留存,再重新建立一次基线。可以先用一小批已知有效的链接做对照,确认不同结果对应的响应特征,然后再决定哪些记录需要重跑。这个对照批次本身也要记录请求参数,否则下一次限流时还会遇到同样的问题。
综合来看,可以先做这个动作:把现有结果复制为只读副本,检查其中是否存在“限流期间写入的疑似错误值”,并确认脚本是否保存了请求参数与原始响应。如果两者都具备,就按唯一标识断点续跑;如果只具备其一,先补齐缺失的那一项再续跑;如果两者都不具备,先不要继续调用,转而用人工或低频方式重建一批可对照的基线记录。
判断是否恢复正常的依据,不是“这次请求成功了”,而是连续若干批请求都能稳定返回可区分的结果,且已有结果没有被覆盖或重复写入。满足这个条件后,再把续跑范围逐步扩大;不满足,就维持小批量节奏,避免把已经拿到的结果再次置于风险中。