遇到限流时,最该先做的不是继续重试,而是把已经拿到的数据冻结成可交付版本,并记录每个查询的完成状态。继续硬跑通常只会让更多请求失败,还可能让原本可用的结果被后续空值覆盖。保护已有结果的关键动作是:先落盘、再标记、后补跑;只要这三个动作的顺序对了,限流只是一次中断,不会变成一次数据事故。
脚本调用搜狗SEO工具时,限流往往不会表现为“全部失败”。更常见的情况是:前几百条查询正常返回,中间开始出现超时或空响应,脚本却继续往下跑,最后把空值、默认值和真实值一起写进同一份结果文件。表面上看任务跑完了,实际上数据已经被污染。
这里有两种解释。第一种是工具端确实在限流,返回的是临时拒绝;第二种是脚本自身的重试逻辑把失败请求反复放大,导致后续请求也被拖垮。两者的外部表现相似,但处理方式完全不同:前者要降低请求节奏并保留断点,后者要先修重试策略,否则降速也没用。
能区分这两种解释的证据,主要看失败出现的位置和形态。如果失败集中在某个时间窗口之后,且同一批查询在间隔较长时间后单独重跑能成功,更接近工具端限流。如果失败从脚本启动不久就出现,且伴随大量重复请求、并发数偏高、重试次数没有上限,更接近脚本自身的问题。
一个可操作的判断方法是:从失败点附近抽取少量查询,用单线程、固定间隔的方式单独重跑。如果这批查询能稳定返回,说明限流是主因;如果仍然失败,就要先检查请求构造、参数格式和重试逻辑。这个动作的结果直接决定下一步:前者要改调度,后者要改代码。
确认是限流后,不要在原文件上继续追加。正确顺序是:
done、failed、pending,不要用空字符串表示失败。failed 和 pending,并降低并发、拉大间隔。这个动作的结果是:即使补跑再次中断,已有结果仍然是完整可用的,不会因为一次失败而回退到起点。后续无论换工具、换账号还是换时间段,都能从断点继续,而不是从头再来。
假设脚本计划查询 500 个词,跑到第 180 个时开始出现超时,最终只有 150 条是可信结果。如果不冻结,直接重跑,可能把 150 条可信结果覆盖成空值。如果先冻结,再补跑剩余 350 条,那么即使补跑只成功 200 条,你手里仍有 350 条可用数据,而不是 0 条。
这个例子的重点不是数字,而是比较方法:判断一次中断是否严重,要看“已确认可用的结果”有没有被破坏,而不是看任务有没有跑完。只要可用结果被保留,限流就只是进度问题;一旦可用结果被覆盖,限流就变成了数据质量问题。
冻结和补跑不是无条件适用。如果业务要求同一批数据必须在同一时间窗口内采集,那么断点补跑会引入时间差,此时应优先考虑整体重跑,但要先把旧结果归档,避免新旧混用。如果查询本身依赖登录态或短期凭证,补跑前要确认凭证是否仍然有效,否则补跑会批量失败。
另外,限流的具体表现和恢复时间取决于工具端的实际策略,不同时间、不同调用方式可能不同。具体限制条件需要以工具端当前返回的信息为准,不能把一次观察到的现象当成固定规律。
最可靠的做法是把冻结逻辑写进脚本本身:每完成一批查询就落盘一次,失败时写入状态标记而不是空值,退出前输出断点文件。这样即使限流突然出现,也不需要人工判断该不该保存。下一次运行时,脚本读取断点文件,只补未完成部分。这个动作的结果是,限流从“需要紧急处理的事故”变成“下次运行自动接续的普通中断”。