限流发生时,先别急着重跑脚本。把已经拿到的结果当成不可再生的资产:立刻停止新的调用,把当前内存或临时目录里的数据落盘,记录每条结果的来源参数和抓取时间,然后再决定是保留现状、改写调用方式,还是退出这条路径。是否保留,取决于已有结果能否覆盖交付所需的最小字段;是否改写,取决于限流是并发过高还是配额耗尽;是否退出,取决于这条数据源是否还有可替代的获取方式。
限流不是一个单一状态。常见的有两类:一类是短时间请求过密触发的临时拒绝,稍后恢复;另一类是配额用尽或权限被收回,继续等待也不会自动恢复。这两类对应的处理完全不同。
如果返回信息里带有重试等待时间、剩余配额或明确的恢复窗口,说明是临时限流,已有结果值得保留,等窗口过去后可以增量补齐。如果返回的是权限错误、账号被停用或配额已归零且没有恢复说明,就要按退出路径处理,已有结果能救多少救多少,不要指望自动恢复。
判断依据可以看三点:错误码是否稳定复现、等待后是否恢复、同账号其他调用是否也失败。只看一次失败就断定是限流,容易把网络抖动或参数错误误判成配额问题,做出错误的保留决定。
限流中断时,最危险的不是数据少,而是数据在内存里、格式还没统一、来源参数没记。一旦进程退出,这批结果就没了。
一个实际动作是:在脚本里加一个中间落盘步骤,每成功拿到一批结果就写入本地文件,文件名带上调用参数摘要和时间戳。例如用 result_关键词_20250101_1200.jsonl 这样的命名,而不是等全部跑完再统一写出。这样即使下一次调用被限流,已有批次仍然可读、可核对、可增量合并。
落盘之后要立刻做一次字段清点:交付需要的字段是否齐全,缺失的是哪些,缺失部分能否用其他批次补上。如果已有结果已经覆盖交付所需的最小字段,就可以保留现状,把剩余部分标记为待补,而不是推翻重来。
改写不是无条件的。它成立的前提是:限流来自调用节奏,而不是数据源本身封死了这条路。具体来说,降低并发、拉长请求间隔、把一次大批量拆成多次小批量,这些手段只在限流是速率触发时有效。
可以做一个假设比较:假设原本每秒发 10 个请求、每次取 100 条,被限流;改成每秒 2 个请求、每次取 20 条,总请求数反而变多,但如果限流按每秒请求数计算,改写后可能通过。反过来,如果限流按总配额计算,拆小批量只会更快耗尽配额,改写反而有害。
所以改写前要先确认限流口径。口径不清楚时,先用极小批量做一次试探调用,观察返回信息是否变化,再决定是否扩大改写范围。试探本身也要落盘,不要浪费这次调用。
当限流属于配额耗尽、权限收回,或同一数据源反复失败且没有恢复说明时,继续投入就是在消耗时间。退出的判断标准是:已投入的补齐成本是否超过换一条获取路径的成本。
退出不等于丢弃。把已有结果按来源和完整度分类:完整可用的直接进入交付;部分缺失的标注缺口;完全无法核对的单独存放,避免混入正式结果。这样即使换路径,之前的工作仍能作为对照或补充。
退出后要记录这次限流的触发条件,包括调用频率、批量大小、账号状态和返回信息。这份记录决定下一次是否还要走同一条路径,也决定改写方案是否有依据。多个角色对限流原因有分歧时,这份记录就是把分歧转成可核对事实的最小材料。
不同角色对限流的理解常常不同:有人认为是脚本写错了,有人认为是账号权限问题,有人认为是数据源故意限制。争论没有意义,能核对的是记录。
一份可核对的记录至少包含:每次调用的时间、参数、返回状态、等待后是否恢复、同账号其他调用是否正常。把这些并排看,就能区分是脚本问题、账号问题还是数据源问题。记录不需要复杂,但要在限流发生时就写,事后补记容易失真。
下一步动作取决于记录指向哪一类原因:指向脚本节奏就改写,指向账号权限就核对账号状态,指向数据源限制就评估退出或换路径。已有结果在每一步都先落盘保留,直到确认新路径可用,再决定是否清理旧结果。