Jak skonfigurować własny proxy w Scrapy (gotowe do użycia w produkcji)

Ostatnia aktualizacja: August 11, 2026
Hand-drawn Scrapy crawler routing through a proxy pool, retrying a 503 route and completing through a 200 route
Podsumowanie AI
  • Zbuduj własny middleware proxy dla Scrapy, które przypisuje zatwierdzone trasy, bezpiecznie dodaje uwierzytelnianie, rejestruje powody błędów i zachowuje metadane requestów podczas ponawiania prób.
  • Zrozum kolejność działania downloader middleware, zwłaszcza sposób, w jaki logika własnego proxy współpracuje z HttpProxyMiddleware, RetryMiddleware, przekierowaniami i obsługą wyjątków.
  • Dodaj rotację z ograniczoną liczbą prób, okresami schłodzenia, stanem kondycji proxy oraz polityką zależną od celu zamiast wybierania losowego proxy dla każdego requestu.
  • Rozróżniaj błędy autoryzacji proxy, błędy połączenia, problemy DNS, odpowiedzi 403 od celu i limity żądań, aby każda sytuacja otrzymała właściwą reakcję.
  • Stosuj zabezpieczenia produkcyjne dla przechowywania sekretów, współbieżności, obserwowalności, spójności sesji i zachowania fail-closed, gdy nie ma już dostępnego zatwierdzonego proxy.

Twój spider Scrapy bez problemu przechodzi 100 testowych stron, a potem rozsypuje się przy 10 000. To wcale nie musi być błąd scrapingu — często to problem sieciowy, który tylko wygląda jak błąd scrapingu. Najczęściej sięga się wtedy po proxy, a wrzucenie go do request.meta zajmuje dosłownie jakieś 30 sekund.

Problem polega na tym, że na tym zwykle kończą się większość podstawowych poradników. Pokazują meta={"proxy": "http://IP:PORT"}, czasem dorzucają klasę middleware i uznają temat za zamknięty. Zazwyczaj pomijają to, co dzieje się, gdy proxy padnie w trakcie crawl'a, jak nie dopuścić do wycieku danych uwierzytelniających do historii Git, albo dlaczego ponowna próba może użyć dokładnie tego samego, wadliwego proxy. To właśnie są kwestie produkcyjne, które omawia ten przewodnik: konfiguracja fail-closed, zarządzanie sekretami, świadomy dobór proxy przy retry, ograniczenia protokołów i mierzalne kompromisy kosztowe.

Czym jest proxy middleware w Scrapy?

Proxy middleware to kawałek kodu, który działa w potoku pobierania danych Scrapy i decyduje, z jakiego adresu IP ma wyglądać dany request, zanim trafi on do sieci. Scrapy ma wbudowane rozwiązanie, HttpProxyMiddleware, które odczytuje klucz proxy z request.meta, dodaje autoryzację proxy, jeśli jest potrzebna, i przekazuje request do download handlera, który faktycznie otwiera połączenie. Własne proxy middleware nie zastępuje tego etapu transportu — ono jest selektorem, który wybiera proxy, zanim wbudowany mechanizm przejmie sterowanie. Ta różnica jest ważniejsza, niż może się wydawać, i właśnie ona stoi za większością zgłoszeń w stylu „moje custom middleware nie działa”.

Dlaczego proxy ma znaczenie w projektach Scrapy produkcyjnie

Proxy zmienia trasę sieciową i widoczny adres IP. Może pomóc w legalnych testach geolokalizacyjnych, rozdzielaniu autoryzowanego ruchu i izolowaniu awarii sieci. Nie daje jednak pozwolenia, nie omija limitów ani nie gwarantuje dostępu. To, czy crawl w ogóle potrzebuje proxy, zależy od celu, jego warunków, częstotliwości zapytań i wymagań dotyczących niezawodności.

Nie każde proxy jest takie samo, a wybór złego typu to osobna awaria produkcyjna:

