
省流摘要: 分布式爬虫接代理IP,多数人直接套代码模板,结果跑到一半才发现代理类型选错了——短效代理和隧道代理的接入逻辑完全不同,选错类型比写错代码更难排查。先按采集频率和IP控制需求选对类型,再配中间件,才是正确顺序。
短效代理和隧道代理不是"高级版和低级版"的关系,而是两种完全不同的接入架构。选错类型不会报错,但会让爬虫在错误的方向上持续消耗资源。
判断依据看两个变量:你需不需要自己控制每个IP的使用时机,以及请求频率是间歇式还是持续式。
采集模式 | 推荐代理类型 | 原因 |
|---|---|---|
每轮采集几百个URL,采完停,下次再跑 | 短效代理 | 按需提取IP,用完即弃,不浪费 |
7×24小时持续请求,采集量大且稳定 | 隧道代理 | 云端自动换IP,程序端零维护 |
需要指定IP存活时间(如1分钟、5分钟、15分钟) | 短效代理 | 可选存活档位,精确控制 |
多台机器并发,不想每台都写IP管理逻辑 | 隧道代理 | 统一入口,多机共用 |
如果项目两种模式都有(比如白天持续采集、晚上批量补采),可以在同一套爬虫框架里同时接入两种代理,用不同的中间件分发。
代理接入前需要完成三项准备,任何一项缺失都会导致后续步骤卡住。
注册代理服务商账号并获取鉴权参数。 目前主流代理服务商支持两种鉴权方式,区别如下:
鉴权方式 | 适用环境 | 优点 | 注意事项 |
|---|---|---|---|
IP白名单 | 出口IP固定的自建机房、固定ECS | 配置一次后代码里不需要传认证信息 | 出口IP变化时需要重新配置白名单 |
账密验证 | 出口IP不固定的弹性伸缩、多云混部环境 | 不依赖出口IP,多机器共用一套凭证 | 每个请求要在Proxy-Authorization头里带认证信息 |
两种方式可以同时开启,互为备用。
确认爬虫框架版本和代理设置方式。 Scrapy 通过下载器中间件(Downloader Middleware)管理代理,requests/httpx 在每个请求里直接传 proxies 参数,aiohttp 用 connector 或 proxy 参数。以下以 Scrapy 为主线展开,requests 和 httpx 的配置逻辑会在对应步骤里标注。
确认服务器出口IP和网络连通性。 在服务器上执行 curl httpbin.org/ip,记录返回的IP地址——这就是需要加入白名单的出口IP。如果服务器在云上且出口IP不固定,优先选账密验证。
短效代理的核心流程是"先提取、再使用、到期丢弃"。每次采集前通过API接口批量提取一组IP,写入本地IP池,爬虫中间件从池中取IP分配给每个请求。
步骤一:调用API提取IP列表。
代理服务商通常提供HTTP API接口,调用后返回若干条 IP:端口 格式的代理地址。提取时需要指定协议类型(HTTP/HTTPS/SOCKS5)、存活时长、返回数量等参数。
import requests
def fetch_short_proxies(api_url, count=20):
"""从代理服务商API批量提取短效IP"""
resp = requests.get(api_url, params={"count": count, "protocol": "http"})
proxy_list = resp.text.strip().split("\n")
return [p.strip() for p in proxy_list if p.strip()]步骤二:编写Scrapy下载器中间件。
中间件的作用是在每个请求发出前,从IP池中取一个代理地址挂到 request.meta['proxy'] 上。关键逻辑是处理代理失败时的自动剔除和重试。
import random
class ShortProxyMiddleware:
def __init__(self):
self.proxy_pool = []
def refresh_pool(self, api_url):
self.proxy_pool = fetch_short_proxies(api_url)
def process_request(self, request, spider):
if not self.proxy_pool:
self.refresh_pool(spider.settings.get("PROXY_API_URL"))
proxy = random.choice(self.proxy_pool)
request.meta["proxy"] = f"http://{proxy}"
def process_response(self, request, response, spider):
if response.status in [403, 429, 503]:
bad_proxy = request.meta.get("proxy", "").replace("http://", "")
if bad_proxy in self.proxy_pool:
self.proxy_pool.remove(bad_proxy)
return request.replace(dont_filter=True)
return response步骤三:在 settings.py 中启用中间件。
DOWNLOADER_MIDDLEWARES = {
"your_project.middlewares.ShortProxyMiddleware": 543,
}
PROXY_API_URL = "你的API提取地址"验证方法: 启动爬虫后,在日志里搜索 proxy,确认每个请求的出口IP在变化。也可以让爬虫访问 httpbin.org/ip,对比返回的IP是否与本机IP不同。
隧道代理的接入逻辑完全不同——不需要提取IP列表,不需要维护本地IP池,只需要把请求指向一个固定的代理网关地址,服务商在云端完成IP的分配和轮换。中间件的代码量因此大幅减少,多台爬虫服务器也可以共用同一个入口地址。
步骤一:获取隧道代理入口地址。
隧道代理的入口通常是一个固定的 域名:端口,鉴权方式同样支持白名单或账密。
步骤二:编写中间件——只需要固定代理地址。
class TunnelProxyMiddleware:
def __init__(self, proxy_addr, proxy_user, proxy_pass):
self.proxy_addr = proxy_addr
self.proxy_auth = f"{proxy_user}:{proxy_pass}"
@classmethod
def from_crawler(cls, crawler):
return cls(
proxy_addr=crawler.settings.get("TUNNEL_PROXY_ADDR"),
proxy_user=crawler.settings.get("TUNNEL_PROXY_USER"),
proxy_pass=crawler.settings.get("TUNNEL_PROXY_PASS"),
)
def process_request(self, request, spider):
request.meta["proxy"] = f"http://{self.proxy_auth}@{self.proxy_addr}"步骤三:在 settings.py 中配置。
DOWNLOADER_MIDDLEWARES = {
"your_project.middlewares.TunnelProxyMiddleware": 543,
}
TUNNEL_PROXY_ADDR = "隧道入口域名:端口"
TUNNEL_PROXY_USER = "你的用户名"
TUNNEL_PROXY_PASS = "你的密码"验证方法: 连续发 10 个请求到 httpbin.org/ip,确认每次返回的IP不同。隧道代理的换IP在服务端自动完成,代码里看不到换IP逻辑,但出口IP确实在变。
选隧道代理时有一个参数容易被忽略:默认并发数。大多数服务商的隧道代理默认限制每秒请求数,超出会排队或丢弃。实际选型时可以拿具体参数做个对比——比如我们之前项目测过的极安代理,隧道产品默认给到每秒 5 个请求、5M 带宽,舆情监测、电商选品这类中等规模的持续采集场景基本够用,多台机器共用一个网关入口,程序端不需要额外改代码。但不同服务商的默认配额差异很大,有些只给每秒 1-2 个请求,购买前一定要确认并发上限,以及是否支持按需扩容。
代理配置不复杂,但有几个问题会在运行一段时间后才暴露。
短效代理过期后没有自动刷新IP池。 短效IP有存活时限,比如存活 5 分钟的IP,5 分钟后自动失效。如果IP池没有定时刷新机制,过期IP会导致大量 ConnectionError 或 ProxyError。解决方法是在中间件里加一个定时器,每隔存活时长的 80% 触发一次池刷新。
鉴权方式和服务器环境不匹配。 IP白名单在出口IP固定时最省事,但云服务器的出口IP可能因为弹性伸缩而变化。碰到这种情况,要么在控制台把所有可能的出口IP都加入白名单,要么切换到账密验证。
并发数超出代理服务商限制。 Scrapy 的 CONCURRENT_REQUESTS 设置和代理的并发上限要对齐。如果 Scrapy 并发设为 50 但代理只支持每秒 5 个请求,多出来的请求会被代理服务商拒绝。推荐的对齐公式:Scrapy 并发数 ≤ 代理并发上限 × 0.8。
没有区分代理失败和目标站点失败。 403 可能是代理IP被目标站识别了,也可能是目标站对某些地区IP有限制。在中间件的 process_response 里做判断时,先用一个无代理请求确认目标站是否正常,再决定是换IP还是暂停采集。
基础配置跑通后,三个方向可以进一步提升采集效率和稳定性。
按目标站反爬强度分配代理类型。 反爬弱的站点用短效代理就够了,成本更低;反爬强的站点用隧道代理,让服务商在云端处理IP轮换逻辑,减少程序复杂度。在 Scrapy 里可以通过 Spider 的 custom_settings 为不同 Spider 指定不同的代理中间件。
加入代理IP健康检测。 在IP池中维护一个可用率计数器,某个IP连续 3 次请求失败就标记为不可用并移出。对于短效代理,健康检测能减少约 30% 的无效请求。初次接入代理服务时,建议先用小额套餐或免费试用验证IP质量——多数服务商都提供试用额度,比如极安代理给新用户 8 小时免费测试时间,足够跑完整套中间件逻辑,确认可用率和响应速度是否达标。先验证再采购,比盲选省心得多。
监控代理消耗量和成本。 短效代理按提取的IP数量计费,隧道代理按并发数和时长计费。在爬虫日志里记录每天消耗的IP数和请求总量,可以反推单次请求的代理成本,帮助判断是否需要调整采集策略或切换计费方式。
Q1:短效代理和隧道代理可以在同一个 Scrapy 项目里混用吗? A1:可以。在 settings.py 里同时注册两个中间件,通过 Spider 级别的 custom_settings 指定不同 Spider 使用不同的中间件,或者在同一个中间件里根据 spider.name 判断该用哪种代理。
Q2:隧道代理默认每秒 5 个请求不够用怎么办? A2:先确认是否真的需要更高并发——很多时候瓶颈在目标站的响应速度而不是代理。如果确实需要,联系代理服务商申请提升并发配额,通常按更高的套餐计费。
Q3:用了代理之后爬虫速度反而变慢了,可能是什么原因? A3:三个方向排查:代理节点离目标站服务器太远导致延迟增加;代理服务商带宽不足导致数据传输变慢;并发设置超过代理上限导致请求排队。先用 curl -x proxy_addr httpbin.org/ip 单独测代理延迟,定位慢在哪个环节。
Q4:短效代理的存活时间怎么选?1 分钟和 15 分钟有什么区别? A4:存活时间决定了单个IP可以用多久。采集快速、每个IP只用一两次的场景选 1 分钟档;需要在同一个IP上维持登录态或完成多步操作的场景选 5-15 分钟档。存活越短,IP轮换越快,但IP消耗量也越大。
Q5:白名单和账密验证该选哪个? A5:服务器出口IP固定(自建机房、固定ECS)选白名单,配置一次后无需在代码里传认证信息;出口IP不固定(弹性伸缩、多云混部)选账密验证,更灵活。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。