Rotacja proxy w Crawlee dla Pythona — przewodnik dla programistów

Kompletny przewodnik po zarządzaniu proxy w frameworku Crawlee dla Pythona: ProxyConfiguration, SessionPool, rotacja IP, proxy residential i wzorce produkcyjne z ProxyHat.

Proxy Rotation in Crawlee for Python: A Developer's Guide to Residential Proxies
W tym artykule

Uwaga prawna: Scraping danych publicznych podlega regulacjom takim jak Computer Fraud and Abuse Act (CFAA) w USA oraz RODO/GDPR w Unii Europejskiej. Zbieraj wyłącznie dane publiczne, honoruj pliki robots.txt, limity częstotliwości oraz regulaminy serwisów (ToS), a tam gdzie to możliwe — preferuj oficjalne API. Ten artykuł ma charakter edukacyjny i nie stanowi porady prawnej.

Rotacja proxy w Crawlee dla Pythona to kluczowa umiejętność dla każdego programisty budującego produkcyjne crawlery. Crawlee — framework stworzony przez zespół Apify — oferuje wbudowane mechanizmy zarządzania sesjami i proxy, które znacznie przewyższają ręczne rozwiązania typu „lista proxy w pętli”. W tym przewodniku pokażemy, jak idiomatycznie zintegrować crawlee python proxy z infrastrukturą ProxyHat, wykorzystując klasę ProxyConfiguration, SessionPool oraz wzorce produkcyjne takie jak session.retire().

Architektura Crawlee: Request Queue, Autoscaling i SessionPool

Crawlee dla Pythona dzieli rdzeń architektoniczny z odpowiednikiem w TypeScript. Trzy komponenty są kluczowe dla zrozumienia proxy rotation:

  • Request Queue — centralna, deduplikująca kolejka żądań, współdzielona przez wszystkie crawlery (BeautifulSoupCrawler, PlaywrightCrawler). Żądania można dodawać dynamicznie z poziomu request_handler.
  • Autoscaled Pool — pula workerów, która automatycznie dostosowuje współbieżność na podstawie wydajności i limitów. Domyślnie startuje ostrożnie i zwiększa liczbę jednoczesnych żądań, gdy system radzi sobie bez błędów.
  • SessionPool — zarządza sesjami HTTP, z których każda może mieć powiązany adres IP, ciasteczka i odcisk palca przeglądarki. To właśnie tutaj proxy rotation spotyka się z zarządzaniem stanem.

SessionPool to fundament idiomatycznej rotacji proxy. Zamiast traktować proxy jako listę URL-i do losowego wybierania, Crawlee wiąże każdy adres IP z sesją, która przechowuje ciasteczka i nagłówki. Dzięki temu kolejne żądania w tej samej sesji trafiają na ten sam adres IP — co jest kluczowe dla stron wymagających logowania lub utrzymania koszyka.

Więcej o architekturze Crawlee można przeczytać w oficjalnej dokumentacji Crawlee.

ProxyConfiguration: idiomatyczna rotacja proxy w Crawlee

Klasa ProxyConfiguration jest idiomatycznym sposobem konfiguracji proxy w Crawlee. Zamiast ręcznie przekazywać URL proxy do każdego żądania, definiujesz konfigurację raz, a Crawlee automatycznie aplikuje ją do wszystkich sesji i crawlerów.

Dwa główne wzorce rotacji to:

  • Round-robin — każde żądanie otrzymuje nowy adres IP. Odpowiednie dla prostego scrapingu SERP lub monitoringu cen, gdzie nie potrzebujesz utrzymania stanu.
  • Session-bound (sticky) — adres IP jest przypisany do sesji na cały jej cykl życia. Użyj proxy_configuration.new_url(session_id=...), aby przypiąć residential IP do konkretnej sesji.

Oto jak wygląda podstawowa konfiguracja crawlee proxyconfiguration z ProxyHat:

from crawlee.proxy_configuration import ProxyConfiguration