Typ proxyNiezawodnośćSzybkośćRyzyko wykryciaTypowy koszt
Darmowe publiczne proxyBardzo zmiennaZmiennaCzęsto wysokieBrak opłaty, ale duże ryzyko bezpieczeństwa i operacyjne
Proxy datacenterZależne od dostawcy i celuCzęsto szybkieZależne od celuZwykle rozliczane za GB lub IP
Proxy residentialZależne od dostawcy i celuZmiennaZależne od celuZwykle rozliczane za GB
Proxy ISPZależne od dostawcy i celuZmiennaZależne od celuZależne od dostawcy

Na darmowe proxy warto patrzeć bardzo ostrożnie, bo ryzyko jest realnie spore. 30-miesięczne badanie Free Proxies Unmasked objęło ponad 640 000 adresów od 11 dostawców: 34,5% było aktywnych przynajmniej raz, a 16 923 modyfikowały treść. To wystarczająca podstawa, żeby mocno ostrzegać przed publicznymi listami; nie jest to jednak uniwersalny wskaźnik awaryjności dla każdej aktualnej listy, płatnej puli, celu czy obciążenia.

Proxy też nie gwarantują obejścia nowoczesnych systemów bot-detekcji. Usługi takie jak Cloudflare oceniają requesty na podstawie dziesiątek sygnałów — fingerprintu TLS, spójności nagłówków, wykonania JavaScriptu, wzorców zachowania — a adres IP jest tylko jednym z wielu czynników. Czyste residential proxy przy requestach z niespójnymi nagłówkami i bez cookie jar nadal może zostać oznaczone jako podejrzane. Warto mieć realistyczne oczekiwania, zanim zbudujesz całą architekturę wokół hasła „po prostu rotuj IP”.

Zanim zaczniesz

  • Poziom trudności: średni
  • Czas potrzebny: około 30–45 minut na pełną konfigurację produkcyjną, około 5 minut na szybki test
  • Czego potrzebujesz: Python 3.9+, zainstalowany Scrapy (ten przewodnik testowano na Scrapy 2.17.0, wydanym w lipcu 2026), działający spider utworzony przez scrapy startproject oraz przynajmniej jeden endpoint proxy (na potrzeby testu wystarczy darmowy trial od dowolnego dostawcy proxy datacenter)

Krok 1: Przetestuj proxy przez parametr request.meta

Najszybszy sposób sprawdzenia, czy proxy działa, to całkowicie ominąć architekturę middleware i po prostu je przetestować.

Wbudowane HttpProxyMiddleware w Scrapy odczytuje klucz proxy bezpośrednio z request.meta i kieruje przez niego request. Bez zmian w ustawieniach, bez klasy middleware — tylko jeden argument.

import scrapy

class ProxyTestSpider(scrapy.Spider):
    name = "proxy_test"
    start_urls = ["https://httpbin.org/ip"]

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(
                url,
                meta={"proxy": "http://203.0.113.10:8080"},
                callback=self.parse,
            )

    def parse(self, response):
        self.logger.info(response.text)

Uruchom to poleceniem scrapy runspider proxy_test.py. Jeśli proxy działa, httpbin.org/ip zwróci IP proxy zamiast Twojego — i to będzie potwierdzenie. Jeśli odpowiedź wisi i finalnie kończy się błędem TCP connection timed out, proxy jest martwe albo niedostępne, co — nie będzie zaskoczeniem — zdarza się częściej, niż dostawcy proxy lubią przyznawać.

Ta metoda jest dobra przy jednorazowych spiderach albo szybkich testach. Rozsypuje się jednak wtedy, gdy masz więcej niż jednego spidera, bo nagle wpisujesz ten sam adres proxy na sztywno w pięciu różnych plikach.

Krok 2: Zbuduj własny proxy middleware

Jeśli wykraczasz poza pojedynczego spidera, logika proxy powinna być scentralizowana w jednym miejscu. Utwórz klasę ProxyMiddleware w pliku middlewares.py w swoim projekcie:

from scrapy.exceptions import NotConfigured

