返回博客

解析Wildberries和Ozon所需的代理数量:按RPS计算代理池的公式

大多数解析器在购买代理时仅凭IP数量而出错。我们展示了通过RPS、延迟和超时计算代理池的公式,并提供了代码示例。

📅2026年9月17日

在扩展爬虫时的经典错误是“凭感觉”购买代理:买了100个IP,启动爬虫,半小时后就被封了。问题不在于地址数量,而在于没有人计算每个IP的实际负载。我们将分析基于RPS(每秒请求数)、延迟和目标网站限制的代理池计算公式——附有具体数字和Python代码。

为什么按IP数量计算代理池是错误的

新手爬虫的典型思路是:“需要收集50,000个商品卡片,所以我们买500个代理并分散负载”。这个逻辑看似合理,但没有考虑到最重要的一点——像Wildberries和Ozon这样的网站并不是根据请求的绝对数量来封禁,而是根据单个IP在单位时间内的请求强度。也就是说,500个代理,每个每秒发出20个请求,会立即被封禁——反爬虫系统会识别出类似DDoS的模式。

另一方面,如果你有50个代理,但每个每5-10秒发出1个请求,模拟人类行为,你可以稳定地爬取数周而不会被封禁。IP数量并不是稳定性的原因,而是正确计算负载的结果。因此,公式应该从“买多少个IP”出发,而不是“需要达到多少RPS,以及每个IP的安全负载是多少”。

还有一个细节:不同类型的代理在单个IP上的“承受能力”不同。数据中心代理在高请求频率下更容易被封禁,因为它们的子网容易被识别为托管服务。住宅和移动IP看起来像普通用户,可以允许稍高的请求频率而不被封禁——但这并不意味着可以完全忽视限制。

代理池计算的基本公式

计算代理池中所需代理数量的公式如下:

N = (RPS_target × Delay_per_ip) / Concurrency_per_ip

其中:

  • N — 代理池中所需的代理数量;
  • RPS_target — 目标爬取速度(整个系统的每秒请求数);
  • Delay_per_ip — 单个IP之间的最小安全间隔(以秒为单位);
  • Concurrency_per_ip — 每个IP允许的并行线程数(通常为1,住宅代理最多为2)。

逻辑很简单:如果你想保持每秒10个请求的总数,而单个IP之间的安全间隔为8秒,那么一个IP在8秒内只能发出1个请求,即0.125 RPS。为了获得10 RPS的总数,需要10 / 0.125 = 80个代理。这就是替代“以防万一买500个IP”的计算。

如何计算爬取的目标RPS

在计算代理池之前,需要确定RPS_target——你实际需要的每秒请求数,以便在合理的时间内收集数据。这里的公式是反向的:

RPS_target = Total_requests / Time_budget_seconds

例如:需要在8小时内从Wildberries收集100,000个商品卡片(28,800秒)。如果每个卡片需要1个请求,RPS_target = 100,000 / 28,800 ≈ 3.47请求每秒。这并没有看起来那么多——许多人高估了所需的速度,购买了过量的代理。

如果任务包含多种类型的请求(例如,首先获取类别列表,然后是卡片,然后是评论),请分别计算每个阶段的RPS——它们可以并行进行,使用不同的代理池,整体负载将分散到不同的端点。

每个IP的限制:每分钟安全请求数

Delay_per_ip是公式中最重要的参数,需要根据每个网站的经验来确定。基于市场爬虫实践的一般参考:

平台 单个IP之间的安全间隔 单个IP的最大请求数/分钟
Wildberries(商品API) 4-6秒 10-15
Ozon(商品页面) 5-8秒 8-12
Avito(广告) 6-10秒 6-10
Yandex.Market 5-7秒 8-12

这些数字是起始点,而不是教条。开始时使用保守的值(暂停的上限),监控429和403错误的百分比,如果封禁没有增加,则逐渐减少暂停时间。突然增加RPS而不进行逐步测试是导致整个代理池在一天内被封禁的最常见方式。

实际计算:Wildberries、Ozon、Avito

我们将分析三个实际场景,并根据公式进行完整计算。

场景1:监控Wildberries的价格。 需要每2小时更新20,000个商品的价格。RPS_target = 20,000 / (2 × 3600) ≈ 2.78 RPS。对于每个IP暂停5秒且并发=1:N = (2.78 × 5) / 1 ≈ 14个代理。为了防止部分IP被封,建议购买1.5-2倍的代理池,即21-28个代理。

场景2:一次性收集Ozon的目录。 500,000个卡片在24小时内。RPS_target = 500,000 / 86,400 ≈ 5.79 RPS。暂停6秒:N = (5.79 × 6) / 1 ≈ 35个代理。加上安全系数——50-60个代理。

场景3:实时监控Avito的竞争对手。 5,000个广告,每15分钟更新一次。RPS_target = 5000 / 900 ≈ 5.56 RPS。暂停8秒:N = (5.56 × 8) / 1 ≈ 45个代理。这里需要注意,Avito会积极封禁数据中心的子网,因此对于这样的任务,建议直接使用住宅或移动IP。

公式中的住宅、移动和数据中心代理

