DrissionPage — jedno narzędzie do HTTP i przeglądarki
DrissionPage to framework Python, który rozwiązuje jeden z najstarszych dylematów web scrapingu: używać requests czy Selenium? Zamiast instalować dwóch bibliotek, zarządzać dwoma zestawami zależności i ręcznie synchronizować ciasteczka między sesją HTTP a sterowaną przeglądarką, DrissionPage oferuje jedno API z trzema trybami pracy. SessionPage obsługuje szybkie żądania HTTP w stylu requests, ChromiumPage steruje przeglądarką przez Chrome DevTools Protocol (CDP), a WebPage łączy oba tryby — przełączając się w locie przy zachowaniu wspólnego stanu.
Dla scraperów Python to zmniejsza koszty i złożoność. Zamiast zawsze uruchamiać headless Chromium (co zużywa ~200–500 MB RAM na instancję), możesz wykonać 90% żądań lekkim HTTP i eskalować do przeglądarki tylko tam, gdzie strona wymaga renderowania JavaScript. Z proxy do web scrapingu od ProxyHat zyskujesz dodatkowo rotację IP bez zmiany kodu.
Uwaga prawna: Ten przewodnik dotyczy wyłącznie pobierania publicznie dostępnych danych. Przestrzegaj robots.txt, warunków serwisu (ToS) oraz regulaminów — w USA nieautoryzowany dostęp może naruszać CFAA, a w UE przetwarzanie danych osobowych podlega RODO (GDPR). Preferuj oficjalne API, gdy są dostępne.
Model DrissionPage: SessionPage, ChromiumPage i WebPage
DrissionPage definiuje trzy klasy stron, które współdzielą bazowe interfejsy. Wybór odpowiedniej klasy determinuje backend, zużycie zasobów i możliwości renderowania:
| Cecha | SessionPage | ChromiumPage | WebPage |
|---|---|---|---|
| Backend | requests / urllib3 | Chrome DevTools Protocol | Oba, przełączane dynamicznie |
| Pamięć RAM (typowo) | ~20–40 MB | ~200–500 MB | Zależy od aktywnego trybu |
| Renderowanie JS | Nie | Tak | Tak (w trybie Chromium) |
| Prędkość żądania | ~50–200 ms | ~1–3 s (z renderowaniem) | Zależy od trybu |
| Współdzielony stan | Ciasteczka sesji | Ciasteczka przeglądarki | Automatyczna synchronizacja |
WebPage to kluczowa innowacja. Rozpoczynasz w trybie HTTP (szybko, tanio), a gdy trafisz na stronę wymagającą JavaScript, wywołujesz page.change_mode() — ciasteczka i nagłówki są automatycznie kopiowane do nowej sesji Chromium. Nie musisz ręcznie eksportować ani importować stanu.
Idiomatyczne API DrissionPage — ele(), eles() i nasłuchiwanie XHR
DrissionPage używa ujednoliconego API lokalizacji elementów, które działa identycznie w SessionPage i ChromiumPage. Funkcja ele() zwraca pierwszy pasujący element, a eles() — listę wszystkich dopasowań.
Lokatory ele() i eles()
Składnia lokalizatorów w DrissionPage jest bardziej zwięzła niż XPath w Selenium. Oto najważniejsze wzorce:
from DrissionPage import WebPage
page = WebPage()
# Selektor CSS z atrybutem
link = page.ele('@class=product-title')
# Selektor tagu z atrybutem
input_field = page.ele('tag:input@type=email')
# XPath, gdy potrzebujesz pełnej mocy
items = page.eles('xpath://div[@class="item"]/a')
# Tekst elementu
title = page.ele('tag:h1').text
# Wiele elementów
prices = page.eles('@class=price')Notacja @class=... to skrót DrissionPage dla selektora atrybutu — odpowiednik [class="..."] w CSS. Prefix tag: ogranicza wyszukiwanie do konkretnego tagu HTML. Możesz też używać pełnego XPath z prefixem xpath:, gdy logika wyszukiwania jest złożona.
ChromiumOptions — konfiguracja przeglądarki
Obiekt ChromiumOptions kontroluje parametry uruchamiania Chromium: ścieżkę do binarki, argumenty wiersza poleceń, rozszerzenia, proxy i więcej.
from DrissionPage import ChromiumOptions
co = ChromiumOptions()
co.headless()
co.set_argument('--disable-gpu')
co.set_argument('--window-size=1920,1080')
co.set_argument('--no-sandbox')
co.set_user_agent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...')Nasłuchiwanie XHR i JSON — listen.start()
Jedną z najpotężniejszych funkcji DrissionPage jest listen — wbudowany przechwytywacz ruchu sieciowego. Zamiast parsować HTML, możesz nasłuchiwać żądań XHR/Fetch, które strona wykonuje w tle, i wyciągać dane bezpośrednio z odpowiedzi JSON.
from DrissionPage import ChromiumPage
page = ChromiumPage()
page.listen.start('api/products') # filtruj URL zawierający ten fragment
page.get('https://example.com/shop')
packet = page.listen.wait(timeout=10)
if packet:
print(packet.response.body) # surowy JSON z APITo podejście często eliminuje potrzebę parsowania DOM w ogóle — strukturalne dane API są czystsze i stabilniejsze niż HTML. Zobacz też nasz przewodnik śledzenia SERP, gdzie przechwytywanie XHR jest kluczowe.
Konfiguracja proxy w DrissionPage
DrissionPage obsługuje proxy w obu trybach, ale konfiguracja różni się między SessionPage a ChromiumPage. Oto jak zintegrować proxy z ProxyHat.
SessionPage — set_proxies()
Dla trybu HTTP wystarczy przekazać URL proxy do metody set_proxies():
from DrissionPage import SessionPage
page = SessionPage()
page.set_proxies('http://user-country-US:pass@gate.proxyhat.com:8080')
page.get('https://httpbin.org/ip')
print(page.response.json()) # {"origin": "IP proxy"}ChromiumPage — ChromiumOptions.set_proxy()
Dla trybu przeglądarki proxy ustawia się w ChromiumOptions, ponieważ Chromium musi znać proxy przed uruchomieniem procesu:
from DrissionPage import ChromiumPage, ChromiumOptions
co = ChromiumOptions()
co.set_proxy('http://user-country-US:pass@gate.proxyhat.com:8080')
co.headless()
page = ChromiumPage(co)
page.get('https://httpbin.org/ip')Dlaczego proxy residential? Strony z silną ochroną anti-bot (Cloudflare, PerimeterX, DataDome) często blokują adresy IP z zakresów datacenter. Residential proxy ProxyHat pochodzą z rzeczywistych dostawców ISP, co sprawia, że ruch wygląda jak naturalny ruch użytkownika. Sprawdź dostępne lokalizacje proxy, aby dopasować geo-targeting do swojego przypadku użycia.
Przykład: WebPage z proxy ProxyHat — od HTTP do Chromium
Oto kompletny, uruchamialny przykład. WebPage rozpoczyna w trybie HTTP przez residential proxy z przypiętą sesją, pobiera stronę kategorii. Gdy wykryje, że treść wymaga JavaScript, przełącza się do trybu Chromium — zachowując ciasteczka i tę samą sesję proxy.
import uuid
from DrissionPage import WebPage, ChromiumOptions
# Budowanie nazwy użytkownika ProxyHat z geo-targetingiem i sesją
country = 'US'
session_id = 'abc123'
username = f'user-country-{country}-session-{session_id}'
password = 'twoje_haslo'
proxy_url = f'http://{username}:{password}@gate.proxyhat.com:8080'
# Przygotuj ChromiumOptions z proxy dla eskalacji do przeglądarki
co = ChromiumOptions()
co.set_proxy(proxy_url)
co.headless()
co.set_argument('--disable-gpu')
# Start w trybie HTTP (szybko, lekko)
page = WebPage(mode='session')
page.set_proxies(proxy_url)
# Krok 1: szybkie żądanie HTTP
page.get('https://shop.example.com/category/electronics')
print(f'Tryb: {page.mode}') # 'session'
# Sprawdź, czy treść wymaga renderowania JS
if 'product-list' not in page.html:
# Krok 2: eskalacja do Chromium — ciasteczka kopiowane automatycznie
page.change_mode(co=co)
page.get('https://shop.example.com/category/electronics')
# Nasłuchuj ukrytego API XHR
page.listen.start('api/products')
page.listen.wait(timeout=15)
# Wyciągnij dane z elementów
items = page.eles('@class=product-card')
for item in items:
name = item.ele('@class=product-name').text
price = item.ele('@class=price').text
print(f'{name}: {price}')
page.close()Kluczowy szczegół: flaga -session-abc123 w nazwie użytkownika ProxyHat przypina żądania do jednego adresu IP na czas życia sesji. To krytyczne dla stron, które śledzą spójność IP między żądaniami logowania i dostępu do treści. Zobacz dokumentację ProxyHat, aby poznać pełną listę flag geo-targetingu i sesji.
Wzorce produkcyjne — sesje, ponowienia, współbieżność
Przypinanie sesji proxy
Dla scrapingu wieloetapowego (logowanie → nawigacja → ekstrakcja) każdy krok musi pochodzić z tego samego IP. ProxyHat pozwala przypiąć sesję przez flagę -session- w nazwie użytkownika:
import uuid
def build_proxy_url(country='US', session=None):
if session is None:
session = uuid.uuid4().hex[:8]
username = f'user-country-{country}-session-{session}'
return f'http://{username}:pass@gate.proxyhat.com:8080'
# Każdy worker dostaje unikalną sesję = unikalny IP
proxy = build_proxy_url(session='worker-01')Ponowienia z wycofaniem (retry with backoff)
Nawet z residential proxy, ~2–5% żądań może zwrócić błąd (timeout, 403, 429). Wzorzec ponowień z wycofaniem jest niezbędny:
import time
import random
def fetch_with_retry(page, url, max_retries=3):
for attempt in range(max_retries):
try:
resp = page.get(url, timeout=15)
if resp.status_code == 200:
return resp
elif resp.status_code == 429:
wait = (2 ** attempt) + random.uniform(0, 1)
time.sleep(wait)
else:
return resp
except Exception as e:
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt)
return NonePrzechwytywanie ukrytych API przez listen
Wiele nowoczesnych stron ładuje dane przez XHR do punktu końcowego API, który nie jest udokumentowany. Zamiast parsować HTML, użyj listen, aby znaleźć ukryte API:
- Otwórz stronę w ChromiumPage z włączonym
listen.start()i szerokim filtrem. - Wykonaj akcję (scroll, kliknięcie, zmiana strony).
- Zbadaj przechwycone pakiety — szukaj odpowiedzi JSON z danymi.
- Gdy znajdziesz endpoint API, przełącz się na SessionPage, aby pobierać dane bezpośrednio — 10x szybciej i taniej.
Ten wzorzec „odkrycia przez przeglądarkę, pobierania przez HTTP” jest właśnie tym, do czego WebPage został zaprojektowany.
Limity współbieżności
Przy skalowaniu do setek żądań, pamiętaj o limitach:
- SessionPage: 50–100 równoczesnych żądań na proces (zależnie od CPU i przepustowości).
- ChromiumPage: 5–10 instancji na maszynę (każda zużywa ~300 MB RAM).
- ProxyHat: do 1000 równoczesnych sesji residential w zależności od planu — zobacz cennik ProxyHat.
W kontenerach Docker zalecany jest jeden ChromiumPage na kontener, z limitami pamięci --memory=512m i restart policy --restart=on-failure. Dla floty headless rozważ Kubernetes z HorizontalPodAutoscaler skalującym na podstawie metryk niestandardowych (np. długość kolejki zadań w Redis).
Kiedy NIE eskalować do przeglądarki i etyka scrapingu
Eskalacja do Chromium jest kosztowna — czas, RAM, przepustowość. Nie rób tego, gdy:
- Strona jest statyczna HTML. Jeśli
page.htmlw SessionPage zawiera potrzebne dane, nie uruchamiaj przeglądarki. - Dane są dostępne przez API. Sprawdź, czy strona oferuje oficjalne API — jest stabilniejsze i legalniejsze.
- Musisz pobrać tysiące stron. 1000 żądań HTTP trwa ~2 minuty; 1000 renderowań Chromium trwa ~50 minut.
- Strona blokuje headless Chrome. Nawet z proxy residential, fingerprinting przeglądarki może zdradzić automatyzację. Rozważ
co.set_argument('--disable-blink-features=AutomationControlled')lub przejście na czyste HTTP.
Etyka i legalność
Web scraping działa w szarej strefie prawnej. Kluczowe zasady:
- robots.txt: Zawsze sprawdzaj i przestrzegaj RFC 9309 — standardu robots.txt. DrissionPage nie ma wbudowanego parsera robots.txt, więc dodaj własny (np.
urllib.robotparserz biblioteki standardowej Python). - Rate limiting: Utrzymuj ≤1 żądanie/sekundę na domenę, chyba że strona wyraźnie na to pozwala.
- Dane osobowe: Pobieranie danych osobowych bez podstawy prawnej narusza RODO (GDPR) w UE i CCPA w Kalifornii.
- ToS: Wiele serwisów zabrania scrapingu w regulaminie — naruszenie może skutkować pozwem cywilnym.
DrissionPage to narzędzie; odpowiedzialność za jego użycie leży po Twojej stronie. Projekt DrissionPage na GitHub dokumentuje API, ale nie zastępuje oceny prawnej Twojego przypadku użycia.
Kluczowe wnioski
- DrissionPage = jedno API, dwa backendy. SessionPage dla szybkiego HTTP, ChromiumPage dla renderowania JS, WebPage dla płynnego przełączania z zachowaniem stanu.
- Proxy residential są kluczowe dla trudnych celów. Konfiguracja przez
set_proxies()(HTTP) lubChromiumOptions.set_proxy()(przeglądarka) z ProxyHatgate.proxyhat.com:8080. - Przechwytywanie XHR przez
listenznajduje ukryte API — potem przełącz się na SessionPage, aby pobierać dane 10x szybciej. - Przypinanie sesji przez flagę
-session-w nazwie użytkownika ProxyHat zapewnia spójność IP w scrapingu wieloetapowym. - Eskaluj do Chromium tylko gdy konieczne — 90% pracy wykonaj w HTTP, oszczędzając RAM i czas.
- Etyka przede wszystkim: przestrzegaj robots.txt, limitów żądań i przepisów RODO/CFAA.