class ProxyMiddleware:
    def __init__(self, proxy_url):
        self.proxy_url = proxy_url

    @classmethod
    def from_crawler(cls, crawler):
        proxy_url = crawler.settings.get("PROXY_URL")
        if not proxy_url:
            raise NotConfigured("PROXY_URL is required; refusing silent direct fallback")
        return cls(proxy_url=proxy_url)

    def process_request(self, request, spider):
        if "proxy" not in request.meta:
            request.meta["proxy"] = self.proxy_url

A potem zarejestruj je w settings.py:

import os

PROXY_URL = os.environ.get("PROXY_URL")

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

Zwróć uwagę na metodę klasową from_crawler zamiast zwykłego __init__. To właśnie rekomendowany przez Scrapy sposób czytania ustawień, i ten sam mechanizm przyda nam się ponownie w kroku 4, gdy będziemy mówić o sekretach. Zaletą jest prostota: zmieniasz jedno ustawienie i wszystkie spidery w projekcie przejmują nowe proxy. Koniec z przeszukiwaniem pięciu plików w poszukiwaniu martwego IP.

Krok 3: Zrozum kolejność wykonywania middleware, żeby proxy nie wyglądało na „nic nierobienie”

To właśnie ten fragment większość innych poradników zbywa krótkim „ustaw priorytet na 350 i zaufaj mi”. Downloader middleware w Scrapy działa w konkretnej, przewidywalnej kolejności, a jeśli jej nie rozumiesz, konfiguracja proxy będzie generowała błędy, które wyglądają zupełnie jak coś innego.

Hooki po stronie requestów (process_request) wykonują się w kolejności rosnącej — najniższy numer idzie pierwszy. Hooki po stronie odpowiedzi (process_response, process_exception) działają w kolejności malejącej — najwyższy numer pierwszy, cofając się w dół łańcucha.

Przepływ requestu (rosnąco):
  Spider → [100] RobotsTxt → [300] HttpAuth → [350] TWOJE PROXY MIDDLEWARE
         → [500] UserAgent → [550] Retry → [700] Cookies → [750] HttpProxy
         → Downloader

Przepływ odpowiedzi (malejąco):
  Downloader → [750] HttpProxy → [700] Cookies → [550] Retry
             → [500] UserAgent → [350] TWOJE PROXY MIDDLEWARE → [300] HttpAuth
             → [100] RobotsTxt → Spider

Oto aktualna tabela domyślnych priorytetów wbudowanych middleware Scrapy (zweryfikowana na 2.17.0):

MiddlewareDomyślny priorytet
RobotsTxtMiddleware100
HttpAuthMiddleware300
DownloadTimeoutMiddleware350
DefaultHeadersMiddleware400
UserAgentMiddleware500
RetryMiddleware550
RedirectMiddleware600
CookiesMiddleware700
HttpProxyMiddleware750
DownloaderStats850
HttpCacheMiddleware900

Gdy RetryMiddleware planuje ponowną próbę, kopiuje nieudany request — razem z jego metadanymi — a ten nowy request ponownie wchodzi do łańcucha downloader middleware. Relacja selektora do priorytetu 550 nie gwarantuje rotacji. Rotacja zachodzi tylko wtedy, gdy kod selektora rozpozna retry i celowo nadpisze skopiowane meta["proxy"]. Priorytet 350 to wygodne miejsce dla selektora, bo działa przed wbudowanym etapem transportu na 750, ale sam w sobie nie jest mechanizmem rotacji.

Ścieżki requestów i odpowiedzi Scrapy przez priorytety 350, 550 i 750, z retry 503 ponownie wchodzącym do łańcucha middleware

