限流发生时,最该保护的不是“继续跑完”,而是已经拿到的数据不因重试、覆盖或进程中断而丢失。做法可以概括为:把每次查询结果先落到本地可追加的存储,再决定是否重试;对未完成的部分记录断点,而不是整批重跑。这样即使脚本被限流打断,已有结果仍可核对、可续跑。
脚本调用外链查询工具时,限流通常表现为返回错误码、返回空数据或要求等待。但真正导致“已有结果消失”的,往往不是限流本身,而是脚本的处理方式。可以区分两种解释:
能区分这两种解释的证据是:查看输出文件的时间戳和行数变化。如果限流后文件行数不变、时间戳停在限流前,说明是解释一;如果文件被重写、行数回落或出现空文件,说明是解释二。先看这个证据,再决定是调整重试策略还是修数据写入逻辑。
很多脚本习惯先把整批结果放在内存里,跑完再统一写文件。限流一旦发生,内存里的结果随进程结束一起消失。更稳妥的动作是每拿到一条或一小批结果就追加写入,并带上查询参数和时间。
假设一个脚本要查询 500 个目标页面的外链数据,每页请求一次。如果在第 120 次遇到限流,采用追加写入的脚本会留下前 119 条记录,断点标记为第 120 个目标;采用批量写入的脚本可能一条都不剩。这个假设说明的是写入时机对结果留存的影响,不涉及具体工具的能力差异。
追加写入后,下一步不是马上重试,而是先确认已写入的记录能否被读取和去重。如果追加格式没有唯一键,续跑时可能产生重复行。因此写入时最好同时记录目标标识和查询时间,续跑时以目标标识判断是否已存在。
断点不是只记一个数字。要让续跑可核对,至少需要记录:
有了这些,续跑时可以跳过已成功的目标,只处理未完成部分。如果错误类型显示是临时限流,等待后从断点继续;如果错误类型显示是参数或权限问题,继续重试不会改善结果,应该先停下来核对请求条件。这个判断动作直接影响下一步:是等待重试,还是回到查询参数上排查。
脚本使用者、数据核对者和决策者可能对同一批外链查询结果有不同理解:使用者认为“跑完了”,核对者发现中间有缺口,决策者只看到一份汇总。把分歧转成可核对的项目,比争论“结果准不准”更有效。
可以核对的项目包括:目标总数、成功写入数、断点位置、限流发生次数、续跑后新增数。把这些数字放在同一份运行记录里,任何一方都能看出缺口在哪里。如果成功写入数加未完成数等于目标总数,说明数据覆盖可追踪;如果对不上,先查写入逻辑,而不是先怀疑工具返回。
需要说明的是,请求量或抓取量归零、返回空结果,不能单独证明限流已经解除或数据处理正确。空结果还可能来自目标本身没有外链、查询参数写错、返回格式变化等原因。要区分这些解释,可以拿一个已知有外链的目标做对照查询;对照也返回空,才更可能是请求侧问题。
限流后的重试策略应建立在“已有结果已固定”的前提上。具体动作可以是:把当前输出文件复制一份带时间戳的副本,再在原文件上继续追加;或者把已成功记录导入一个只读的核对集,续跑结果写入新文件。这样即使续跑再次失败,上一份结果仍可用于核对。
如果工具或接口的具体限流规则、等待时间、配额信息没有明确依据,不要凭猜测设置固定等待秒数。应先查看返回提示或文档中可核对的信息;无法确认时,采用逐步延长等待并记录每次结果的保守方式,同时保留每次尝试的运行记录。具体品牌的现行功能、入口和额度需要以该品牌当前说明为准,不能沿用旧教程的假设。
最终要保住的是可追溯:哪些目标查过、哪些没查、结果写在哪里、下一次从哪里继续。做到这四点,限流只是一次中断,不会变成一次数据丢失。