# Round-robin: Crawlee wywoła new_url() bez session_id
proxy_config = ProxyConfiguration(
    proxy_urls=[
        'http://user-country-US:PASSWORD@gate.proxyhat.com:8080',
        'http://user-country-DE:PASSWORD@gate.proxyhat.com:8080',
        'http://user-country-GB:PASSWORD@gate.proxyhat.com:8080',
    ]
)

Dla sesji przypiętej do konkretnego IP (sticky session), używamy flagi session w nazwie użytkownika ProxyHat:

from crawlee.proxy_configuration import ProxyConfiguration
import uuid

def make_proxy_url(session_id: str, country: str = 'US') -> str:
    username = f'user-country-{country}-session-{session_id}'
    return f'http://{username}:PASSWORD@gate.proxyhat.com:8080'

# ProxyConfiguration z generatorem URL-i per sesja
proxy_config = ProxyConfiguration(
    new_url_function=lambda session_id=None: make_proxy_url(
        session_id or str(uuid.uuid4())
    )
)

W tym wzorcu crawlee proxy rotation odbywa się automatycznie — Crawlee wywołuje new_url(session_id=...) dla każdej nowej sesji w SessionPool, a ProxyHat utrzymuje ten sam residential IP tak długo, jak sesja jest aktywna.

Dlaczego residential proxy biją datacenter na Cloudflare i DataDome

Systemy ochrony typu Cloudflare Bot Management i DataDome klasyfikują ruch na podstawie reputacji adresu IP. Adresy z puli datacenter (AWS, DigitalOcean, OVH) są natychmiast oznaczane jako podejrzane, ponieważ nie pochodzą od dostawców internetu (ISP). Residential proxy korzystają z adresów IP przydzielonych przez prawdziwych ISP zwykłym gospodarstwom domowym — co sprawia, że dla systemu antybotowego wyglądają jak organiczny ruch.

Według raportu Cloudflare Radar, ponad 30% ruchu internetowego jest filtrowane jako automatyczne, a systemy bot management coraz częściej stosują analizę reputacji IP w czasie rzeczywistym. Adresy datacenter mają wskaźnik blokady często przekraczający 50% na chronionych celach, podczas gdy residential proxy mogą utrzymywać wskaźnik sukcesu powyżej 90% przy odpowiedniej rotacji.

Strategia proxy warstwowych (tiered proxies) polega na hierarchii:

  1. Zacznij od residential proxy dla pierwszej warstwy żądań.
  2. Jeśli sesja otrzyma blokadę (status 403, challenge CAPTCHA), wycofaj ją (session.retire()).
  3. Utwórz nową sesję z nowym residential IP.
  4. Rezerwuj mobile proxy dla najtrudniejszych celów — mają najwyższą reputację IP, ale są najdroższe.
Cecha Datacenter Proxy Residential Proxy Mobile Proxy
Reputacja IP Niska — oznaczane jako hosting Wysoka — prawdziwy ISP Bardzo wysoka — sieć komórkowa
Wskaźnik blokad (Cloudflare/Datadome) 40–60% 5–15% <5%
Latencja ~50–100ms ~200–500ms ~300–800ms
Koszt Niski (~$1/GB) Średni (~$5–15/GB) Wysoki (~$20–50/GB)
Idiomy Crawlee Round-robin Session-bound rotation Session-bound, długie sesje

Sprawdź dostępne lokalizacje ProxyHat na stronie /pl/locations, aby dobrać geo-targetowanie do swojego przypadku użycia.

Przykład: BeautifulSoupCrawler z ProxyConfiguration i ProxyHat

Poniżej znajduje się kompletny, uruchamialny przykład crawlee session pool z proxy residential. Crawler pobiera strony e-commerce, używając sesji przypiętych do residential IP w USA.

import asyncio
import uuid
from crawlee.beautifulsoup_crawler import BeautifulSoupCrawler
from crawlee.proxy_configuration import ProxyConfiguration
from crawlee.sessions import SessionPool

PROXYHAT_USER = 'user'
PROXYHAT_PASS = 'PASSWORD'