Typowe błędy w kolejności middleware

  • Ustawienie middleware na ten sam priorytet co HttpProxyMiddleware (750): tworzy to warunek wyścigu, w którym o kolejności przetwarzania decyduje Scrapy (a nie Twoja logika) przez kolejność w słowniku. Objaw: nieregularne, niewyjaśnione zachowanie proxy.
  • Używanie setdefault() albo if "proxy" not in request.meta w selektorze rotującym: skopiowany retry zachowuje stare proxy. Objaw: każda ponowna próba idzie tą samą, nieskuteczną trasą. Naprawa: wykryj retry (na przykład retry_times > 0) i jawnie podmień wartość proxy należącą do selektora.
  • Całkowite wyłączenie HttpProxyMiddleware: niektóre poradniki sugerują ustawienie "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": None, bo „custom middleware zrobi to samo”. Nie zrobi — Twoje middleware jest selektorem, nie warstwą transportową. Wyłączenie wbudowanego mechanizmu sprawia, że nagłówki autoryzacji proxy nigdy nie są dodawane, a requesty wychodzą bez uwierzytelnienia (albo w ogóle nie wychodzą).

Krok 4: Przestań wpisywać dane uwierzytelniające proxy na sztywno

Każdy poradnik o proxy dla Scrapy, który trafiał wysoko w wynikach, wpisywał http://username:password@proxy.example.com:8080 bezpośrednio do pliku Pythona. To poświadczenie, które zostaje w historii Git na zawsze, pojawia się w każdym klonie, każdym forku i w każdym log dumpie, jeśli ktoś bezmyślnie użyje print().

W praktyce są trzy poziomy takiego podejścia:

MetodaBezpieczeństwoElastycznośćNajlepsza do
Na sztywno w spider/settings.pySłabe — sekrety lądują w repozytoriumNiskaTylko szybkie testy lokalne
Zmienna środowiskowa http_proxy (natywnie w Scrapy)Lepsze — poza kodemNiska (jedno proxy)CI/CD, Docker
Plik .env + python-dotenv + from_crawlerNajlepsze — poza kodem, osobno dla każdego środowiskaWysoka (wiele proxy, rotacja)Scrapery produkcyjne

Trzecia opcja naprawdę warto zbudować porządnie. Zainstaluj python-dotenv, utwórz plik .env i od razu dodaj go do .gitignore — mówię serio, zrób to teraz:

PROXY_USER=myuser
PROXY_PASSWORD=my$ecret!Pass
PROXY_HOST=proxy.example.com
PROXY_PORT=8080

Załaduj to na początku settings.py:

from dotenv import load_dotenv
import os

load_dotenv()

PROXY_USER = os.getenv("PROXY_USER")
PROXY_PASSWORD = os.getenv("PROXY_PASSWORD")
PROXY_HOST = os.getenv("PROXY_HOST")
PROXY_PORT = os.getenv("PROXY_PORT")

Następnie odczytaj te dane bezpiecznie wewnątrz middleware, używając from_crawler — to właśnie ten wzorzec rozwiązuje zamieszanie, które często widuję na forach, gdzie ludzie pytają: „jak to ustawić przed scrapy crawl, jeśli dane logowania zmieniają się przy każdym uruchomieniu?”:

import os
from urllib.parse import quote

class SecureProxyMiddleware:
    def __init__(self, user, password, host, port):
        self.user = quote(user, safe="")
        self.password = quote(password, safe="")
        self.host = host
        self.port = port

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        return cls(
            user=settings.get("PROXY_USER"),
            password=settings.get("PROXY_PASSWORD"),
            host=settings.get("PROXY_HOST"),
            port=settings.get("PROXY_PORT"),
        )

    def process_request(self, request, spider):
        proxy_url = f"http://{self.user}:{self.password}@{self.host}:{self.port}"
        request.meta["proxy"] = proxy_url

Zwróć uwagę na urllib.parse.quote() zastosowane do danych logowania. Jeśli hasło zawiera @, : albo / (a generatory haseł uwielbiają takie znaki), URL zostanie źle zinterpretowany, chyba że wcześniej je zakodujesz procentowo. To jedno linijkowe zabezpieczenie oszczędza żenującej godziny debugowania błędów typu „invalid proxy URL”, które wcale nie wynikają z tego, że proxy jest wadliwe.

Trzymaj dane logowania poza logami i testuj kodowanie procentowe na reprezentatywnych — ale fikcyjnych — wartościach. Tunneling HTTPS, SOCKS5 i poświadczenia z niełacińskimi znakami mają ograniczenia zależne od handlera; nie zakładaj, że jeden schemat uwierzytelniania zadziała wszędzie bez przypiętego testu integracyjnego.

