# 礼貌爬虫仍能扩展：速率限制指南

猛烈攻击网站会被封禁；一次只抓取一个请求则毫无进展。可扩展的中间方法是根据每个域名自适应调整速度，分散到干净的IP上——对网站礼貌，对你快速。

现在几乎一半的互联网流量是自动化的，网站对此心知肚明。速率限制是他们的第一道也是最基本的防线——一个速度限制，决定你能获取多少以及多快。诱惑在于将其视为一个需要用蛮力突破的障碍，但这会导致封禁。相反的错误是一次小心翼翼地抓取一个请求，这在规模上毫无进展。可扩展的答案是**礼貌爬虫**：以一个合法但繁重的用户的方式调整每个目标的速度，将负载分散到干净的IP上，并让网站自己的响应调整你的速度。这就是如何保持快速而不成为导致所有人被封禁的流量。

## 知道你触碰了哪个限制

服务器根据一个标识符——通常是你的IP，有时是API密钥或账户——在一个时间窗口内计算你的请求，并在你超过阈值时采取行动。三种常见的模型表现不同：**固定窗口**按日历分钟计算请求；**令牌桶**每分钟给你固定数量的令牌（比如100个），每个请求消耗一个，当桶空时强制等待；**滑动窗口**在任何时刻计算过去滚动的60秒内的请求。实际结果是，突发比稳定流更危险——一秒内的十个请求可能触发一个限制，而一分钟内分散的一百个请求则不会。

限制也有不同的形式。软限制是温和的：服务器减慢你的速度，或者返回`429 请求过多`，并带有`Retry-After`头，告诉你确切的等待时间（Cloudflare的错误1015就是这样）。有些网站容忍小的突发——允许每分钟100个，但只在120个时限制，而另一些则在每分钟15个时就开始限制，并在30个时才完全封锁。硬限制是严格的上限：一个API允许每小时1000个请求，一旦超过就完全锁定你。反复触碰软限制会导致升级：429变为403，然后是几分钟到几小时的临时封禁，每次触发时窗口都会增长，最终是永久性地将你的IP或整个子网列入黑名单。

## 读取响应，不要猜测

