错误修复 · 1 分钟阅读

如何在抓取时修复429请求过多

429 是速率限制,而不是禁止——服务器在要求您减速。持久的修复结合了退避、遵守 Retry-After,并在 IP 池中分散负载。以下是如何使用有效的 Python。

429 是速度限制,而不是墙

HTTP 429 请求过多意味着您在给定的时间窗口内发送了太多请求,服务器正在限制您。这是故意的临时措施——与硬性阻止不同,429 通常在您减慢速度后会自动解除。许多服务器会包含一个Retry-After头部,告诉您确切需要等待多少秒;遵循它是最有效的解决方案,因为这使您与服务器的限制保持一致,而不是猜测。

There are two levers. The first is rate: send fewer requests per second per IP, add delays, cap concurrency, and back off exponentially when a 429 appears. The second is distribution: spread requests across multiple IPs so each stays under the per-IP limit. Rate control is where you should start — a proxy pool multiplies your throughput but does not excuse hammering a site. s4m provides authenticated datacenter proxies (SOCKS5 1080, HTTP 3128, USER:PASS) to spread load, and this pairs directly with the proxy rotation guide and scraping with requests.

尊重 Retry-After,退后,然后轮换

一个尊重Retry-After的获取循环,随着抖动指数级回退,并在代理池中分散。替换USER:PASS。

python
import random, time
import requests

USER, PASS, HOST = "USER", "PASS", "proxy.s4m.online"
POOL = [
    f"socks5h://{USER}:{PASS}@{HOST}:1080",
    f"http://{USER}:{PASS}@{HOST}:3128",
]

def polite_get(url, max_tries=6):
    for attempt in range(1, max_tries + 1):
        proxy = random.choice(POOL)
        r = requests.get(url, proxies={"http": proxy, "https": proxy},
                         timeout=(5, 20))
        if r.status_code != 429:
            r.raise_for_status()
            return r

        # 429: prefer the server's Retry-After, else exponential backoff
        retry_after = r.headers.get("Retry-After")
        if retry_after and retry_after.isdigit():
            wait = int(retry_after)
        else:
            wait = min(2 ** attempt, 60) + random.random()  # cap + jitter

        print(f"[{attempt}/{max_tries}] 429; waiting {wait:.1f}s")
        time.sleep(wait)

    raise SystemExit(f"still rate-limited after {max_tries} tries")

# Global throttle: cap how fast you fire, independent of retries.
MIN_INTERVAL = 0.5  # seconds between requests per worker
_last = 0.0
def throttled_get(url):
    global _last
    delta = time.time() - _last
    if delta < MIN_INTERVAL:
        time.sleep(MIN_INTERVAL - delta)
    _last = time.time()
    return polite_get(url)

print(throttled_get("https://httpbin.org/status/200").status_code)

修复 429 的命令

首先解决最便宜、最尊重的修复。

尊重Retry-After

如果 429 响应包含 Retry-After 头部,请准确等待该时间后再重试。这是服务器告诉你其限制 — 遵循它可以立即清除大多数 429。

添加带抖动的指数退避

当没有 Retry-After 时,等待 2、4、8… 秒(上限)加上小的随机抖动在重试之间,以便您停止猛击并避免同步重试。

限制请求速率

限制每秒请求和并发,以便您首先保持在限制之内。稳定、较慢的爬虫比不断被限制的突发更可靠地完成。

在 IP 之间分散负载

一旦您的每个请求行为礼貌,便在代理池中轮换,以便每个IP保持在每个IP限制之下。这在不提高任何单一地址的速率的情况下,增加了安全的吞吐量。

为什么仅仅旋转不是答案

将代理视为忽略速率限制的一种方式是很诱人的——只需添加更多的IP并继续发送请求。但这会适得其反。返回429的站点正在监控请求模式,从一组不断变化的地址在同一时刻向相同端点发送洪水请求本身就是一个可检测的特征,这会升级为严格的禁令。轮换会增加礼貌的吞吐量;它并不替代礼貌。始终将代理池与退避、Retry-After、现实的节奏和合理的并发结合使用。

老实说,一些限制是应该被尊重的——在围绕429进行扩展之前,检查是否存在官方的API或文档速率,并阅读每个站点的条款。当你确实需要分布时,s4m的认证数据中心代理分散负载,并且是计量的,因此扩大池是便宜的;有关机制,请参见轮换指南。请记住,数据中心IP仍然可能被整体标记,轮换对指纹没有任何作用。以免费代理列表进行低成本原型设计,并使用工具验证出口。

FAQ

问题,已解答

429 是永久禁令吗?

不。HTTP 429 请求过多是一个临时速率限制 — 通常在你减慢速度后会清除。遵循任何Retry-After头,增加退避时间,并减少请求速率,访问通常会恢复。

解决 429 的单一最有效的修复是什么?

尊重服务器发送的 Retry-After 头。它告诉您确切的等待时间,因此您可以重新对齐服务器的限制,而不是猜测并再次被限制。

轮换代理会停止 429 错误吗?

它通过保持每个 IP 在每个 IP 限制内来提供帮助,但仅在配合退避和限流的情况下。没有礼貌的节奏的轮换会产生可检测的洪水,导致更严格的封锁,因此将两者结合起来。

s4m代理足够绕过任何速率限制吗?

没有诚实的工具可以承诺这一点。s4m数据中心代理在IP之间分散负载,但您仍然需要退避和限速,数据中心范围可能会被标记,某些限制应该通过官方API得到尊重。

以诚实的方式分散负载

在 proxy.s4m.online 上结合回退和限流与经过身份验证的数据中心代理,以保持每个 IP 在限制之内。按需计费,专用 IP 可选。

人们通过搜索找到此页面

此页面回答的真实搜索短语 — 链接的短语打开详细覆盖它们的页面。