Bezpieczny przepływ od zablokowanego pliku środowiskowego przez zakodowane procentowo ustawienia proxy do metadanych requestu Scrapy

Krok 5: Dodaj rotację proxy

Jedno proxy — nawet dobre — wykonujące 5 000 requestów do tej samej strony w końcu zostanie oznaczone. Potrzebujesz puli.

Opcja A — zbuduj to samodzielnie. To naprawdę proste:

import random

class RotatingProxyMiddleware:
    def __init__(self, proxy_pool):
        self.proxy_pool = proxy_pool

    @classmethod
    def from_crawler(cls, crawler):
        return cls(proxy_pool=crawler.settings.getlist("PROXY_POOL"))

    def process_request(self, request, spider):
        request.meta["proxy"] = random.choice(self.proxy_pool)

To działa przy prostych zastosowaniach, ale nie wie nic o tym, które proxy faktycznie żyją. Przy każdym requestcie rzucasz kością.

Opcja B — użyj scrapy-rotating-proxies. Ten pakiet zewnętrzny dodaje wykrywanie banów i automatyczny backoff od razu po instalacji:

pip install scrapy-rotating-proxies

Powiem to uczciwie: najnowsza wersja na PyPI to 0.6.2 z 2019 roku, a projekt ma etykietę Alpha. Niekoniecznie oznacza to, że nie działa na nowym Scrapy, ale „nieutrzymywany aktywnie od 2019” to nie to samo co „przetestowany bojowo na ruchu produkcyjnym w 2026”. Przypnij wersję, przetestuj ją na realnych celach i nie zakładaj, że obsługuje autoryzowane endpointy proxy — w dużej mierze tego nie robi.

Krok 6: Zbuduj odporny na awarie proxy middleware (wykrywanie martwych proxy)

To jest sekcja, którą każdy konkurencyjny poradnik pomija całkowicie, a właśnie ona odróżnia demo od rozwiązania, które przetrwa 6-godzinny crawl bez nadzoru.

ScenariuszCo pokazuje większość poradnikówCo dodaje to middleware
Proxy zwraca 407Brak omówieniaTraktuje to jako błąd autoryzacji proxy
Cel zwraca 403/429Często wrzucane do jednego workaOddziela sygnały polityki/limitów od kondycji proxy
Proxy timeoutujeBrak omówieniaKonfigurowalny próg timeoutu, spadek score kondycji
Wszystkie proxy martweBrak omówieniaŁagodny fallback albo pauza crawl'a z ostrzeżeniem w logu
Proxy „flapping” (przerywane działanie)Brak omówieniaOkres schłodzenia przed ponownym dodaniem do puli
import time
import random
from scrapy.exceptions import IgnoreRequest

class FaultTolerantProxyMiddleware:
    MAX_FAILURES = 3
    COOLDOWN_SECONDS = 300

    def __init__(self, proxy_pool):
        self.pool = {p: {"failures": 0, "banned_until": 0} for p in proxy_pool}

    @classmethod
    def from_crawler(cls, crawler):
        return cls(proxy_pool=crawler.settings.getlist("PROXY_POOL"))

    def _healthy_proxies(self):
        now = time.time()
        return [p for p, s in self.pool.items() if s["banned_until"] < now]

    def process_request(self, request, spider):
        healthy = self._healthy_proxies()
        if not healthy:
            spider.logger.warning("Wszystkie proxy są niezdrowe — wstrzymuję crawl")
            raise IgnoreRequest("No healthy proxies available")
        request.meta["proxy"] = random.choice(healthy)

    def process_response(self, request, response, spider):
        proxy = request.meta.get("proxy")
        if proxy and response.status == 407:
            self._mark_failure(proxy)
        return response

    def process_exception(self, request, exception, spider):
        proxy = request.meta.get("proxy")
        if proxy:
            self._mark_failure(proxy)

    def _mark_failure(self, proxy):
        state = self.pool[proxy]
        state["failures"] += 1
        if state["failures"] >= self.MAX_FAILURES:
            state["banned_until"] = time.time() + self.COOLDOWN_SECONDS
            state["failures"] = 0