代理类型直接影响Delay_per_ip,从而影响公式中的最终N。数据中心代理更便宜且速度更快,但在请求之间需要更长的暂停时间,并且在高频率下更容易被封禁——实际上,对于同样的5 RPS,你可能需要2-3倍于住宅代理的数据中心IP。

代理类型 平均Delay_per_ip 何时使用
数据中心代理 8-15秒 开放API,无严格反爬虫的网站
住宅代理 4-8秒 Wildberries、Ozon、Avito和其他带反爬虫的网站
移动代理 3-6秒 最激进的保护,社交网络,移动API

对于像Wildberries和Ozon这样的市场爬取,通常最佳选择是住宅代理——它们在价格和稳定性之间取得了平衡,允许在不急剧增加封禁的情况下保持较短的暂停时间。数据中心代理只应在没有激进反爬虫的网站或一次性任务中考虑,且RPS不高。

Python中的代理池实现:带轮换的代码

以下是一个简化的代理池实现,控制每个IP的请求频率。逻辑是:每个代理存储最后使用的时间,调度程序只选择那些自上次请求以来经过足够时间的IP。

import time
import random
from dataclasses import dataclass, field
from typing import List, Optional

@dataclass
class ProxyNode:
    address: str
    delay_per_ip: float  # 安全间隔(秒)
    last_used: float = field(default=0.0)

class ProxyPool:
    def __init__(self, proxies: List[str], delay_per_ip: float):
        self.nodes = [ProxyNode(address=p, delay_per_ip=delay_per_ip) for p in proxies]

    def get_available_proxy(self) -> Optional[ProxyNode]:
        now = time.time()
        available = [
            node for node in self.nodes
            if now - node.last_used >= node.delay_per_ip
        ]
        if not available:
            return None
        # 从可用的中随机选择,以避免队列模式
        node = random.choice(available)
        node.last_used = now
        return node

    def size(self) -> int:
        return len(self.nodes)


def calculate_pool_size(rps_target: float, delay_per_ip: float, concurrency: int = 1) -> int:
    """公式:N = (RPS_target * Delay_per_ip) / Concurrency_per_ip"""
    return max(1, int((rps_target * delay_per_ip) / concurrency))


# 示例用法
rps_target = 5.79        # 从任务量和时间计算得出
delay_per_ip = 6.0        # Ozon的安全间隔
n_proxies = calculate_pool_size(rps_target, delay_per_ip)
print(f"代理池中需要的代理数量:{n_proxies}")  # ~35,安全系数50-60

在实际爬虫中,这个逻辑需要补充任务队列(例如,通过asynciomultiprocessing),以便工作线程在没有可用代理时等待,而不是因缺少代理而失败。还应在收到429/403时添加指数退避——这会在检测到封禁迹象时自动增加特定IP的暂停时间。

监控和动态调整代理池

静态的公式计算是起点,而不是最终解决方案。在实际使用中,需要监控三个关键指标:

  • 成功率 — 成功请求(状态码200)占总请求的百分比。低于90-95%时,意味着需要增加Delay_per_ip或在池中添加代理;
  • 封禁率 — 在过去一小时内显示封禁迹象的代理比例(验证码、403、重定向到验证表单);
  • 实际RPS — 实际请求处理速度,可能由于超时和重试而与计算值不同。

实际规则是:如果封禁率在一小时内超过5-7%,请将Delay_per_ip增加20-30%,并重新计算N。如果成功率在几个小时内稳定在98%以上,可以逐渐减少暂停时间并缩小代理池——这将直接节省代理预算而不影响稳定性。

一个好的做法是为每个IP单独记录日志:最后一次成功请求的时间、连续错误的数量、平均响应时间。这可以自动将“损坏”的代理排除在轮换之外30-60分钟,而不是继续通过它们发送请求并在每一步都收到验证码。

计算代理池时的常见错误

即使知道公式,在计算细节上也容易出错。以下是典型错误的清单:

  • 忽视封禁的安全系数。 即使在理想计算下,5-10%的代理也会因封禁或网络问题而暂时不可用。始终在基本N上添加1.3-2倍的系数;
  • 对所有端点使用相同的Delay_per_ip。 类别页面和商品页面可能有不同的限制——请分别计算;
  • 未经过测试的Concurrency大于1。 从一个IP发出的并行请求会显著增加封禁风险,尤其是在住宅代理上——从Concurrency = 1开始;
  • 缺乏User-Agent和头部的轮换。 即使计算出的代理池也无法拯救,如果所有请求都来自相同的浏览器指纹;
  • 固定的暂停时间没有抖动。 请求之间严格相同的间隔(例如,正好5.0秒)是反爬虫容易识别的模式。添加±20-30%的随机偏差。

结论

公式N = (RPS_target × Delay_per_ip) / Concurrency_per_ip将代理池的计算从猜测转变为具有具体数字的工程任务。首先根据数据量和时间确定目标爬取速度,然后经验性地找到特定平台的安全间隔,最后计算所需的IP数量——并增加30-100%的安全系数以防封禁和故障。

这种方法节省了预算:与其“以防万一”购买过量的IP,不如支付确切所需的代理量,以达到目标RPS而不冒被封禁的风险。对于市场爬取和其他受保护的网站,建议从住宅代理开始——它们在与Wildberries、Ozon和Avito的反爬虫系统打交道时提供了最佳的稳定性和成本平衡。