对爬虫的最大升级是响应服务器告诉你的，而不是以固定速率猛攻。学习这些术语：`429`意味着减速并遵守`Retry-After`；`403`意味着此身份被标记，因此要旋转而不是重试；`503`通常是一个挑战或临时拒绝；而返回验证码页面的`200`是软封锁，而不是成功。对每一个都要区别对待。错误的操作——在403时重试同一个被封的IP，或忽略Retry-After并在429时继续猛攻——会将软警告变为永久封禁。我们关于[修复429](https://quantumproxies.io/blog/fix-429-too-many-requests-scraping)的深入探讨详细介绍了响应处理。

```python
import time, requests

def polite_get(session, url, max_tries=4):
    for attempt in range(max_tries):
        r = session.get(url, timeout=20)
        if r.status_code == 200 and "captcha" not in r.text.lower():
            return r
        if r.status_code == 429:                       # obey the server
            wait = int(r.headers.get("Retry-After", 2 ** attempt))
            time.sleep(wait)
            continue
        if r.status_code in (403, 503):                # this exit is burned
            rotate_ip(session)                         # fresh IP, then retry
            time.sleep(2 ** attempt)                    # exponential backoff
            continue
        return r
    return None
```

![读取每个状态码的 Python 节奏控制逻辑：200 直接返回，429 等待 Retry-After 响应头或进行指数退避，403 或 503 则更换 IP 并退避；卡片把状态码对应到动作：200 时加速，429 时等待，403 时轮换，并把返回 200 的 CAPTCHA 页面视为软封锁。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335203/blog/generated/qp-b9-074-diag1.png)
*让网站自己的响应代码驱动你的速度：在200时加速，429时遵守Retry-After，403时旋转。*

## 为每个域名分配请求预算

一个触及多个网站的爬虫不应对所有网站应用一个全局速率。一个小博客和一个坚固的市场所能承受的负载截然不同，因此给每个域名分配自己的预算。每个主机的令牌桶是一个清晰的模式：为每个域名分配一个保守的速率，随着时间的推移补充，并让对不同主机的请求并行运行，而对同一主机的请求保持在其限制内。在新的目标上慢慢开始，让响应代码告诉你是否可以加速。

```python
import time
from collections import defaultdict

class DomainLimiter:
    def __init__(self, per_min=30):
        self.gap = 60.0 / per_min          # min seconds between hits per host
        self.last = defaultdict(float)
    def wait(self, host):
        now = time.time()
        delay = self.gap - (now - self.last[host])
        if delay > 0:
            time.sleep(delay)
        self.last[host] = time.time()

# 30 req/min to any single host; different hosts proceed independently
limiter = DomainLimiter(per_min=30)
limiter.wait("example.com")
```

## 分散负载以保持每个IP的礼貌

这是将“礼貌”与“扩展”调和的举措：礼貌是以每个IP为单位衡量的，但你的总吞吐量是所有IP的总和。如果一个目标每分钟允许每个地址30个请求，一个IP将你限制在30个——但十个干净的IP，每个执行30个，可以让你每分钟达到300个，同时每个出口都保持礼貌。一个[旋转住宅网关](https://quantumproxies.io/rotating-proxies)会自动完成这一操作，每次请求分配一个新的IP，覆盖9000万+个地址，因此没有单个出口看起来具有攻击性。这不是一个猛烈攻击的技巧；这是分配真实负载，以便没有一个服务器承受可疑的峰值。IP旋转的基本原理在[IP旋转是什么以及为什么重要](https://quantumproxies.io/blog/what-is-ip-rotation-and-why-it-s-crucial-in-2026)中。

[分散负载到干净的旋转IP上](https://quantumproxies.io/rotating-proxies)

## 减少请求，更多缓存，选择合适的时间

最礼貌的请求是你从未发送的请求。三个习惯可以在不损失数据的情况下减少负载。首先，积极缓存并使用条件请求——发送`If-Modified-Since`或`If-None-Match`，这样未更改的页面会返回一个小的`304`而不是完整的主体，从而节省服务器和你的带宽。其次，故意预算并发：一个信号量限制每个域名的在途请求，防止意外突发。第三，将重负载任务安排在目标的非高峰时段，当你的流量占他们的比例较小时，不太可能触发阈值。结合这些，可以将一个任务所需的请求减半——这是我们更广泛的[反封禁清单](https://quantumproxies.io/blog/avoid-ip-ban-web-scraping)背后的纪律。

还有一件值得明确说的事情：检查`robots.txt`并遵守网站声明的爬行期望。礼貌不仅仅是自我保护——成为一个好公民可以让开放的网络对每个人都可抓取。我们关于[robots.txt 实践](https://quantumproxies.io/blog/robots-txt-web-scraping-ethics)的指南涵盖了它的约束和不约束。

![从软性到永久的升级刻度：429 Too Many Requests 要求你放慢速度，身份被标记时返回 403，然后是持续数分钟到数小时并不断延长的临时封禁，最后是对 IP 或子网的永久黑名单；卡片建议在第一次收到 429 时就遵守 Retry-After，绝不重试已被封的 IP。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335204/blog/generated/qp-b9-074-diag2.png)
*反复触碰软限制会使其变硬：429变为403，然后是不断增长的临时封禁，最终是永久黑名单。*

## 常见问题解答

### 如何在爬虫时避免速率限制？

为每个域名设定自己的请求预算，在429时遵守`Retry-After`，指数退避，并将负载分散到一个干净IP的旋转池中，以免任何单个地址显得具有攻击性。添加缓存和条件请求以减少总体请求，并将重负载任务安排在目标的非高峰时段。

### HTTP 429是什么意思，我该如何处理？

429 请求过多是一个软速率限制——服务器要求你减速，而不是封禁你。读取`Retry-After`头，并在重试前等待确切的时间；如果缺失，则指数退避。永远不要忽视它并继续猛攻，因为反复的429会升级为403，然后是定时或永久封禁。

### 每分钟多少请求是安全的？

没有通用的数字——完全取决于目标。一个小网站可能只容忍每分钟几个请求；一个大网站则可能更多。保守地开始（比如每分钟每个IP 20-30个），观察429，并根据响应进行调整。通过增加IP来扩大总吞吐量，而不是提高单个IP的速率。

### 旋转代理是否被视为不礼貌？

如果用于分配真实负载，则不是。旋转保持每个单独的IP在礼貌的速率内，同时你的总吞吐量增加——服务器从未看到任何一个地址的可疑峰值。只有当你用它来超过网站合理处理的总量时，才会变得不礼貌；要调整整体，而不仅仅是每个IP的速率。

礼貌和可扩展性并不是对立的。读取信号，遵守Retry-After，为每个域名分配预算，缓存你能缓存的，并将其余的分散到干净的旋转IP上。你会比鲁莽的爬虫更快——因为你是那个从不被封禁的人。

[通过旋转住宅代理礼貌地扩展](https://quantumproxies.io/rotating-proxies)