Kilka uwag z praktyki: nie traktuj każdego 403 jako dowodu, że proxy jest martwe — RFC 9110 definiuje 403 jako „serwer zrozumiał, ale odmawia”, co równie dobrze może oznaczać, że podejrzane są nagłówki albo sesja, a nie samo proxy. Z kolei 407 oznacza, że to samo proxy odrzuca autoryzację — to silniejszy i bardziej konkretny sygnał. Mieszanie tych sygnałów w jeden koszyk sprawia, że ludzie spalają zdrowe proxy bez powodu.

W produkcji warto jawnie ustawić tymczasowe retry w Scrapy, żeby recenzenci widzieli politykę:

RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429]
RETRY_TIMES = 2

To są domyślne wartości Scrapy 2.17. Nie dodawaj masowo 403 ani 407: 403 to odmowa po stronie celu z wielu możliwych powodów, a 407 to problem z autoryzacją proxy, którego zwykłe ponawianie requestu nie naprawi. Jeśli konkretny kontrakt celu uzasadnia retry dla innego kodu, udokumentuj ten powód i przetestuj go osobno.

Wyraźne rozróżnienie między błędem autoryzacji 407, limitem 429, retry 503, sukcesem 200 i zamkniętą bramą, gdy proxy są niedostępne

Krok 7: Mierzony wzorzec proxy przy retry

Niektóre autoryzowane cele mogą zwracać poprawną treść bezpośrednio i potrzebować proxy dopiero po udokumentowanej, przejściowej odpowiedzi. Może to zmniejszyć liczbę bajtów przesyłanych przez proxy, ale nie istnieje obronny, uniwersalny procent oszczędności ani przenośny współczynnik sukcesu bezpośrednich requestów. Zmierz własne obciążenie, zanim przyjmiesz ten wzorzec.

Użyj publicznego helpera Scrapy get_retry_request() i ogranicz eskalację wyłącznie do specyficznych dla celu statusów, które zostały przez Ciebie jawnie sklasyfikowane. Ten przykład traktuje 429 i 503 jako sygnały przeciążenia kwalifikujące do retry; celowo wyklucza 403 i 407.

from scrapy.downloadermiddlewares.retry import get_retry_request

class CostAwareEscalationMiddleware:
    def process_response(self, request, response, spider):
        if response.status not in {429, 503}:
            return response

        retry = get_retry_request(
            request,
            spider=spider,
            reason=f"proxy_escalation_{response.status}",
            max_retry_times=2,
        )
        if retry is None:
            return response

        current_tier = request.meta.get("proxy_tier", "direct")
        if current_tier == "direct":
            retry.meta["proxy"] = spider.settings["DATACENTER_PROXY"]
            retry.meta["proxy_tier"] = "datacenter"
        elif current_tier == "datacenter":
            retry.meta["proxy"] = spider.settings["RESIDENTIAL_PROXY"]
            retry.meta["proxy_tier"] = "residential"
        else:
            return response
        return retry

Loguj współczynnik poprawnej treści przy direct, współczynnik poprawnej treści przez proxy, liczbę bajtów na rekord zakończony sukcesem, liczbę retry na sukces i dodatkowe opóźnienie. Architektura direct-first jest akceptowalna tylko wtedy, gdy direct access jest autoryzowany, a system przechodzi w tryb fail-closed zawsze, gdy proxy jest wymagane. Oszczędność to zmierzona redukcja ruchu przez proxy — nie założony procent.

Kiedy samodzielne zarządzanie proxy nie ma sensu

Chcę powiedzieć to wprost, zamiast udawać, że cała reszta artykułu była bez sensu: wszystko powyżej to prawdziwa, użyteczna inżynieria i w wielu projektach — crawlach o dużym wolumenie, niestandardowych pipeline’ach, wszędzie tam, gdzie potrzebujesz pełnej kontroli nad harmonogramem requestów — jest to właściwy wybór.

