跳到正文

Scrapy 动态代理:中间件与重试规则

能直接用的 Scrapy 代理配置、真正要紧的重试规则,以及怎样对被抓网站保持克制。

一个入口,两种写法

动态代理就是一个地址和端口加账号密码,出口 IP 由服务端轮换,不用自己管 IP 列表。Scrapy 从请求 meta 的 proxy 键读取代理,账号密码可以写在 URL 里:http://username:password@some_proxy_server:port。meta 的值优先于 http_proxy、https_proxy 环境变量。

只有部分请求要走代理,就写在对应的 Request 上;所有请求都要走,就用一个小的下载中间件。环境变量和密码里的特殊字符,已有的“Scrapy 代理设置”那篇讲过;这一篇讲轮换和重试。

设置代理的下载中间件

# middlewares.py
class ProxyMiddleware:
    def process_request(self, request, spider):
        # Only set it when the request does not carry its own proxy.
        request.meta.setdefault("proxy", "http://LOGIN:PASSWORD@HOST:PORT")

# settings.py
DOWNLOADER_MIDDLEWARES = {
    "myproject.middlewares.ProxyMiddleware": 350,
}

仅为示例。优先级 350 会先于内置的 HttpProxyMiddleware 运行,后者读取 meta 里的值。

轮换不等于每个请求一个新 IP

动态入口在每个新连接上换 IP。Scrapy 可能让一条连接保持着,在上面连发几个请求,几个请求就可能共用一个 IP。别假设“一请求一 IP”:先用下面的爬虫把出口 IP 打到日志里,再做判断。

任务必须停在同一个地址上时,比如登录后再看几页,就生成“指定地区 / 保持 IP”的粘性模式,并把这些请求放在一起。互不相关的页面,用“指定地区 / 每次换 IP”模式。

打印出口 IP 的爬虫

import scrapy

PROXY = "http://LOGIN:PASSWORD@HOST:PORT"

class IpCheckSpider(scrapy.Spider):
    name = "ip_check"

    def start_requests(self):
        for i in range(5):
            yield scrapy.Request(
                "https://ipinfo.io/ip?n=%d" % i,
                meta={"proxy": PROXY, "max_retry_times": 3},
                dont_filter=True,
            )

    def parse(self, response):
        self.logger.info("exit IP: %s", response.text.strip())

仅为示例。填入“我的资产”里的代理,用 scrapy crawl ip_check 运行,看日志里的 IP。start_requests 仍是经典入口,新版 Scrapy 另有异步的 start()。

哪些状态码该重试

哪些状态码该重试
项目默认是否重试怎么处理
408、500、502、503、504、522、524是让 RetryMiddleware 重试,中间要有间隔
429是网站要你放慢:降低频率,遵守 Retry-After
403、404否重发结果一样;检查网址和网站规则
407否代理账号密码被拒:改正 LOGIN 和 PASSWORD,不要重试

来源:Scrapy 下载器中间件文档(默认 RETRY_HTTP_CODES),2026-11-12 阅读;“怎么处理”一列是建议。不同 Scrapy 版本的默认值可能不同。

重试与克制相关的设置

# settings.py
ROBOTSTXT_OBEY = True
DOWNLOAD_TIMEOUT = 30

# retries (the documented defaults)
RETRY_ENABLED = True
RETRY_TIMES = 2                      # extra tries after the first download
RETRY_HTTP_CODES = [408, 429, 500, 502, 503, 504, 522, 524]

# be gentle with the target site
DOWNLOAD_DELAY = 1.0
CONCURRENT_REQUESTS_PER_DOMAIN = 4
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 1.0
AUTOTHROTTLE_MAX_DELAY = 30.0
AUTOTHROTTLE_TARGET_CONCURRENCY = 2.0

仅为示例。RETRY_TIMES 指首次下载之外额外重试的次数。单个请求可设 meta["max_retry_times"],或 meta["dont_retry"] = True 跳过重试。

AutoThrottle 与请求间隔

AutoThrottle 默认关闭。打开后,它按网站的响应速度算延迟,不会低于 DOWNLOAD_DELAY,且非 200 的响应不能缩短延迟,所以出错时是放慢而不是加速。默认 START_DELAY 为 5.0,MAX_DELAY 为 60.0,TARGET_CONCURRENCY 为 1.0。

保持 ROBOTSTXT_OBEY 开启,明确设置 DOWNLOAD_DELAY 和 CONCURRENT_REQUESTS_PER_DOMAIN,不要依赖默认值,并读一下网站条款。代理改变的是请求从哪来,不改变网站能承受多少请求。

