In this Article
Scrapy 轮换代理通过在多个 IP 端点之间切换,让爬虫的连续请求从不同地址发出,从而降低触发速率限制和 IP 封禁的风险。本教程将演示如何在实际项目中结合 scrapy-rotating-proxies 中间件和 DataImpulse 住宅轮换网关配置轮换代理,并完成验证与排错。
你将安装中间件、配置 settings.py、启用封禁检测和重试、确认出口 IP 是否变化,并了解如何在轮换网关与静态代理列表之间选择。下文所有代码块均可直接运行,文末也会说明方案的实际局限。
DataImpulse 是一家注重合规的代理服务商,在 195 个国家提供超过 9000 万个住宅、移动和数据中心 IP。其按量付费套餐每 GB 1 美元起,流量永不过期,适用于网页抓取、广告验证、价格监控、市场调研和多账号管理。
关键要点
- 配置: 使用 Scrapy 轮换代理时,可让 scrapy-rotating-proxies 中间件使用一组代理端点,或使用 gw.dataimpulse.com:823 这样的单一轮换网关,使每个请求通过不同的 IP 发出。
- 最佳代理类型: 轮换住宅代理,使用真实用户的 IP,更不易触发检测。
- 价格: 从每 GB 1 美元起,按量付费,流量不过期且无需订阅。
- 覆盖范围: 遍布 195 个国家、超过 9000 万个来源合规的 IP。
- 可靠性: 成功率 99.51%,在 G2 上获得 5 分中的 4.8 分评价。
- 协议与定向: 支持 HTTP、HTTPS 和 SOCKS5,并支持按国家定向。