def make_proxy_url(session_id: str, country: str = 'US') -> str:
    """Generuje URL proxy ProxyHat dla danej sesji i kraju."""
    username = f'{PROXYHAT_USER}-country-{country}-session-{session_id}'
    return f'http://{username}:{PROXYHAT_PASS}@gate.proxyhat.com:8080'

async def main():
    # ProxyConfiguration z funkcją generującą URL per sesja
    proxy_config = ProxyConfiguration(
        new_url_function=lambda session_id=None: make_proxy_url(
            session_id or str(uuid.uuid4())[:8]
        )
    )

    crawler = BeautifulSoupCrawler(
        proxy_configuration=proxy_config,
        max_request_retries=3,
        request_handler_timeout=60,
        max_requests_per_crawl=500,
        # Autoscaling: Crawlee sam dostosuje współbieżność
        min_concurrency=2,
        max_concurrency=10,
    )

    @crawler.router.default_handler
    async def handler(request, session, request_handler_data):
        response = await request_handler_data.http_client.send_request(
            str(request.url)
        )

        # Wykrywanie blokad
        if response.status_code == 403:
            session.retire()
            raise RuntimeError(f'Zablokowano na {request.url} — wycofuję sesję')

        # Parsowanie danych
        soup = request_handler_data.soup
        title = soup.find('h1')
        price = soup.find('span', class_='price')

        await request_handler_data.push_data({
            'url': str(request.url),
            'title': title.text.strip() if title else None,
            'price': price.text.strip() if price else None,
            'session_id': session.id,
        })

        # Dodawanie kolejnych linków
        for link in soup.select('a.product-link'):
            await request_handler_data.enqueue_links(
                selector='a.product-link',
                label='PRODUCT'
            )

    await crawler.run(['https://example-store.com/products'])

if __name__ == '__main__':
    asyncio.run(main())

Kluczowe elementy tego przykładu:

  • ProxyConfiguration z new_url_function generuje unikalny URL proxy dla każdej sesji, używając flagi -session-{id} w nazwie użytkownika ProxyHat.
  • session.retire() wycofuje sesję po blokadzie — Crawlee automatycznie tworzy nową sesję z nowym IP.
  • max_request_retries=3 zapewnia, że zablokowane żądanie zostanie ponowione z nową sesją.
  • Autoscaling (min_concurrency, max_concurrency) kontroluje przepustowość — Crawlee zwiększa współbieżność, gdy wskaźnik sukcesu jest wysoki.

Wzorce produkcyjne: session.retire(), retry i error handling

Wycofywanie sesji po blokadzie

Najważniejszy wzorzec produkcyjny to session.retire(). Kiedy wykryjesz blokadę — status 403, 429, redirect do strony CAPTCHA, lub nieoczekiwany HTML z challenge — wycofujesz sesję. Crawlee automatycznie utworzy nową sesję z nowym proxy URL.

@crawler.router.default_handler
async def handler(request, session, request_handler_data):
    response = await request_handler_data.http_client.send_request(
        str(request.url)
    )

    # Wzorce detekcji blokad
    blocked_signals = [
        response.status_code == 403,
        response.status_code == 429,
        'cf-challenge' in response.headers.get('server', ''),
        'captcha' in response.text.lower()[:2000],
    ]

    if any(blocked_signals):
        session.retire()
        # Rzucenie wyjątku powoduje retry z nową sesją
        raise RuntimeError(f'Zablokowano: {response.status_code} na {request.url}')

    # Normalna obsługa...

Tiered proxy fallback

Dla najtrudniejszych celów warto zaimplementować fallback: zacznij od residential, a po N blokadach przełącz się na mobile proxy. Możesz to osiągnąć, nadpisując new_url_function na podstawie licznika blokad sesji:

block_counter = {'count': 0}

def tiered_proxy_url(session_id=None):
    if block_counter['count'] > 5:
        # Przełącz na mobile proxy
        username = f'{PROXYHAT_USER}-country-US-session-{session_id}-mobile'
    else:
        username = f'{PROXYHAT_USER}-country-US-session-{session_id}'
    return f'http://{username}:{PROXYHAT_PASS}@gate.proxyhat.com:8080'