四步配好

  1. 第 1 步:生成代理

    在动态住宅页选国家、出口方式和 HTTP / SOCKS5,然后生成。HTTP 用 2222 端口,SOCKS5 用 3333 端口。

  2. 第 2 步:加上代理

    在“我的资产”复制地址、端口、账号、密码,设置 meta["proxy"] 或加上中间件。

  3. 第 3 步:检查出口 IP

    运行 ip_check 爬虫,看日志里的 5 个 IP。

    预期结果 5 个 IP,国家和你选的一致。

  4. 第 4 步:加上重试和延迟设置

    粘贴设置,先跑一个小爬取,在结束时的 Scrapy 统计里看重试次数和 429 次数。

排查

响应全是 407,或代理毫无回应

检查 meta 的值是不是带协议头的完整 URL,LOGIN 和 PASSWORD 有没有原样复制?

处理 改正 URL,密码里的特殊字符做百分号编码,先用 curl -x 测。

停止条件 别加大 RETRY_TIMES:密码错了每次都会失败。

大量 429

检查 看 CONCURRENT_REQUESTS_PER_DOMAIN、DOWNLOAD_DELAY 和 Retry-After 响应头。

处理 降低并发、加大延迟、打开 AutoThrottle。

停止条件 频率很低仍是 429,说明网站可能不允许这样爬,先停。

登录后的页面丢了会话

检查 登录和下一页之间,出口 IP 有没有变?

处理 这类流程用粘性模式,并把这些请求放在一起。

常见问题

Scrapy 里怎么用动态代理?

在每个 Request 上把 request.meta["proxy"] 设为 http://LOGIN:PASSWORD@HOST:PORT,或写进一个小的下载中间件。

Scrapy 默认重试哪些状态码?

408、429、500、502、503、504、522、524,额外重试 RETRY_TIMES 次(默认 2)。请以你的 Scrapy 版本文档为准。

403 或 407 要重试吗?

不要。407 是代理拒绝了账号密码,要改正;403 通常重发还是 403,应检查网址和网站规则。

每个请求都会换一个 IP 吗?

不一定。新连接才换 IP,而 Scrapy 可以在一条连接上发多个请求。把出口 IP 打进日志,就知道你的配置里实际如何。

Proxy302 动态住宅多少钱?

低价线路 US$1.50/GB,大包每 GB 更低,买到的流量不过期。没有免费试用。

参考资料

5
  1. Proxy302 产品事实与价格表

    产品观察 · 确认日期:

    站内产品事实表,2026-11-12 核对:动态住宅每个新连接换 IP,可选粘性模式,proxy.proxy302.com 上 HTTP 端口 2222、SOCKS5 端口 3333,低价线路 US$1.50/GB,无免费试用。

  2. Scrapy 文档:下载器中间件

    官方文档 · 确认日期:

    2026-11-12 阅读:HttpProxyMiddleware 读取请求 meta 里的 proxy,可写 http://username:password@some_proxy_server:port,且 meta 的值优先于环境变量;RetryMiddleware 默认 RETRY_ENABLED 为 True、RETRY_TIMES 为 2、RETRY_HTTP_CODES 为 [408, 429, 500, 502, 503, 504, 522, 524];meta 键 max_retry_times 和 dont_retry;RobotsTxtMiddleware 受 ROBOTSTXT_OBEY 控制。

  3. Scrapy 文档:AutoThrottle 扩展

    官方文档 · 确认日期:

    2026-11-12 阅读:默认关闭;AUTOTHROTTLE_START_DELAY 5.0、AUTOTHROTTLE_MAX_DELAY 60.0、AUTOTHROTTLE_TARGET_CONCURRENCY 1.0;延迟由响应延迟算出,不会低于 DOWNLOAD_DELAY,非 200 响应不能缩短延迟。

    默认值来自文档开发版,请以你安装的 Scrapy 版本为准。

  4. Scrapy 文档:设置

    官方文档 · 确认日期:

    2026-11-12 阅读:DOWNLOAD_DELAY 是对同一域名两次连续请求之间的最小间隔秒数;CONCURRENT_REQUESTS_PER_DOMAIN 限制对单个域名的并发请求;ROBOTSTXT_OBEY 让 Scrapy 遵守 robots.txt;DOWNLOAD_TIMEOUT 是下载器等待超时的时间。

  5. MDN:429 Too Many Requests

    官方文档 · 确认日期:

    2026-11-12 阅读:429 表示一段时间内请求过多;Retry-After 可能说明等多久。

准备好试试了吗?

注册账号、充值一次,就能选动态住宅、静态 ISP 或数据中心 IP,几分钟配进你的浏览器。