Ale jeśli Twoim realnym celem jest „pobierz ustrukturyzowane dane z tej strony”, a nie „utrzymuj infrastrukturę proxy”, API ekstrakcyjne może być lepszą granicą odpowiedzialności. Aktualna dokumentacja Thunderbit dla POST /extract przyjmuje URL strony i opcjonalny JSON Schema; gdy schemat jest pominięty, usługa może wygenerować go na podstawie treści strony. Endpoint udostępnia też tryby renderowania none, basic i full, a także kontrolę timeoutu i czasu oczekiwania po załadowaniu strony. Ekstrakcja wyłącznie na podstawie promptu nie jest częścią aktualnie wspieranego zakresu requestu, więc integracje produkcyjne buduj wokół udokumentowanego kontraktu schematu. To przenosi interfejs ekstrakcji za jeden request; nie uzasadnia jednak uniwersalnej obietnicy skuteczności wobec każdego anty-botowego mechanizmu czy CAPTCHA.

CzynnikDIY Scrapy + proxyEkstrakcja oparta o API (np. Thunderbit)
Nakład startowyWysoki — middleware, rotacja, logika retryNiski — jedno wywołanie API ze schematem
Zachowanie sieci/renderowaniaKonfigurujesz handlery, proxy, nagłówki i opóźnieniaSterowane przez udokumentowane opcje API
UtrzymanieOdpowiadasz za selektory, kondycję puli i zmiany celuOdpowiadasz za jakość schematu, walidację i integrację
Model kosztówOpłaty za proxy + compute + czas inżynierówAktualna dokumentacja podaje 20 jednostek na stronę (sprawdzone 2026-08-10)
KontrolaPełna — własne pipeline’y, łańcuch middlewareOgraniczona do możliwości API
Najlepsze dlaZłożone crawl'e, duży wolumen, własna logikaUkierunkowana ekstrakcja, prototypowanie, enrichment

Jeśli głównie wyciągasz ustrukturyzowane strony do list leadów, danych produktowych albo researchu, uruchom reprezentatywny pilot z Thunderbit Chrome Extension albo API i porównaj liczbę poprawnych rekordów, opóźnienie, jednostki oraz czas utrzymania. Jeśli Twój projekt wymaga własnych grafów crawl'i i kontroli pipeline’u, Scrapy pozostaje lepszym wyborem.

Dowiedz się więcej

Wskazówki i częste pułapki

  • Wskazówka: Przetestuj proxy na httpbin.org/ip, zanim podłączysz je do prawdziwego celu. To najszybszy sposób, żeby sprawdzić, czy routing działa, zanim dołożysz kolejne warstwy złożoności.
  • Pułapka: Ustawianie proxy w request.headers zamiast w request.meta. To naprawdę częsty, niemal literówkowy błąd — HttpProxyMiddleware odczytuje tylko meta["proxy"], a próba oparta na nagłówkach zakończy się cicho, bez oczywistego błędu.
  • Pułapka: Zakładanie, że proxy HTTP i HTTPS konfiguruje się identycznie. Routing przez HTTP proxy do celu HTTPS zwykle działa przez tunel CONNECT przy kompatybilnym handlerze, ale użycie schematu https:// dla samego endpointu proxy to zupełnie inna, słabiej wspierana konfiguracja — nie myl tych dwóch rzeczy.
  • Wskazówka: Jeśli potrzebujesz wsparcia dla SOCKS5, najpierw sprawdź możliwości download handlera w swojej wersji Scrapy. Eksperymentalny Httpx handler w Scrapy 2.17 dodał obsługę SOCKS5 przez httpx[socks], ale nadal jest oznaczony jako eksperymentalny — nie opieraj na nim produkcji bez własnych testów.

Metody alternatywne

