
基础方案:自定义代理池中间件(推荐)
编写代理中间件(middlewares.py)
通过自定义下载中间件,可灵活控制代理池的管理逻辑,包括代理分配、认证处理及失效重试:
import random
import base64
class RotateProxyMiddleware:
# 代理池(可从文件/API加载)
PROXY_POOL = [
"http://123.123.123.123:8888",
"http://45.45.45.45:9999",
"http://user:pass@67.67.67.67:7777", # 带认证
# 更多代理...
]
def process_request(self, request, spider):
# 随机选代理
proxy = random.choice(self.PROXY_POOL)
request.meta["proxy"] = proxy
# 处理带账号密码的代理认证
if "@" in proxy:
auth_str = proxy.split("@")[0].replace("http://", "").replace("https://", "")
encoded = base64.b64encode(auth_str.encode()).decode()
request.headers["Proxy-Authorization"] = f"Basic {encoded}"
spider.logger.info(f"使用代理: {proxy}")
return None # 继续处理
# 代理失效时重试
def process_exception(self, request, exception, spider):
bad_proxy = request.meta.get("proxy")
spider.logger.error(f"代理失效: {bad_proxy}, 异常: {exception}")
# 复制请求并跳过去重,重新发起
new_req = request.copy()
new_req.dont_filter = True
return new_req
启用中间件(settings.py)
关闭Scrapy默认的代理中间件,启用自定义中间件以确保代理逻辑生效:
# 关闭默认代理中间件,启用自定义
DOWNLOADER_MIDDLEWARES = {
"scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": None,
"你的项目名.middlewares.RotateProxyMiddleware": 543, # 优先级适中
}
进阶方案:借助第三方库简化实现
对于快速开发场景,可借助成熟的第三方库减少自定义代码量,提升开发效率。
方案A:scrapy-proxies轻量随机轮换
适用于对代理轮换逻辑要求简单的场景,支持随机、固定等多种代理分配模式:
pip install scrapy-proxies
在settings.py中配置:
DOWNLOADER_MIDDLEWARES = {
"scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": 110,
"scrapy_proxies.RandomProxy": 100,
}
# 代理列表(文件路径或直接列表)
PROXY_LIST = [
"http://ip:port",
"http://user:pass@ip:port",
]
# 模式0:随机轮换;1:固定一个;2:自定义
PROXY_MODE = 0
方案B:scrapy-rotated-proxy支持代理拉黑/恢复
具备代理有效性自动检测与拉黑功能,可自动剔除失效代理并在指定时长后恢复:
pip install scrapy-rotated-proxy
在settings.py中配置:
DOWNLOADER_MIDDLEWARES.update({
"scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": None,
"scrapy_rotated_proxy.downloadmiddlewares.proxy.RotatedProxyMiddleware": 750,
})
ROTATED_PROXY_ENABLED = True
# 代理文件路径(一行一个)
PROXY_FILE_PATH = "proxies.txt"
# 代理失效后拉黑时长(秒)
PROXY_BLOCK_SECONDS = 300
动态代理池:从API实时获取代理
手动维护代理池易出现IP失效、资源不足等问题,通过服务商API实时拉取代理可解决这一痛点:
import requests
import random
class DynamicProxyMiddleware:
def get_proxies(self):
# 调用代理API获取列表(示例)
resp = requests.get("https://your-proxy-api.com/get?count=10")
return [f"http://{ip}" for ip in resp.json()["data"]]
def process_request(self, request, spider):
proxy = random.choice(self.get_proxies())
request.meta["proxy"] = proxy
return None
关键实现要点
代理格式规范
所有代理必须带协议前缀(http:///https:///socks5://),否则Scrapy无法识别代理类型,导致请求失败。
认证信息处理
带账号密码的代理需将认证信息编码后添加到Proxy-Authorization请求头中,确保代理服务器能通过身份验证。
异常重试机制
在process_exception方法中复制原请求并设置dont_filter=True,跳过Scrapy的去重机制,确保失效代理的请求能重新分配新代理并发起。
中间件优先级设置
自定义代理中间件的优先级需高于默认的HttpProxyMiddleware,一般设置在500-600区间,确保自定义逻辑优先执行。
选择专业代理IP服务商保障Scrapy业务稳定性
对于需要长期稳定运行的Scrapy采集业务,依赖免费或手动维护的代理池易出现IP质量差、稳定性不足等问题,专业企业级代理IP服务商能提供更可靠的解决方案,青果网络就是其中的典型选择:
海量纯净IP资源覆盖
青果网络国内代理资源基于三大运营商宽带构建,每日更新600万+纯净IP资源,覆盖全国300多个城市与地区;针对跨境采集需求,还提供2000W+纯净全球HTTP与海外代理IP资源池,可满足不同地域的采集需求,避免IP资源不足导致的业务中断。
高可用的代理调用稳定性
青果网络采用自研代理服务端,所有IP上线前均检测验证,网络延迟低于100毫秒,可用率高达99.9%,同时采用业务分池技术,整体业务成功率比行业平均高出约30%,能有效保障Scrapy采集过程中的请求稳定性,减少因代理失效导致的重试成本。
适配业务场景的灵活产品类型
青果网络产品类型覆盖国内代理IP、全球HTTP、短效代理、隧道代理、静态代理与独享代理,可根据Scrapy业务的不同需求选择合适的代理类型:比如短效代理适合需要频繁切换IP的高频采集场景,隧道代理则适合需要保持会话一致性的采集需求。
便捷的测试与技术支持
青果网络提供国内代理IP 6小时测试与全球HTTP 2小时体验,技术团队7×24小时在线支持,能帮助开发者快速验证代理适配性,在遇到接入或运行问题时及时得到响应,降低业务落地的试错成本。
总结
Scrapy中实现自动切换代理IP的核心是通过下载中间件管理代理池,可根据业务需求选择自定义中间件、第三方库或动态API拉取的实现方式;对于长期稳定的采集业务,选择专业的企业级代理IP服务商如青果网络,能获得更优质的IP资源、更高的调用稳定性及配套技术支持,有效提升采集效率与业务连续性。
常见问题解答
Q1:Scrapy中代理中间件的优先级设置有什么要求?
A1:自定义代理中间件的优先级应高于默认的HttpProxyMiddleware,一般设置在500-600之间,确保自定义中间件先于默认中间件处理请求,避免代理设置被覆盖。
Q2:带账号密码的代理在Scrapy中如何处理认证?
A2:需要从代理地址中提取账号密码信息,通过base64编码后添加到请求头的Proxy-Authorization字段中,格式为Basic 编码后的字符串,这样Scrapy请求时会自动携带认证信息通过代理服务器验证。
Q3:为什么重试请求需要设置dont_filter=True?
A3:Scrapy默认会对重复请求进行过滤,若重试请求不设置dont_filter=True,会被去重机制拦截而无法重新发起,设置该参数可以跳过去重,确保失效代理的请求能重新分配新代理并执行。