DrissionPage e proxy residenziali: un'unica libreria per HTTP e browser
Se hai mai scritto uno scraper Python, probabilmente hai combattuto con il dilemma classico: requests è veloce ed economico ma non esegue JavaScript, mentre Selenium o Playwright gestiscono il rendering ma consumano molta più CPU e memoria. DrissionPage risolve questo problema unendo entrambi i mondi in un'unica libreria, con un'API coerente che permette di passare dalla modalità HTTP al browser Chromium mantenendo cookie e stato di sessione.
In questa guida pratica vedrai come integrare proxy residenziali ProxyHat con DrissionPage per scraping affidabile su target difficili, con esempi di codice runnable, pattern di produzione e consigli su quando non escalare al browser.
Nota legale: lo scraping di dati pubblici è generalmente lecito, ma l'accesso non autorizzato a sistemi protetti può violare leggi come il Computer Fraud and Abuse Act (CFAA) negli USA o il GDPR in Europa. Rispetta sempre i
robots.txt, i Termini di Servizio e i rate limit. Quando esiste un'API ufficiale, preferiscila.
Il modello di DrissionPage: SessionPage, ChromiumPage e WebPage
DrissionPage si basa su tre classi principali che coprono l'intero spettro delle necessità di scraping:
- SessionPage — usa
requestssotto il cofano per richieste HTTP pure. Ideale per pagine statiche, API JSON, e qualsiasi contenuto che non richiede rendering JavaScript. Latenza tipica: 200–500ms per richiesta. - ChromiumPage — controlla un browser Chromium reale via Chrome DevTools Protocol (CDP), senza i driver esterni di Selenium. Esegue JavaScript, gestisce cookie, localStorage, e interazioni complesse come click e scroll.
- WebPage — la classe unificata che può passare dalla modalità
s(session/HTTP) alla modalitàd(driver/browser) condividendo cookie e stato. È il cuore del valore di DrissionPage.
Perché questo approccio riduce i costi? Un'istanza Chromium consuma tipicamente 150–300 MB di RAM per tab, mentre una richiesta HTTP con requests ne consuma meno di 5 MB. Se il 70% delle tue pagine è statico, passare a SessionPage per quelle e usare ChromiumPage solo per il 30% restante può ridurre il consumo di memoria del 60% o più.
Secondo la documentazione ufficiale di DrissionPage, il framework è progettato per "far cooperare richieste e browser come un unico strumento", eliminando la necessità di gestire due librerie separate con stato sincronizzato manualmente.
API idiomatica: ele(), eles(), ChromiumOptions e listen
DrissionPage ha un sistema di locatori proprio che unifica la sintassi per SessionPage e ChromiumPage. Questo significa che lo stesso codice di parsing funziona in entrambe le modalità.
Locatori con ele() ed eles()
Il metodo ele() restituisce un singolo elemento, eles() una lista. La sintassi supporta diversi selettori:
from DrissionPage import WebPage
page = WebPage()
# Selettore CSS con prefisso '@'
button = page.ele('@class=submit-btn')
# Tag con attributo
inputs = page.eles('tag:input')
# XPath
title = page.ele('xpath://h1[@id="main-title"]')
# Testo esatto
login_link = page.ele('text:Accedi')
# Combinazione: tag + classe
articles = page.eles('tag:div@class=article-card')
Una particolarità potente: ele() può concatenare ricerche gerarchiche senza dover scrivere XPath complessi:
# Cerca un div con classe 'sidebar', poi al suo interno un link
target = page.ele('@class=sidebar').ele('tag:a')
ChromiumOptions per configurare il browser
ChromiumOptions è il centro di configurazione per ChromiumPage. Qui imposti proxy, user-agent, headless mode, argomenti CLI e percorso dell'eseguibile:
from DrissionPage import ChromiumOptions, ChromiumPage
co = ChromiumOptions()
co.set_argument('--headless=new')
co.set_argument('--disable-gpu')
co.set_argument('--no-sandbox')
co.set_user_agent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...')
co.set_proxy('http://gate.proxyhat.com:8080')
page = ChromiumPage(co)
page.get('https://example.com')
Cattura di richieste XHR/JSON con listen
Una delle funzionalità più utili di DrissionPage è listen, che intercetta le richieste di rete in background del browser. Questo permette di catturare API nascoste che le pagine chiamano via XHR/fetch senza dover reverse-engineerare il traffico manualmente:
from DrissionPage import ChromiumPage, ChromiumOptions
co = ChromiumOptions()
co.set_proxy('http://gate.proxyhat.com:8080')
page = ChromiumPage(co)
# Avvia l'ascolto di URL che contengono 'api/data'
page.listen.start('api/data')
# Naviga alla pagina che triggera la chiamata
page.get('https://example.com/dashboard')
# Attendi il pacchetto catturato
packet = page.listen.wait(timeout=10)
if packet:
print(packet.url) # URL della richiesta
print(packet.request.body) # Body della richiesta
print(packet.response.body) # Body della risposta (JSON)
page.listen.stop()
Questo pattern è estremamente potente: invece di parsare l'HTML renderizzato, catturi direttamente il JSON che il frontend riceve dal backend. Più pulito, più veloce, più affidabile.
Configurare proxy in DrissionPage con ProxyHat
DrissionPage supporta proxy in entrambe le modalità, ma con API diverse. Vediamo entrambe con i parametri di ProxyHat.
Proxy in SessionPage (modalità HTTP)
SessionPage usa il sistema di proxy di requests, configurabile tramite set_proxies():
from DrissionPage import SessionPage
page = SessionPage()
page.set.proxies({
'http': 'http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080',
'https': 'http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080'
})
page.get('https://httpbin.org/ip')
print(page.html)
Proxy in ChromiumPage (modalità browser)
Per il browser, il proxy si imposta in ChromiumOptions prima di avviare l'istanza:
from DrissionPage import ChromiumOptions, ChromiumPage
co = ChromiumOptions()
co.set_proxy('http://user-country-DE-session-def456:pass@gate.proxyhat.com:8080')
co.set_argument('--headless=new')
page = ChromiumPage(co)
page.get('https://httpbin.org/ip')
Nota importante: Chromium applica il proxy a livello di processo, quindi tutte le richieste del browser (immagini, CSS, XHR) passano attraverso lo stesso proxy. Questo è un vantaggio per l'autenticità del traffico ma significa che devi scegliere un proxy con banda sufficiente.
Perché i proxy residenziali sono necessari per target difficili
I siti con protezioni anti-bot avanzate (Cloudflare, PerimeterX, DataDome) identificano e bloccano rapidamente gli IP datacenter. I proxy residenziali usano IP reali assegnati da ISP a utenti domestici, rendendo il traffico indistinguibile da quello di un utente legittimo.
Con ProxyHat, puoi geo-targetizzare a livello di paese o città e mantenere sessioni sticky per preservare lo stato di login attraverso più richieste. Vedi le locazioni disponibili per copertura dettagliata.
Esempio runnable: WebPage con escalation da HTTP a Chromium
Vediamo un esempio completo che illustra il pattern più potente di DrissionPage: iniziare in modalità HTTP per una pagina statica, poi escalare a Chromium per una pagina che richiede rendering JavaScript, tutto con lo stesso proxy residenziale e sessione condivisa.
from DrissionPage import WebPage
import json
import time
# Helper per costruire lo username ProxyHat
def proxyhat_username(country='US', session=None):
user = f'user-country-{country}'
if session:
user += f'-session-{session}'
return user
PROXY_USER = proxyhat_username(country='US', session='abc123')
PROXY_PASS = 'your_password'
PROXY_HTTP = f'http://{PROXY_USER}:{PROXY_PASS}@gate.proxyhat.com:8080'
# Inizializza WebPage in modalità session (HTTP)
page = WebPage(mode='s')
page.set.proxies({
'http': PROXY_HTTP,
'https': PROXY_HTTP
})
# Fase 1: richiesta HTTP veloce per una pagina statica
page.get('https://httpbin.org/headers')
print('IP check (HTTP mode):', page.ele('tag:pre').text[:200])
# Salva i cookie della sessione HTTP
cookies = page.cookies()
print(f'Cookie raccolti: {len(cookies)}')
# Fase 2: escalation a modalità browser (Chromium)
# WebPage mantiene i cookie della sessione HTTP
page.change_mode() # passa da 's' a 'd' automaticamente
# Il browser eredita lo stato; imposta lo stesso proxy
# (ChromiumOptions viene configurato internamente da WebPage)
# Naviga a una pagina che richiede JavaScript
page.get('https://quotes.toscrape.com/js/')
# Attendi il rendering dinamico
page.wait.eles_displayed('tag:div@class=quote', timeout=10)
# Estrai le citazioni usando ele()/eles() — stessa API di SessionPage
quotes = page.eles('tag:div@class=quote')
for q in quotes[:5]:
text = q.ele('tag:span@class=text').text
author = q.ele('tag:small@class=author').text
print(f'{author}: {text[:80]}...')
print(f'\nTotale citazioni estratte: {len(quotes)}')
page.close()
Questo esempio mostra il flusso ideale: HTTP per la prima richiesta (veloce, economica), poi browser solo quando serve. Il passaggio change_mode() trasferisce automaticamente cookie e header dalla sessione HTTP al browser Chromium.
Pattern di produzione: sessioni sticky, retry, cattura pacchetti e concorrenza
Per-session proxy pinning
Per siti che richiedono login o mantenimento di stato, usa sessioni sticky ProxyHat. Lo stesso IP viene mantenuto per tutta la durata della sessione:
import uuid
def create_sticky_page(country='US'):
session_id = str(uuid.uuid4())[:8]
proxy_user = f'user-country-{country}-session-{session_id}'
proxy_url = f'http://{proxy_user}:pass@gate.proxyhat.com:8080'
page = WebPage(mode='s')
page.set.proxies({'http': proxy_url, 'https': proxy_url})
return page, session_id
# Usa la stessa sessione per login + navigazione
page, sid = create_sticky_page('US')
page.get('https://example.com/login')
# ... fai il login ...
page.get('https://example.com/protected-area')
# L'IP resta lo stesso grazie alla sessione sticky
Retry con backoff esponenziale
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)
print(f'Rate limited, attesa {wait:.1f}s')
time.sleep(wait)
else:
print(f'Status {resp.status_code}, retry {attempt+1}')
except Exception as e:
print(f'Errore: {e}, retry {attempt+1}')
time.sleep(2 ** attempt)
return None
Cattura di API nascoste via listen
Molti siti moderni caricano i dati via XHR dopo il rendering iniziale. Invece di parsare l'HTML, cattura direttamente le risposte JSON:
from DrissionPage import ChromiumPage, ChromiumOptions
co = ChromiumOptions()
co.set_proxy('http://user-country-US-session-xyz:pass@gate.proxyhat.com:8080')
co.set_argument('--headless=new')
page = ChromiumPage(co)
# Ascolta tutte le richieste che contengono 'api' o 'graphql'
page.listen.start(['api', 'graphql'])
page.get('https://example.com/products')
# Raccogli 10 pacchetti
packets = page.listen.wait(count=10, timeout=30)
for p in packets:
if p.response.body:
try:
data = json.loads(p.response.body)
print(f'{p.url} → {len(str(data))} bytes')
except json.JSONDecodeError:
pass
page.listen.stop()
Concorrenza e limiti
Per scraping ad alto volume, gestisci la concorrenza con cura. Ogni istanza ChromiumPage consuma ~200 MB di RAM. Una macchina con 8 GB può gestire circa 20–30 istanze browser simultanee, mentre lo stesso hardware può sostenere 200+ sessioni HTTP.
Pattern consigliato: usa un pool di worker con concurrent.futures per SessionPage e riserva ChromiumPage per task che lo richiedono davvero:
from concurrent.futures import ThreadPoolExecutor, as_completed
def scrape_url(url):
page = WebPage(mode='s')
proxy = f'http://user-country-US-session-{url[-6:]}:pass@gate.proxyhat.com:8080'
page.set.proxies({'http': proxy, 'https': proxy})
try:
page.get(url, timeout=15)
return page.ele('tag:title').text
except Exception as e:
return f'Error: {e}'
finally:
page.close()
urls = ['https://example.com/page1', 'https://example.com/page2']
with ThreadPoolExecutor(max_workers=10) as executor:
futures = {executor.submit(scrape_url, u): u for u in urls}
for f in as_completed(futures):
print(f.result())
Consulta le documentazione ProxyHat per i limiti di concorrenza specifici del tuo piano.
Confronto: DrissionPage vs alternative
| Caratteristica | DrissionPage | Playwright | Selenium | requests + BeautifulSoup |
|---|---|---|---|---|
| HTTP + Browser unificati | Sì (WebPage) | No (solo browser) | No (solo browser) | No (solo HTTP) |
| Condivisione cookie HTTP→Browser | Automatica | Manuale | Manuale | N/A |
| Controllo Chromium via CDP | Nativo | Sì | Tramite driver | No |
| Cattura XHR/JSON | listen.start() nativo | page.route() / page.on() | Richiede driver esterno | N/A |
| RAM per istanza browser | ~200 MB | ~150–250 MB | ~300–400 MB | N/A |
| Configurazione proxy unificata | Sì (HTTP + browser) | Solo browser | Solo browser | Solo HTTP |
| API locatori unificata | ele()/eles() in entrambe le modalità | Locatori browser only | Locatori browser only | BS4 selectors |
Quando NON escalare al browser
Non ogni sito richiede Chromium. Escalare al browser quando non necessario è il errore più comune e costoso. Ecco quando restare in SessionPage:
- Il contenuto è nell'HTML iniziale — se
page.get(url)in modalità HTTP restituisce già i dati nel HTML, non hai bisogno del browser. Verifica concurlprima. - Esiste un'API JSON pubblica — molti siti espongono endpoint REST/GraphQL non documentati. Usa
listenuna volta per trovarli, poi chiamali direttamente con SessionPage. - Volume alto, struttura semplice — se devi processare 10.000 pagine con la stessa struttura statica, SessionPage è 10–50x più veloce e consuma 40x meno RAM.
- Il sito non ha protezioni anti-bot — se non vedi challenge Cloudflare o CAPTCHA, HTTP puro con proxy residenziali è sufficiente.
Escalata a ChromiumPage solo quando:
- Il contenuto è generato lato client via JavaScript.
- Il sito richiede interazioni complesse (click, scroll, drag-and-drop).
- Le protezioni anti-bot verificano fingerprint del browser.
- Devi catturare traffico XHR per reverse-engineerare API nascoste.
Considerazioni etiche e legali
Lo scraping è uno strumento potente che richiede responsabilità. Alcuni principi:
- Rispetta
robots.txt— DrissionPage non lo fa automaticamente. Controlla prima di avviare lo scraping. - Onora i rate limit — se un sito risponde con 429, rallenta. Usa backoff esponenziale.
- Preferisci API ufficiali — se il sito offre un'API pubblica o a pagamento, usala. È più affidabile e legalmente sicura.
- Raccogli solo dati pubblici — non accedere a aree protette senza autorizzazione. Il CFAA negli USA e leggi simili in altri paesi possono considerare l'accesso non autorizzato un reato.
- GDPR e dati personali — se raccogli dati personali di cittadini UE, devi rispettare il GDPR. Consulta le linee guida GDPR.
Key Takeaways
- DrissionPage unifica HTTP e browser in un'unica libreria con API coerente, riducendo costo e complessità rispetto a usare due strumenti separati.
- WebPage è la classe chiave: passa da SessionPage (HTTP) a ChromiumPage (browser) mantenendo cookie e stato, permettendo di usare HTTP quando basta e il browser solo quando serve.
- Proxy residenziali ProxyHat si configurano con
set_proxies()per SessionPage eChromiumOptions.set_proxy()per il browser, con geo-targeting e sessioni sticky. - listen.start() cattura richieste XHR/JSON in background, permettendo di estrarre dati da API nascoste senza parsare HTML renderizzato.
- Non escalare sempre al browser: se il contenuto è statico o esiste un'API, SessionPage è 10–50x più veloce e consuma 40x meno RAM.
- Produzione richiede retry, concorrenza controllata, e rispetto di robots.txt e rate limit.
Pronto a iniziare? Esplora i piani ProxyHat o consulta le use case di web scraping per altri pattern. Per tracking SERP specifico, vedi la nostra guida su SERP tracking con proxy.