Zarządzanie współbieżnością

Autoscaled Pool w Crawlee automatycznie dostosowuje współbieżność, ale warto ustawić limity. Dla residential proxy rozsądna konfiguracja to max_concurrency=10–20 — zbyt agresywne współbieżne żądania z tej samej puli IP mogą wywołać blokady. Pełną dokumentację parametrów znajdziesz na docs.proxyhat.com.

Kiedy NIE używać PlaywrightCrawler

PlaywrightCrawler uruchamia pełną przeglądarkę headless — jest 10–50x wolniejszy i zużywa znacznie więcej zasobów niż BeautifulSoupCrawler. Używaj go tylko gdy:

  • Strona renderuje treść w JavaScript (SPA, React, Vue).
  • Musisz wykonać interakcje (kliknięcia, scrollowanie, wypełnianie formularzy).
  • System antybotowy wymaga pełnego odcisku palca przeglądarki (Canvas, WebGL, WebRTC).

W pozostałych przypadkach — statyczne HTML, API endpoints, JSON — BeautifulSoupCrawler z proxy residential jest znacznie wydajniejszy i tańszy. Monitorowanie cen SERP najlepiej realizować przez HTTP-only crawling. Zobacz nasze przypadki użycia na /pl/use-cases/serp-tracking.

Etyka i zgodność z prawem

Web scraping jest legalny dla danych publicznych, ale podlega ograniczeniom:

  • CFAA (USA) — Computer Fraud and Abuse Act zabrania „nieautoryzowanego dostępu” do systemów komputerowych. Scraping za zaporami logowania lub z naruszeniem ToS może naruszać CFAA.
  • GDPR/RODO (UE) — dane osobowe podlegają ochronie. Scraping danych osobowych (nazwiska, e-maile, adresy) wymaga podstawy prawnej.
  • robots.txt — choć nie jest prawnie wiążący, jego ignorowanie może być argumentem przeciwko Tobie w sporze.
  • Limity częstotliwości — agresywny scraping może zakłócać działanie serwisu i naruszać ToS.

Zawsze preferuj oficjalne API, gdy są dostępne. Więcej o przypadkach użycia scraping znajdziesz na /pl/use-cases/web-scraping, a cennik proxy residential na /pl/pricing.

Kluczowe wnioski: Rotacja proxy w Crawlee dla Pythona jest idiomatycznie realizowana przez ProxyConfiguration z new_url_function, który generuje URL proxy per sesja. SessionPool wiąże IP z ciasteczkami i nagłówkami. Residential proxy z ProxyHat (gate.proxyhat.com:8080) oferują wskaźnik sukcesu >90% na celach chronionych przez Cloudflare. session.retire() jest kluczowym wzorcem obsługi blokad. BeautifulSoupCrawler jest wystarczający dla większości zadań — PlaywrightCrawler używaj tylko dla JS-heavy stron.

Często zadawane pytania

Czym jest rotacja proxy w Crawlee dla Pythona?

Rotacja proxy w Crawlee dla Pythona to mechanizm zarządzania adresami IP poprzez klasę ProxyConfiguration i SessionPool. Crawlee automatycznie przypisuje proxy do sesji, utrzymując ten sam IP dla sticky sessions lub rotując IP per żądanie w trybie round-robin. Konfiguracja odbywa się raz na poziomie crawlera, a Crawlee aplikuje ją do wszystkich żądań.

Dlaczego rotacja proxy w Crawlee dla Pythona ma znaczenie dla użytkowników proxy?

Bez rotacji proxy pojedynczy adres IP zostanie szybko zablokowany przez systemy antybotowe. Crawlee integruje rotację z SessionPool, co oznacza, że ciasteczka i nagłówki są spójne z adresem IP — to zapobiega anomaliom, które systemy ochrony wykrywają jako boty. Residential proxy z rotacją sesyjną utrzymują wskaźnik sukcesu powyżej 90% na chronionych celach.

Który typ proxy najlepiej działa z rotacją w Crawlee dla Pythona?