Poza scrapy-rotating-proxies niektóre zespoły kierują całą logikę proxy przez gateway dostawcy — pojedynczy URL proxy, za którym dostawca sam obsługuje rotację, sticky session i targetowanie geograficzne. To oddaje część kontroli w zamian za znacznie mniej kodu middleware, i warto wycenić to rozwiązanie względem własnej puli, zanim zaczniesz budować wszystko od zera.

Podsumowanie

Ustawienie proxy w Scrapy wymaga jednej linii. Sprawienie, by taka konfiguracja przetrwała prawdziwy produkcyjny crawl, wymaga jawnej polityki błędów, zabezpieczonych danych uwierzytelniających, przetestowanych granic handlerów oraz kodu selektora, który świadomie podmienia skopiowane metadane proxy przy retry. Jeśli masz wynieść z tego dwie nawyki, niech będą to: fail closed, gdy proxy jest wymagane, oraz nigdy nie commituj hasła do proxy do pliku Pythona.

FAQ

Jak skonfigurować własny proxy w Scrapy z uwierzytelnianiem? Użyj formatu URL protocol://username:password@host:port, ale najpierw zakoduj username i password przy pomocy urllib.parse.quote(), jeśli zawierają znaki specjalne. W produkcji czytaj te dane przez metodę klasową from_crawler, pobierając je ze zmiennych środowiskowych zamiast wpisywać je na sztywno.

Jakiego numeru priorytetu użyć dla własnego proxy middleware w Scrapy? 350 to częsty wybór dla selektora, ponieważ działa przed HttpProxyMiddleware na 750. Nie gwarantuje to rotacji. Retry dostaje nowe proxy tylko wtedy, gdy selektor rozpozna skopiowany request retry i nadpisze jego wcześniejszą wartość meta["proxy"].

Jak automatycznie obsługiwać martwe proxy w Scrapy? Zbuduj middleware, które śledzi liczbę błędów per proxy w process_response i process_exception, usuwa proxy z aktywnej puli po przekroczeniu progu błędów i dodaje je ponownie po okresie schłodzenia, zamiast blokować je na stałe.

Czy mogę używać Scrapy z proxy SOCKS5? Eksperymentalny HttpxDownloadHandler w Scrapy 2.17 dokumentuje wsparcie dla SOCKS5, jeśli zainstalowano httpx[socks]. Domyślny handler HTTP/1.1 nie obsługuje proxy SOCKS. Zablokuj wersję handlera i zrób test integracyjny, zanim uznasz tę ścieżkę za gotową do produkcji.

Ile naprawdę można zaoszczędzić na kosztach proxy dzięki wzorcowi proxy-on-retry? Nie istnieje uniwersalny procent. Zmierz udział autoryzowanych requestów, które zwracają poprawną treść bezpośrednio, liczbę bajtów przesyłanych przez każdą warstwę proxy, liczbę retry na każdy rekord zakończony sukcesem i dodatkowe opóźnienie. Zaoszczędzona kwota to obserwowana redukcja ruchu przez proxy — jeśli direct-first nie jest autoryzowane albo nie działa poprawnie, nie stosuj tego wzorca.

Ke
Ke
CTO w Thunderbit | Starszy data scientist i ekspert ML Dzięki prawie dziesięciu latom doświadczenia w uczeniu maszynowym i data science, Ke Shen jest absolwentem Columbia University i byłym starszym data scientistą w Walmart Labs. Dysponując dogłębną, uznaną przez branżowych ekspertów wiedzą w zakresie Python, R, Java i statystyki, dzieli się sprawdzonymi w boju spostrzeżeniami na temat wdrażania złożonych algorytmów AI — od teorii po architekturę gotową do produkcji.
Topics
middleware proxy w Scrapyweb scraping w Pythonierotacja proxy
Spis treści
Thunderbit · Agent AI do danych z sieci

Wyodrębnij dane z dowolnej strony w 1 klik

Zaufało nam ponad 250 000 użytkowników
dostępny darmowy plan
Od strony WWW do arkusza
Opisz, czego potrzebujesz — agent AI Thunderbit to zeskrapuje i wyeksportuje do Excel, Google Sheets, Airtable lub Notion. Start jest darmowy.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week