限流触发后,最危险的动作不是等待,而是立刻重试。脚本一旦在限流窗口内反复请求,可能把已经拿到的结果覆盖成空值,也可能让后续任务全部卡死。保护已有结果的核心原则是:先冻结,再判断,最后决定是续跑还是重建。
两种情况的处理方式完全不同。临时限流通常表现为请求间隔缩短后出现连续失败,但等待一段时间后单次请求能恢复。结构性限流则表现为无论怎么放慢频率,只要脚本运行到某个批量规模就必然中断,或者同一账号在多个任务间共享额度时互相挤占。
区分方法不需要复杂工具。用一条最小请求做探测:如果单次请求能返回正常结构,说明通道还在,属于频率问题;如果单次请求也返回错误码或空结构,说明当前身份或调用方式已被限制,属于结构问题。这个判断结果直接决定下一步是调整节奏还是更换调用方式。
确认是临时限流后,不要清空已有数据重跑。正确动作是让脚本进入暂停状态,同时做三件事:
这个动作的结果是:你已经拥有的数据被固定下来,后续恢复时只需要从断点继续,而不是从头再来。如果跳过这一步直接重试,最常见的后果是结果文件被截断或部分字段被空值覆盖,反而丢失了原本可用的部分。
恢复调用时,把请求间隔调整为触发限流前的两到三倍,先跑一个小批量验证稳定性。如果小批量能完整通过,再逐步恢复到正常节奏。注意:请求量归零或抓取量骤降不能单独证明限流已经解除,也可能是目标页面结构变化或账号权限被调整,需要结合返回内容的结构是否完整来判断。
如果单次请求也无法恢复,说明当前调用方式已经不可用。这时保护已有结果的重点从续跑转为归档。
具体动作:把已获取的结果按字段完整度分成两档。字段完整、能直接使用的部分单独存放;字段缺失或只有部分内容的部分标记为待补。然后评估这些待补数据是否必须补齐——如果核心字段已经够用,就不需要为了补全边缘字段而更换整套调用方案。
一个假设的例子:某脚本需要采集一批页面的标题和描述,限流发生后标题字段大部分已拿到,描述字段缺失较多。如果标题已经能满足当前的分析目的,就不必为了描述字段去重构调用方式;如果描述是必需字段,才需要考虑更换调用身份或改用其他数据来源。这个判断依据是字段对最终用途的必要性,而不是字段缺失的数量。
条件一:限流可恢复,且断点清晰。选择续跑。实施动作是冻结结果、标记断点、放慢节奏。结果是已有数据不丢失,恢复成本最低。
条件二:限流不可恢复,或断点不清晰。选择归档并重新评估调用方案。实施动作是按字段完整度分档、判断核心字段是否够用。结果是避免在不可用的通道上继续消耗时间,同时保住已经拿到的部分。
例外情况:如果脚本本身没有做结果去重和断点记录,那么无论哪种限流,第一步都应该是停止写入,先检查结果文件是否已经被部分覆盖。这种情况下,保护已有结果的优先级高于判断限流类型。
限流发生后,不要在同一台机器上同时运行多个调用同一资源的脚本。多个脚本共享同一个出口身份时,一个脚本触发限流会连带影响其他脚本,导致原本正常的结果也被中断。如果必须并行,先确认各脚本使用的调用身份是否独立;如果不确定,暂停其他脚本,只保留一个探测请求来判断通道状态。