在 Scrapy 中开始使用轮换代理之前,你需要什么?
你需要一个可用的 Scrapy 项目、Python 3.8 或更新版本、scrapy-rotating-proxies 包,以及一个可用的代理端点池。轮换逻辑位于一个下载器中间件中,因此你的爬虫无需做任何改动。
在编写代码之前,请准备以下内容:
- 一个用
scrapy startproject创建的 Scrapy 项目。 - scrapy-rotating-proxies 中间件。这是一个社区维护的软件包,相关抓取工作流可供参考,项目以 scrapy-rotating-proxies 之名托管在 GitHub 上。
- 代理凭据。本指南使用 DataImpulse 的住宅代理,它们提供单一的轮换网关,以及 HTTP、HTTPS 和 SOCKS5 支持和按国家定向。
将该中间件安装到你的项目环境中:
pip install scrapy-rotating-proxies
该包添加了两个中间件:RotatingProxyMiddleware,它为每个请求分配一个代理;以及 BanDetectionMiddleware,它用于判断响应是否疑似被封禁,并在 IP 出现问题时切换代理。
如何在 Scrapy 中使用轮换代理?
要启用 scrapy-rotating-proxies,只需在 settings.py 中声明代理端点并启用两个下载器中间件。代理可通过内联 Python 列表提供,也可从指定路径的文本文件加载。
内联方式使用 ROTATING_PROXY_LIST。按所示优先级启用这两个中间件,使它们以正确的顺序运行:
# settings.py
ROTATING_PROXY_LIST = [
'http://user:[email protected]:823',
]
DOWNLOADER_MIDDLEWARES = {
'rotating_proxies.middlewares.RotatingProxyMiddleware': 610,
'rotating_proxies.middlewares.BanDetectionMiddleware': 620,
}
为了让凭据不进入源代码管理,使用 ROTATING_PROXY_LIST_PATH,并将其指向一个每行一个代理的文件:
# settings.py
ROTATING_PROXY_LIST_PATH = 'proxies.txt'
# proxies.txt (one endpoint per line)
http://user:[email protected]:823
http://user:[email protected]:824
DataImpulse 网关可替代需要自行维护的长代理列表。gw.dataimpulse.com:823 会由服务商在其端轮换出口 IP,因此只需配置这一行即可:网关会为每个请求分配新的住宅 IP;若响应被标记为封禁,中间件会通过同一网关重试。这是大多数爬取任务中最简单、也最可靠的模式。
如果你更愿意按请求而非全局设置代理,可在爬虫中通过 request 的 meta 为单个请求指定代理。这也是显式附加代理认证的方式,DataImpulse 的代理认证指南对此有所介绍:
import scrapy
class GatewaySpider(scrapy.Spider):
name = 'gateway'
urls = ['https://httpbin.org/ip']
def start_requests(self):
proxy = 'http://user:[email protected]:823'
for url in self.urls:
yield scrapy.Request(url, meta={'proxy': proxy}, dont_filter=True)
如何验证轮换代理在 Scrapy 中正常工作?
可向 IP 回显端点发送多次请求,检查各个响应返回的来源 IP 是否发生变化,以验证轮换是否生效。httpbin.org/ip 会返回请求方的出口 IP,是快速验证的好工具。
添加一个小爬虫,让它访问回显端点十次并记录每个出口 IP:
import scrapy
class IPCheckSpider(scrapy.Spider):
name = 'ipcheck'
start_urls = ['https://httpbin.org/ip'] * 10
def parse(self, response):
self.logger.info('Exit IP: %s', response.json()['origin'])
从项目根目录运行它:
scrapy crawl ipcheck
日志中的 Exit IP 应显示多个不同的地址。如果每一行都显示相同的地址,则轮换未生效:确认中间件已启用、ROTATING_PROXY_LIST 不为空,且请求不是从 HTTP 缓存返回的。该中间件还会记录代理健康状况,因此请留意有关 good、dead 和 reanimated 代理的行,以确认它在管理这个代理池。
如何用 Scrapy 轮换代理排查封禁和 407 错误?
大多数轮换问题都涉及两点:中间件能否正确识别封禁,以及代理认证是否配置无误。封禁检测不完善会让已被封的 IP 继续返回无效响应;认证配置错误则会导致 HTTP 407。
为避免封禁检测全凭猜测,本指南提供一个适用于 Scrapy 的四信号检测模型。它根据四个独立信号评估每个响应,避免因单次误报淘汰健康代理:
- 状态码: 将 403、429 和 503 视为封禁候选,将 200、301 和 302 视为健康。
- 重定向目标: 指向登录、captcha 或验证路径的 302 是一种软封禁,即使状态看起来正常。
- 正文特征: 扫描响应正文中的 captcha、访问被拒等标记,以及正常页面不应出现的空内容。
- 延迟: 响应时间远高于移动平均值,往往预示着即将发生限流或封禁。
将该策略编码到一个类中并注册它,使 BanDetectionMiddleware 使用你的逻辑而非默认逻辑:
# ban_policy.py
class DataImpulseBanPolicy:
NOT_BAN_STATUSES = {200, 301, 302}
def response_is_ban(self, request, response):
if response.status in (403, 429, 503):
return True
if b'captcha' in response.body.lower():
return True
if not response.body:
return True
return False
def exception_is_ban(self, request, exception):
return True
# settings.py
ROTATING_PROXY_BAN_POLICY = 'myproject.ban_policy.DataImpulseBanPolicy'
将检测机制与重试和退避策略结合,让被标记的请求切换到新的 IP,而不是直接失败。Scrapy 处理重试状态码,中间件处理按页面的代理重试:
# settings.py
RETRY_ENABLED = True
RETRY_TIMES = 5
RETRY_HTTP_CODES = [403, 407, 429, 500, 502, 503, 504]
ROTATING_PROXY_PAGE_RETRY_TIMES = 5
添加限流以免耗尽代理池。DOWNLOAD_DELAY 会拉开请求间隔,AUTOTHROTTLE 会根据服务器延迟自适应调整延迟:
# settings.py
DOWNLOAD_DELAY = 1.0
CONCURRENT_REQUESTS = 16
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 1.0
AUTOTHROTTLE_MAX_DELAY = 10.0
AUTOTHROTTLE_TARGET_CONCURRENCY = 4.0
如果请求返回 HTTP 407,说明是代理拒绝了你的凭据,而不是目标站点封禁了你。请检查用户名和密码是否完全按签发的样子嵌入在代理 URL 中,若包含特殊字符则需进行 URL 编码。完整的诊断见 DataImpulse 的HTTP 407 错误指南。只有在执行 JavaScript 后才显示内容的站点还需要一个无头层,具体见如何抓取动态网页。
哪种轮换代理配置适合你的 Scrapy 项目?
大多数爬取任务适合使用轮换网关;需要控制单个 IP 时可使用静态代理列表;只有轮换规则较特殊时才需要自定义中间件。选择取决于你需要的控制程度,以及愿意维护多少底层配置。
下面的决策矩阵让它更具体:
- 在以下情况使用轮换网关: 希望仅用一个端点实现按请求的 IP 多样性,目标站点按 IP 施加速率限制,且不想维护代理文件。
- 在以下情况使用静态代理列表: 你需要可复现的会话、希望为每个爬虫固定特定地区,或者必须精确审计使用了哪些端点时。
- 在以下情况避免使用自定义中间件: scrapy-rotating-proxies 已经满足你的需求时,因为自定义中间件会增加维护成本,也可能引入新的封禁检测缺陷。
- 在以下情况避免使用轮换网关: 只有工作流需要在多步登录期间保持同一个 IP 时,才应使用粘性会话。
以下是三种方法的对比:
| 方法 | 轮换控制 | 配置工作量 | 最佳适用 |
|---|---|---|---|
| 轮换网关(单端点) | 提供商按请求轮换 | 最低,settings 中一行 | 大规模爬取、应对基于 IP 的速率限制 |
| 代理列表文件 | 中间件循环使用你的端点 | 中等,维护一个代理文件 | 地区固定、可审计的代理池 |
| 自定义中间件 | 完全,由你编写逻辑 | 最高,代码加测试 | 非标准的轮换规则 |
DataImpulse 通过网关提供轮换,也支持需要保持连续性的粘性会话。因此,许多团队先使用网关,只为少数必须固定地区的爬虫保留代理列表文件。如果成本和速度比住宅信任度更重要,数据中心代理和移动代理是同一账号下的替代方案。
在 Scrapy 中轮换代理的局限性和风险是什么?
轮换代理可减少基于 IP 的封禁,但无法让爬虫完全隐形,也无法弥补不当的爬取行为。轮换只是其中一层保障,并非万无一失。
请牢记这些局限:
- 轮换无法战胜指纹识别。 站点还会分析请求头、TLS 签名和行为,因此即使是使用默认 Scrapy user agent 的新 IP 仍可能被标记。
- captcha 仍会出现。 轮换 IP 会降低它们触发的频率,但并不能解决它们;你仍需要一套 captcha 策略或更慢的爬取。
- 地理不匹配会制造噪声。 如果代理定向到某个国家,却请求另一地区的本地化页面,即使轮换正常,返回内容也可能不符合预期。
- 激进的并发会适得其反。 过多的并行请求会耗尽代理池并抬高封禁率,这正是 AUTOTHROTTLE 重要的原因。
- 存在法律和条款上的限制。 轮换是一种可靠性工具,而非许可;请尊重 robots 指令、速率限制和适用的法律。
需要明确的是,DataImpulse 是一个来源合规、用户自愿加入的代理网络,在 195 个国家拥有超过 9000 万个 IP;按量付费每 GB 1 美元起,成功率为 99.51%。它不是返回已解析数据的托管抓取 API,不出售静态 ISP 代理,也不是免费的网页代理。爬取工作仍由 Scrapy 完成;代理只改变请求从何处发出。

