Scrapy 代理中介軟體:完整設定指南(2026)

發佈於 2026年6月4日 · 約 11 分鐘閱讀

Scrapy 在 2026 年仍是生產級爬取的主力——也仍是最讓人搞不懂代理設定的框架,因為有四個不同的地方可以插入代理,而其中三個對大多數專案來說都是錯的。本指南給你正確的那一個:一個帶有每請求路由、黏性工作階段、封鎖偵測與合理重試行為的小型自訂中介軟體。

如果你用的是純 requestshttpxaiohttp,請參見 如何在 Python 中輪換代理。本文是 Scrapy 專屬的。

30 秒版本

對於輪換式住宅閘道,最小可行設定就是每個請求一行——不需要中介軟體:

def start_requests(self):
    for url in self.urls:
        yield scrapy.Request(
            url,
            meta={"proxy": "http://USERNAME:[email protected]:913"},
        )

Scrapy 內建的 HttpProxyMiddleware 會讀取 request.meta["proxy"] 並從 URL 處理驗證。閘道替你輪換出口 IP。如果你需要的就這些,到此為止。本指南其餘部分是給你需要控制的時候:黏性工作階段、國家路由、封鎖感知的輪換,以及並行度調校。

一個生產級的代理中介軟體

把這段放進 middlewares.py。它替每個網域指派黏性工作階段、在被封鎖時輪換,並為每個請求加標籤,讓你能除錯是哪個工作階段抓了什麼:

import random
import string

GATEWAY = "us.jibaoproxy.com:913"
USERNAME = "USERNAME"          # move to settings.py / env in real projects
PASSWORD = "PASSWORD"

def _new_session(n=8):
    return "".join(random.choices(string.ascii_lowercase + string.digits, k=n))

class JibaoProxyMiddleware:
    """Sticky session per domain; rotate session on ban."""

    def __init__(self):
        self.sessions = {}          # domain -> session id

    def _proxy_url(self, session_id):
        user = f"{USERNAME}-session-{session_id}"
        return f"http://{user}:{PASSWORD}@{GATEWAY}"

    def process_request(self, request, spider):
        domain = request.url.split("/")[2]
        session = self.sessions.setdefault(domain, _new_session())
        request.meta["proxy"] = self._proxy_url(session)
        request.meta["proxy_session"] = session

    def rotate(self, domain):
        """Call when a session is burned."""
        self.sessions[domain] = _new_session()

再配一個下載器中介軟體,偵測封鎖並在新工作階段上重試:

from scrapy.downloadermiddlewares.retry import RetryMiddleware
from scrapy.utils.response import response_status_message

BAN_CODES = {403, 429}
BAN_MARKERS = (b"captcha", b"access denied", b"unusual traffic")

class BanAwareRetryMiddleware(RetryMiddleware):

    def process_response(self, request, response, spider):
        banned = (
            response.status in BAN_CODES
            or any(m in response.body[:2048].lower() for m in BAN_MARKERS)
        )
        if banned:
            domain = request.url.split("/")[2]
            proxy_mw = spider.crawler.engine.downloader.middleware.middlewares
            for mw in proxy_mw:
                if hasattr(mw, "rotate"):
                    mw.rotate(domain)        # burn the session
            reason = response_status_message(response.status)
            return self._retry(request, reason, spider) or response
        return super().process_response(request, response, spider)

settings.py 裡把兩者接上線:

DOWNLOADER_MIDDLEWARES = {
    "myproject.middlewares.JibaoProxyMiddleware": 350,
    "scrapy.downloadermiddlewares.retry.RetryMiddleware": None,   # replace stock retry
    "myproject.middlewares.BanAwareRetryMiddleware": 550,
}
RETRY_TIMES = 2

優先順序很重要:代理中介軟體必須在 Scrapy 的 HttpProxyMiddleware(750)之前執行,所以任何低於 750 的值都行;350 讓它保持在前面且可預期。

黏性 vs 輪換:哪種爬蟲用哪種模式

爬取類型模式實作
無狀態頁面採集輪換裸使用者名稱,閘道每請求輪換
登入 + 在驗證後爬取每帳號黏性-session-{account_id},登入途中絕不輪換
分頁繁重的列表每網域黏性,被封鎖時輪換上面的中介軟體
特定地區定價輪換 + 國家固定USERNAME-country-de 式的參數

對此取捨的更深入探討:黏性 vs 輪換代理工作階段

不會害你被封的並行設定

Scrapy 的預設值是為禮貌的單 IP 爬取調的。在輪換池後面你可以推得更猛——但每網域限制仍然重要,因為目標看到的是聚合行為:

# settings.py - sane starting point behind a residential pool
CONCURRENT_REQUESTS = 64
CONCURRENT_REQUESTS_PER_DOMAIN = 8     # what the target experiences
DOWNLOAD_DELAY = 0.25                  # jitter applied per slot
RANDOMIZE_DOWNLOAD_DELAY = True        # 0.5x-1.5x the delay
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_TARGET_CONCURRENCY = 6.0
DOWNLOAD_TIMEOUT = 30
ROBOTSTXT_OBEY = True

只有在目前水準下觀察你的 403 比率好幾千個請求之後,才調高 CONCURRENT_REQUESTS_PER_DOMAIN。因為「反正代理會輪換」就從 8 → 32,正是大家在重試上燒掉 GB 的方式。

頻寬紀律(住宅 GB 是錢)

常見失敗以及它們實際的意思

407 Proxy Authentication Required

憑證沒送達代理。把它們放進 meta["proxy"] 的 URL 裡(http://user:pass@host:port)——Scrapy 會替你解析並設定 Proxy-Authorization。同時手動設標頭用 URL 憑證會造成雙重驗證的怪象;二選一。

TunnelError: Could not open CONNECT tunnel

幾乎都是主機/連接埠打錯字,或 HTTPS 目標走了一個不允許在該連接埠用 CONNECT 的端點。先在 Scrapy 之外用 curl -x 驗證。

爬蟲跑了 10 分鐘,然後全部變 403

你的黏性工作階段活過頭了,或你的每網域速率太燙。上面的封鎖感知中介軟體處理第一種情況;第二種就調低 CONCURRENT_REQUESTS_PER_DOMAIN。如果是個檢查 JA4 的目標,Scrapy 的 TLS 堆疊本身可能就是破綻——參見 JA3/JA4 詳解 看為何沒有代理能修好那個。

Free tool · no signup

在爬取之前驗證你的代理清單

把端點貼進我們的 Proxy Checker:它批次測試連通性、延遲、匿名等級與出口 IP 類型——在 Scrapy 為失效或標錯的代理浪費重試之前就抓出它們。

Check my proxies →

厭倦了照顧免費清單?一個住宅閘道就取代全部——領取 500M免費流量 →

總結

把你的爬蟲指向一個真正的池子

同一個閘道上的輪換與黏性住宅工作階段。500M免費流量,拿來爬。

Start Free Trial

適用於所有 IP 產品 · 龐大的節點池隨時可用

立即註冊,儲值最高可享 100% 返現

新用戶註冊即送 500M免費流量,首次儲值另有贈金。優惠限時供應。