DrissionPage est devenu l'un des frameworks Python les plus pratiques pour le web scraping hybride : il combine la simplicité de requests et la puissance de Selenium/Playwright dans une seule API. Mais pour scraper des cibles sérieuses — SERP Google, marketplaces e-commerce, réseaux sociaux — il faut un proxy DrissionPage robuste. Ce guide vous montre comment intégrer des proxies résidentiels ProxyHat dans DrissionPage, basculer entre HTTP et Chromium intelligemment, et déployer en production.
Rappel légal : Le scraping de données publiques est légal dans de nombreuses juridictions, mais des lois comme le Computer Fraud and Abuse Act (CFAA) aux États-Unis ou le RGPD en Europe imposent des limites. Respectez toujours le
robots.txt, les conditions d'utilisation des sites, et ne collectez jamais de données personnelles sans base légale. Privilégiez les API officielles quand elles existent.
DrissionPage : un framework qui unifie HTTP et Chromium
La plupart des scrapers Python utilisent soit requests (rapide, léger, mais sans JavaScript), soit un navigateur headless comme Selenium ou Playwright (puissant, mais 10 à 50× plus lent et gourmand en RAM). DrissionPage résout ce dilemme en proposant trois objets complémentaires :
- SessionPage — mode HTTP pur, basé sur une session
requests.Sessionsous le capot. Idéal pour les pages statiques, les API JSON cachées, et tout ce qui ne nécessite pas de rendu JS. - ChromiumPage — contrôle d'un navigateur Chromium réel via le Chrome DevTools Protocol (CDP). Gère le JavaScript, les SPA, les CAPTCHA interactifs, et les clics.
- WebPage — un objet unique qui peut basculer entre les deux modes à la volée, tout en partageant cookies, headers et état de session. C'est la killer feature de DrissionPage.
Pourquoi c'est important ? Un scraper typique passe 80% de son temps sur des pages où le JavaScript n'est pas nécessaire. En utilisant SessionPage pour ces 80% et ChromiumPage seulement pour les 20% restants, on réduit drastiquement le coût d'infrastructure : moins de CPU, moins de RAM, moins de temps d'exécution, et moins de sessions proxy consommées.
| Critère | SessionPage (HTTP) | ChromiumPage (CDP) | WebPage (hybride) |
|---|---|---|---|
| Vitesse moyenne | ~200 ms / requête | 2–5 s / page | Dépend du mode actif |
| RAM consommée | ~30 MB | 200–500 MB | 30–500 MB |
| Rendu JavaScript | Non | Oui | Oui en mode Chromium |
| Capture XHR/JSON | Non applicable | Oui via listen |
Oui en mode Chromium |
| Partage de cookies | Oui | Oui | Oui entre les deux modes |
Configurer un proxy DrissionPage avec ProxyHat
L'intégration d'un proxy diffère selon le mode utilisé. En SessionPage, on passe par set_proxies(). En ChromiumPage, on configure via ChromiumOptions.set_proxy(). Voyons les deux.
Proxy pour SessionPage (mode HTTP)
from DrissionPage import SessionPage
# Proxy résidentiel ProxyHat — pays US, session collante
proxy_url = "http://user-country-US-session-abc123:PASSWORD@gate.proxyhat.com:8080"
page = SessionPage()
page.set.proxies(proxy_url)
page.get("https://httpbin.org/ip")
print(page.json) # {"origin": "<IP résidentielle US>"}
Le format du nom d'utilisateur ProxyHat encode le pays et la session. La session abc123 garantit que toutes les requêtes de cette SessionPage sortent par la même IP résidentielle, ce qui est crucial pour conserver un panier d'achat ou un token d'authentification.
Proxy pour ChromiumPage (mode navigateur)
from DrissionPage import ChromiumPage, ChromiumOptions
proxy_str = "http://user-country-US-session-abc123:PASSWORD@gate.proxyhat.com:8080"
co = ChromiumOptions()
co.set_proxy(proxy_str)
co.headless(True)
co.set_argument('--no-sandbox')
co.set_argument('--disable-gpu')
page = ChromiumPage(co)
page.get("https://httpbin.org/ip")
print(page.ele('tag:pre').text) # Affiche l'IP du proxy
Notez que ChromiumOptions accepte le proxy au format URL standard. Le navigateur Chromium applique le proxy à toutes ses connexions : documents, XHR, WebSockets, et même les iframes.
L'API idiomatique de DrissionPage : ele(), eles() et listen
DrissionPage propose une syntaxe de localisation d'éléments plus concise que Selenium. Voici les patterns essentiels.
Localisation d'éléments avec ele() et eles()
from DrissionPage import WebPage
page = WebPage()
# Par attribut CSS
title = page.ele('@class=product-title')
# Par tag + attribut
inputs = page.eles('tag:input')
# Par XPath
price = page.ele('xpath://span[@class="price"]')
# Par texte
btn = page.ele('text:Ajouter au panier')
# Récupérer plusieurs éléments
links = page.eles('tag:a@href^https')
for link in links:
print(link.attr('href'))
La syntaxe '@attr=value' est un raccourci DrissionPage pour les sélecteurs CSS. 'tag:input' filtre par balise HTML. On peut combiner : 'tag:div@class=card'. C'est plus lisible que les XPath complexes pour 90% des cas.
Capturer les requêtes XHR en arrière-plan avec listen
L'une des fonctionnalités les plus puissantes de DrissionPage est listen, qui intercepte les requêtes réseau du navigateur Chromium. C'est idéal pour découvrir des API JSON cachées derrière des SPA.
from DrissionPage import ChromiumPage, ChromiumOptions
import json
proxy_str = "http://user-country-DE-session-xyz789:PASSWORD@gate.proxyhat.com:8080"
co = ChromiumOptions()
co.set_proxy(proxy_str)
co.headless(True)
page = ChromiumPage(co)
# Démarrer l'écoute des paquets contenant du JSON
page.listen.start('api/products')
page.get("https://example-shop.com/catalog")
# Attendre le premier paquet correspondant
packet = page.listen.wait(timeout=10)
if packet:
data = packet.response.body
products = json.loads(data)
print(f"{len(products)} produits trouvés via API cachée")
for p in products[:3]:
print(f" - {p['name']}: {p['price']}€")
page.listen.stop()
Cette approche est considérablement plus efficace que de scraper le DOM rendu : on récupère directement le JSON structuré, sans parser le HTML, et on économise du temps de navigateur. Dans nos tests, capturer une API XHR prend ~300 ms contre 3–5 s pour un scraping DOM complet sur une SPA.
Exemple complet : WebPage avec bascule HTTP → Chromium
Voici un exemple runnable qui illustre le workflow hybride : on commence en mode HTTP pour une page d'index statique, puis on bascule en mode Chromium pour une page nécessitant du rendu JavaScript, tout en conservant le même proxy et les mêmes cookies.
from DrissionPage import WebPage
import uuid
import time
def build_proxy_username(country="US", session_id=None):
"""Construit un nom d'utilisateur ProxyHat avec géo-ciblage et session."""
if session_id is None:
session_id = str(uuid.uuid4())[:8]
return f"user-country-{country}-session-{session_id}"
def scrape_hybride():
session_id = str(uuid.uuid4())[:8]
username = build_proxy_username(country="US", session_id=session_id)
password = "YOUR_PASSWORD"
proxy_url = f"http://{username}:{password}@gate.proxyhat.com:8080"
# Initialiser WebPage en mode s (Session/HTTP)
page = WebPage(mode='s')
page.set.proxies(proxy_url)
# Étape 1 : HTTP — récupérer la liste des produits (page statique)
page.get("https://books.toscrape.com/")
book_links = page.eles('tag:h3 > tag:a')
urls = [link.attr('href') for link in book_links[:5]]
print(f"[HTTP] {len(urls)} liens trouvés en mode SessionPage")
# Étape 2 : basculer en mode Chromium pour une page JS-rendered
page.change_mode() # passe en mode c (Chromium), conserve cookies + proxy
# Le proxy est automatiquement réutilisé via ChromiumOptions internes
# mais on peut le reconfigurer explicitement si besoin
page.set.proxy(proxy_url) # réapplique le proxy en mode Chromium
# Écouter les XHR pendant le rendu
page.listen.start('api/')
page.get("https://quotes.toscrape.com/js/")
time.sleep(2) # laisser le JS s'exécuter
quotes = page.eles('tag:div@class=quote')
print(f"[Chromium] {len(quotes)} citations trouvées après rendu JS")
for q in quotes[:3]:
text = q.ele('tag:span@class=text').text
author = q.ele('tag:small@class=author').text
print(f" → {author}: {text[:60]}...")
# Vérifier si des API cachées ont été capturées
packets = page.listen.steps(count=5, timeout=5)
if packets:
print(f"[listen] {len(packets)} paquets XHR interceptés")
page.listen.stop()
page.close()
if __name__ == "__main__":
scrape_hybride()
Points clés de cet exemple :
WebPage(mode='s')démarre en HTTP.change_mode()bascule vers Chromium en transférant automatiquement les cookies de la session HTTP vers le navigateur.- Le même
session_idest utilisé dans les deux modes, donc la même IP résidentielle ProxyHat est conservée. Le site cible voit un visiteur cohérent. listen.start()capture les XHR en arrière-plan pendant que Chromium rend la page. On peut ainsi découvrir des endpoints d'API non documentés.
Patterns de production : rotation, retries et concurrence
Pinning de session par tâche
En production, chaque tâche de scraping doit avoir sa propre session proxy pour éviter qu'une IP soit bannie et affecte toutes les tâches. Utilisez un UUID par tâche :
import uuid
from DrissionPage import SessionPage
def scrape_product(product_id):
session_id = str(uuid.uuid4())[:8]
proxy = f"http://user-country-US-session-{session_id}:PASS@gate.proxyhat.com:8080"
page = SessionPage()
page.set.proxies(proxy)
page.set.timeout(15)
for attempt in range(3):
try:
resp = page.get(f"https://shop.com/product/{product_id}")
if resp.status_code == 200:
return page.html
elif resp.status_code == 429:
time.sleep(2 ** attempt) # backoff exponentiel
else:
break
except Exception as e:
print(f"Tentative {attempt+1} échouée: {e}")
time.sleep(2 ** attempt)
return None
Limites de concurrence
ProxyHat supporte des centaines de sessions simultanées, mais chaque session Chromium consomme ~300 MB de RAM. Pour un serveur avec 8 GB de RAM, limitez-vous à ~20 instances Chromium parallèles maximum. Pour le mode SessionPage, vous pouvez facilement atteindre 100+ requêtes concurrentes.
Utilisez concurrent.futures.ThreadPoolExecutor pour le mode HTTP et ProcessPoolExecutor pour le mode Chromium (afin d'éviter le GIL sur le parsing) :
from concurrent.futures import ThreadPoolExecutor, as_completed
import uuid
def scrape_url(url):
sid = str(uuid.uuid4())[:8]
proxy = f"http://user-country-US-session-{sid}:PASS@gate.proxyhat.com:8080"
page = SessionPage()
page.set.proxies(proxy)
page.set.timeout(15)
page.get(url)
result = page.ele('tag:title').text
page.close()
return result
urls = ["https://example.com/page1", "https://example.com/page2", ...]
with ThreadPoolExecutor(max_workers=20) as executor:
futures = {executor.submit(scrape_url, url): url for url in urls}
for future in as_completed(futures):
url = futures[future]
try:
title = future.result()
print(f"{url}: {title}")
except Exception as e:
print(f"Erreur sur {url}: {e}")
Découverte d'API cachées via listen
Le pattern listen de DrissionPage est particulièrement utile pour le suivi SERP et le scraping e-commerce. De nombreux sites modernes chargent leurs données via des appels XHR vers des endpoints JSON non documentés. En écoutant le trafic réseau, on peut :
- Identifier l'endpoint exact (URL, méthode, headers).
- Reproduire l'appel en mode SessionPage (HTTP pur), 10× plus rapide.
- Éliminer complètement le besoin de navigateur pour les pages suivantes.
C'est une stratégie d'escalade inverse : on commence en Chromium pour découvrir l'API, puis on descend en HTTP pour scaler.
Quand NE PAS passer en mode Chromium
La bascule vers Chromium est coûteuse. Voici les cas où vous devez rester en SessionPage :
- Pages statiques — si le HTML contient déjà les données, inutile de lancer un navigateur.
- API JSON connues — si vous avez déjà identifié l'endpoint via
listen, appelez-le directement en HTTP. - Endpoints REST/GraphQL — beaucoup de sites exposent des API que vous pouvez interroger avec
requestsen ajoutant les bons headers. - Fichiers à télécharger — images, PDFs, CSVs : SessionPage gère ça parfaitement.
Passez en Chromium uniquement quand :
- La page nécessite l'exécution de JavaScript pour afficher le contenu.
- Vous devez interagir avec des éléments (clics, formulaires complexes, scroll infini).
- Le site utilise des challenges CAPTCHA qui nécessitent un environnement navigateur.
- Vous devez capturer des XHR pour découvrir une API cachée.
Erreurs courantes et cas limites
1. Oublier de reconfigurer le proxy après change_mode()
WebPage.change_mode() transfère les cookies mais ne garantit pas que le proxy HTTP soit appliqué au navigateur Chromium dans toutes les versions de DrissionPage. Appelez explicitement page.set.proxy(proxy_url) après le changement de mode pour être sûr.
2. Utiliser une session proxy partagée pour trop de requêtes
Si vous faites 500 requêtes avec la même session session-abc123, le site cible peut flaguer cette IP pour comportement automatisé. Renouvelez la session tous les 50–100 requêtes, ou utilisez la rotation par requête (sans flag de session) pour les tâches sans état.
3. Ne pas gérer les timeouts de listen
page.listen.wait(timeout=10) lève une exception si aucun paquet n'arrive dans le délai. Encadrez toujours dans un try/except :
try:
packet = page.listen.wait(timeout=10)
if packet:
data = packet.response.body
except Exception as e:
print(f"Aucun paquet capturé: {e}")
4. Lancer Chromium sans --no-sandbox en conteneur
Dans Docker ou CI/CD, Chromium nécessite --no-sandbox et souvent --disable-dev-shm-usage pour éviter les crashes liés à /dev/shm trop petit :
co = ChromiumOptions()
co.set_argument('--no-sandbox')
co.set_argument('--disable-dev-shm-usage')
co.set_argument('--disable-gpu')
co.set_argument('--shm-size=2g')
ProxyHat : configuration et tarifs
Pour configurer vos proxies résidentiels ProxyHat avec DrissionPage, consultez la documentation officielle ProxyHat pour le format exact des identifiants. Les points essentiels :
- Passerelle HTTP :
gate.proxyhat.com:8080 - Passerelle SOCKS5 :
gate.proxyhat.com:1080 - Géo-ciblage :
user-country-FR-city-paris:pass - Session collante :
user-session-abc123:pass
Consultez la page de tarifs ProxyHat pour les plans résidentiels, et la page des localisations pour la liste complète des pays disponibles. Pour des cas d'usage avancés, visitez notre guide sur le web scraping avec proxies.
Points clés à retenir
- WebPage est la killer feature de DrissionPage : bascule HTTP ↔ Chromium avec partage de cookies et de proxy.
- Proxy résidentiel obligatoire pour les cibles difficiles : utilisez
user-country-XX-session-YYYpour pincer une IP par tâche.- listen.start() capture les XHR cachés — la stratégie la plus efficace pour découvrir des API JSON non documentées.
- Restez en HTTP quand possible : 80% des pages n'ont pas besoin de Chromium. Vous économisez RAM, temps et crédits proxy.
- Limitez la concurrence Chromium à ~20 instances pour 8 GB de RAM ; SessionPage supporte 100+ threads.
- Respectez robots.txt, CFAA et RGPD : ne scrapez que des données publiques, et préférez les API officielles.
FAQ
Qu'est-ce que DrissionPage ?
DrissionPage est un framework Python open-source qui unifie le scraping HTTP (style requests) et le contrôle navigateur Chromium via le Chrome DevTools Protocol (CDP). Il propose SessionPage pour les requêtes HTTP rapides, ChromiumPage pour le rendu JS, et WebPage qui bascule entre les deux en partageant cookies et état.
Pourquoi DrissionPage est-il important pour les utilisateurs de proxies ?
DrissionPage permet d'utiliser le même proxy résidentiel pour des requêtes HTTP légères et pour un navigateur Chromium. On commence en HTTP (rapide, économique) puis on bascule en navigateur uniquement pour le rendu JS, tout en conservant la même IP et les mêmes cookies via le session ID ProxyHat.
Quel type de proxy fonctionne le mieux avec DrissionPage ?
Les proxies résidentiels avec session collante sont recommandés : ils utilisent des IP d'opérateurs réels (rarement bloquées) et le flag session-xxx garantit la même IP à travers la bascule HTTP → Chromium. Les proxies datacenter conviennent pour des tâches simples sans anti-bot.
Comment éviter les blocages avec DrissionPage ?
Combinez proxies résidentiels rotatifs, sessions pinnées par tâche, délais aléatoires (1–3 s), capture XHR via listen pour éviter de charger toute la page, et respect du robots.txt. Renouvelez les sessions tous les 50–100 requêtes et utilisez un backoff exponentiel sur les HTTP 429.
Peut-on utiliser SOCKS5 avec DrissionPage ?
Oui. Pour SessionPage, utilisez socks5://user-country-US:pass@gate.proxyhat.com:1080. Pour ChromiumPage, Chromium supporte SOCKS5 via ChromiumOptions.set_proxy() avec le même format. Le port SOCKS5 de ProxyHat est 1080.