常见问题
如何在 Scrapy 中使用轮换代理?
安装 scrapy-rotating-proxies,在 settings.py 中将代理端点加入 ROTATING_PROXY_LIST 或 ROTATING_PROXY_LIST_PATH,并启用 RotatingProxyMiddleware 和 BanDetectionMiddleware 下载器中间件。之后每个请求都会通过轮换后的 IP 发出。
轮换网关和代理列表之间有什么区别?
轮换网关是一个端点,服务商会在其端按请求更换出口 IP,因此你只需配置一行。代理列表则包含多个端点,供中间件循环使用;需要固定地区或审计特定 IP 时更合适。
为什么我在 Scrapy 轮换代理中会遇到 HTTP 407 错误?
HTTP 407 意味着是代理拒绝了你的认证,而不是目标站点封禁了你。请确认用户名和密码已嵌入代理 URL,若包含特殊字符则需进行 URL 编码。
我如何确认我的 Scrapy 代理确实在轮换?
向像 httpbin.org/ip 这样的回显 IP 端点发送若干请求,并记录 origin 字段。如果所报告的 IP 在多个响应之间发生变化,则轮换已生效;如果保持不变,请检查中间件是否已启用以及 HTTP 缓存是否已关闭。
轮换代理会阻止所有抓取封锁吗?
不会。轮换能减少基于 IP 的速率限制和封禁,但站点还会使用指纹识别、captcha 和行为检查。请将轮换与合理的延迟、真实的请求头和 AUTOTHROTTLE 结合,以实现可靠的爬取。
什么情况下 DataImpulse 不合适?
如果你需要静态 ISP 代理、完全托管的抓取 API,或访问银行和政府站点,DataImpulse 可能并不适合。它专注于提供用于采集公开数据和访问内容的住宅、移动及数据中心轮换代理。
开始在 Scrapy 中轮换代理
将 scrapy-rotating-proxies 指向一个 DataImpulse 轮换网关,使每个请求都通过新的住宅 IP 发出。你可以从每 GB 1 美元起创建一个按量付费账号,然后将对应的网关配置直接写入 settings.py。