Residential proxy są optymalne dla większości przypadków użycia w Crawlee — oferują wysoką reputację IP (prawdziwy ISP), wskaźnik blokad 5–15% na Cloudflare/DataDome i rozsądną latencję 200–500ms. Mobile proxy mają najwyższą reputację, ale są droższe ($20–50/GB). Datacenter proxy są najtańsze, ale na chronionych celach wskaźnik blokad sięga 40–60%.

Jak unikać blokad implementując rotację proxy w Crawlee dla Pythona?

Kluczowe wzorce: (1) używaj session.retire() po wykryciu blokady (403, 429, CAPTCHA); (2) ustaw max_request_retries=3, aby Crawlee ponowił żądanie z nową sesją; (3) ogranicz współbieżność do 10–20 dla residential proxy; (4) implementuj tiered fallback — residential → mobile; (5) używaj geo-targetowania dopasowanego do celu (np. -country-US dla amerykańskich serwisów).

Czy Crawlee dla Pythona obsługuje SOCKS5 proxy?

Tak, Crawlee obsługuje SOCKS5 przez ProxyConfiguration. Wystarczy użyć formatu socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080 w proxy_urls lub new_url_function. SOCKS5 jest przydatny, gdy HTTP proxy jest blokowane przez sieć docelową lub gdy potrzebujesz tunelowania UDP.

Często zadawane pytania

Czym jest rotacja proxy w Crawlee dla Pythona?

Rotacja proxy w Crawlee dla Pythona to mechanizm zarządzania adresami IP poprzez klasę ProxyConfiguration i SessionPool. Crawlee automatycznie przypisuje proxy do sesji, utrzymując ten sam IP dla sticky sessions lub rotując IP per żądanie w trybie round-robin. Konfiguracja odbywa się raz na poziomie crawlera, a Crawlee aplikuje ją do wszystkich żądań.

Dlaczego rotacja proxy w Crawlee dla Pythona ma znaczenie dla użytkowników proxy?

Bez rotacji proxy pojedynczy adres IP zostanie szybko zablokowany przez systemy antybotowe. Crawlee integruje rotację z SessionPool, co oznacza, że ciasteczka i nagłówki są spójne z adresem IP — to zapobiega anomaliom, które systemy ochrony wykrywają jako boty. Residential proxy z rotacją sesyjną utrzymują wskaźnik sukcesu powyżej 90% na chronionych celach.

Który typ proxy najlepiej działa z rotacją w Crawlee dla Pythona?

Residential proxy są optymalne dla większości przypadków użycia w Crawlee — oferują wysoką reputację IP (prawdziwy ISP), wskaźnik blokad 5–15% na Cloudflare/DataDome i rozsądną latencję 200–500ms. Mobile proxy mają najwyższą reputację, ale są droższe ($20–50/GB). Datacenter proxy są najtańsze, ale na chronionych celach wskaźnik blokad sięga 40–60%.

Jak unikać blokad implementując rotację proxy w Crawlee dla Pythona?

Kluczowe wzorce: (1) używaj session.retire() po wykryciu blokady (403, 429, CAPTCHA); (2) ustaw max_request_retries=3, aby Crawlee ponowił żądanie z nową sesją; (3) ogranicz współbieżność do 10–20 dla residential proxy; (4) implementuj tiered fallback — residential → mobile; (5) używaj geo-targetowania dopasowanego do celu (np. -country-US dla amerykańskich serwisów).

Czy Crawlee dla Pythona obsługuje SOCKS5 proxy?

Tak, Crawlee obsługuje SOCKS5 przez ProxyConfiguration. Wystarczy użyć formatu socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080 w proxy_urls lub new_url_function. SOCKS5 jest przydatny, gdy HTTP proxy jest blokowane przez sieć docelową lub gdy potrzebujesz tunelowania UDP.

Sprawdź konfigurację proxy w kilka sekund

Darmowy tester proxy — potwierdź, że Twoje IP są szybkie, anonimowe i nieblokowane.

Sprawdź proxy za darmo
← Powrót do Bloga