您更换代理,购买新的IP地址池,但解析器仍然出现429 Too Many Requests错误?这是一个经典的情况:70%的封锁案例与IP地址无关,而与请求本身的形式有关。我们分析六个实际原因,导致网站在更换代理后仍然禁止您访问,以及在每种情况下该如何处理。
错误429意味着什么,为什么代理不是灵丹妙药
HTTP状态码429 Too Many Requests正式意味着“请求数量超出限制”。但在实践中,网站——尤其是Wildberries、Ozon、Avito、Yandex.Market——使用此代码作为普遍信号“我们认为您是机器人”。原因可能在于请求频率,但同样可能在于头部、浏览器指纹、缺少cookie会话或与您的账户相关的限制,而不是IP。
正因如此,更换代理往往无济于事:如果系统阻止的不是IP,而是请求模式(指纹、头部、点击速度),那么您将从新的IP地址获得相同的429错误,仅需几分钟。我们将详细分析每个原因,并展示如何在不购买新代理池的情况下进行检查和解决。
重要提示:代理仍然是必要的工具——但仅作为系统的一部分,而不是唯一的解决方案。住宅和移动IP降低了因IP声誉而被列入黑名单的可能性,但无法避免因行为或头部而导致的封锁。
原因1:请求频率过高
最明显但也是最常被错误诊断的原因。许多人认为:“既然我每个请求都更换代理——频率就不重要。”这是错误的。现代反机器人系统(例如,Wildberries和Ozon使用Cloudflare级别的解决方案或自有WAF)不仅分析来自一个IP的请求频率,还分析特定API端点或商品页面在单位时间内的整体负载,以及来自所有来源的行为信号。
如果您的解析器在同一目录部分每秒发出50-100个请求,系统会看到异常的流量激增,无论您使用多少不同的IP。解决方案不是更换代理,而是在请求之间引入人工延迟(throttling):1-3秒的随机延迟,而不是固定间隔,并在收到429时进行指数回退(在每次封锁后将暂停时间加倍)。
import time, random
def safe_request(session, url):
for attempt in range(5):
response = session.get(url)
if response.status_code == 429:
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
continue
return response
return None
如果您使用的是没有代码的现成解析器(例如,云价格监测服务),请检查请求间隔的设置——大多数此类工具都有“扫描速度”的滑块。将速度降低30-40%通常可以完全消除429,即使不更换代理。
原因2:错误或缺失的头部
许多解析器以最小的头部集发送请求,或使用默认的User-Agent库(例如,“python-requests/2.28.1”)。这样的头部会立即暴露出机器人——真实的浏览器会发送数十个头部:Accept、Accept-Language、Accept-Encoding、Sec-Fetch-*、Referer等,且顺序严格。
Wildberries和Ozon会将头部集与真实Chrome或Safari浏览器的预期“指纹”进行比较。如果头部太少,顺序不正确,或者User-Agent与其他参数不符(例如,声明为Windows上的Chrome,但TLS指纹类似于Python)——请求将被阻止为429,无论IP如何。
| 头部 | 典型错误 | 解决方案 |
|---|---|---|
| User-Agent | 过时的版本或明显的库字符串 | 真实Chrome/Safari的最新UA,从池中轮换 |
| Accept-Language | 缺失或与IP的地理位置不符 | 对于俄罗斯市场,使用ru-RU |
| Referer | 空白,尽管真实的跳转总是有Referer | 指定目录的前一页面 |
| Sec-Fetch-* | 完全缺失(不是浏览器客户端) | 从真实浏览器的DevTools中复制完整集 |
最简单的方法是从真实浏览器的DevTools的Network选项卡中复制完整的头部集,手动打开所需页面,并在解析器中使用该集——如果库允许,注意头部的顺序(例如,curl_cffi或httpx具有明确的顺序)。
原因3:缺乏会话和cookie的轮换
一个常被忽视的错误:解析器在每个请求中更换IP,但使用相同的cookie会话或根本不保存cookies。真实用户在首次访问时会获得一组cookie(会话令牌、设备标识符、Cloudflare __cf_bm或Ozon/WB类似的反机器人保护标签),并在后续请求中使用这些cookie。
如果您在没有在“预热”页面上获得的cookies的情况下发送请求,反机器人系统会看到“零”会话——这立即引起怀疑,尤其是在直接访问API端点时,绕过主页。解决方案是模拟完整的场景:首先加载主页或类别页面,获取cookies,等待1-2秒,然后再访问所需的API或商品页面,在请求链中保持cookies在同一会话中。
import requests
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
"Accept-Language": "ru-RU,ru;q=0.9"
})
# 预热会话
session.get("https://www.wildberries.ru/catalog/0/search.aspx")
time.sleep(1.5)
# 主要请求已经带有cookies
response = session.get(target_url)
如果您使用反检测浏览器,如Dolphin Anty或AdsPower,手动监控商品页面或通过内置自动化,请确保配置文件在会话之间保存cookies,而不是每次都“从头开始”启动——这也会触发系统的怀疑。
原因4:类似机器人的行为
即使拥有完美的头部和cookies,解析器也可能通过行为模式暴露自己:严格线性的商品访问顺序(按ID升序)、请求之间的间隔相同到毫秒、缺乏对静态资源(图像、CSS、JS)的“垃圾”请求,普通浏览器会自动加载这些资源。
Wildberries和Ozon的高级保护系统不仅分析HTTP请求,还分析页面上是否执行了JavaScript(通过无头检测)、“鼠标”是否移动、是否有滚动。如果您进行纯HTTP请求而不渲染JS,而网站期望执行脚本以获取令牌(例如,反机器人JavaScript挑战),在未执行此脚本的情况下,请求将自动获得429或403。
解决方案取决于规模:对于小量,适合使用无头浏览器(Playwright、Puppeteer)模拟鼠标移动和随机延迟。对于工业级解析——随机化商品访问顺序,添加对次要资源的“噪音”请求,时间间隔的变异性应遵循正态分布,而不是固定步长。
原因5:TLS/JA3指纹和HTTP/2
这是最“隐蔽”的技术原因,90%从事解析的人并不知道。每个TLS客户端(requests库、curl、urllib)在建立HTTPS连接时留下独特的指纹——支持的加密套件、协议版本、TLS扩展的集合。这个指纹称为JA3/JA4指纹。
Cloudflare、Akamai等反机器人系统及大型市场的自有解决方案会将JA3指纹与已知机器人的数据库进行比较。标准的Python requests或Node.js https模块具有易于检测的指纹,完全不同于真实Chrome的指纹。即使拥有完美的头部和cookies,请求也会在TLS握手级别被阻止,在服务器看到HTTP头部之前。
此外,许多市场要求使用HTTP/2并具有特定参数(设置帧的顺序、流的优先级)——基于HTTP/1.1的库在这方面会自动被识别。解决方案是使用模拟真实浏览器指纹的库:curl_cffi(模拟Chrome TLS指纹)、tls-client,或基于Chromium的完整无头浏览器,它们自然会提供“真实”的指纹。
pip install curl_cffi
示例:curl_cffi.requests.get(url, impersonate="chrome120")——该库自动插入与真实Chrome 120相同的TLS指纹。
原因6:账户或API密钥级别的限制
如果您通过市场的官方或半官方API工作(例如,Wildberries的卖家API或Ozon卖家API),429可能与IP无关,而与卖家的账户或API令牌本身有关。在这种情况下,更换代理完全没有意义——限制存储在服务器端,与您的账户标识符相关联,任何来自该账户的IP都会收到相同的限制。
这种情况在同时通过个人账户监控竞争对手价格并调用API以提取库存的卖家中很常见——这两种请求流会合并到账户的总限制中。解决方案是分散时间负载,更经济地使用官方API配额(缓存不每分钟更改的数据),而对于纯粹的竞争价格监控,使用与卖家账户无关的单独未授权请求流。
检查这一点很简单:如果在使用全新IP且没有来自先前会话的任何cookie时仍然出现429,但您在邻近标签页中已登录个人账户——很可能限制确实与账户有关。
如何诊断真实原因
在更换基础设施之前,请按照以下算法进行诊断。首先,在普通浏览器中手动打开页面,确保在正常行为下不会出现429——这将确认问题出在解析器一侧,而不是区域的全球封锁。
然后,通过DevTools(Network选项卡→复制为cURL)比较解析器的头部与真实浏览器的头部。如果差异最小,请通过tls.peet.ws等服务检查TLS指纹——使用您的库发送请求,并将JA3哈希与标准浏览器进行比较。如果请求在TLS握手阶段失败(连接在接收HTTP响应之前断开)——原因在于指纹,而不是频率或头部。
接下来检查限制是与IP还是与账户相关:使用新的干净IP进行请求,无需授权。如果429消失——问题出在先前IP的声誉或来自该地址的频率。如果429仍然存在——请在头部、TLS或行为中寻找原因,而不是在代理中。
不更换代理的429故障排除清单
- 在请求之间添加1-4秒的随机延迟,而不是固定间隔。
- 复制真实浏览器的完整头部集,包括Sec-Fetch-*和Accept-Language。
- 在同一会话中保存并传递cookies,从预热主页开始。
- 检查您库的TLS指纹——使用curl_cffi或无头浏览器,而不是纯HTTP客户端。
- 随机化页面访问顺序,并添加对静态资源的“噪音”请求。
- 将API账户和匿名价格监控的负载分配到不同的请求流。
- 在收到429时实施指数回退,而不是立即重试请求。
- 仅在检查完上述所有项目后——更换代理或扩展IP池。
何时仍需代理以及选择哪种代理
在消除所有六个原因后,代理仍然是基础设施的重要组成部分——但作为扩展手段,而不是唯一的解决方案。如果您的任务是并行监控来自不同“虚拟用户”的数千个Wildberries和Ozon商品,您需要一个声誉良好的IP池,以免在一个地址上积累封锁历史。
对于大规模监控市场的价格和目录,最适合使用住宅代理——它们使用真实的家庭ISP IP,因此反机器人系统将请求视为普通买家的流量,而不是数据中心的流量。这一点至关重要,因为Wildberries和Ozon早已将数据中心IP范围列入黑名单。
如果任务与检查网站的移动版本、通过市场应用程序工作或在TikTok Ads和Facebook Ads中进行地理精确的广告测试有关,则移动代理是相关的——它们在大多数保护系统中具有最高的信任度,因为IP属于真实的移动运营商。
对于不太敏感的任务——例如,在小规模下解析开放目录而无需授权——可以使用数据中心代理:它们便宜且速度快,但需要更仔细地设置头部和TLS指纹,因为它们本身承受更高的被怀疑风险。
| 代理类型 | 何时解决429 | 何时无效 |
|---|---|---|
| 住宅代理 | IP因声誉已被列入黑名单 | 因TLS指纹或头部而被封锁 |
| 移动代理 | 需要最大信任度的IP以应对敏感场景 | 限制与账户相关,而非IP |
| 数据中心代理 | 简单解析开放页面而无需授权 | 严格的反机器人系统检查声誉范围 |
结论
在解析时,错误429很少通过单击“更换代理”按钮解决。在大多数情况下,问题出在请求频率、头部不完整、缺少cookie会话、可检测的TLS指纹、行为模式或与账户相关的限制,而不是IP地址。在花费预算扩展代理池之前,请逐一检查本文中的六个要点。
当技术部分设置正确——头部与真实浏览器相符,TLS指纹不暴露库,而请求模拟用户的自然行为——代理确实成为有效的扩展工具。对于大规模监控Wildberries和Ozon的价格,我们建议从住宅代理开始:它们在成本和反机器人系统信任度之间提供最佳平衡。