DrissionPage — это Python-фреймворк, который объединяет в одном API два подхода к веб-скрапингу: быстрый HTTP-клиент в стиле requests и полноценное управление браузером Chromium через Chrome DevTools Protocol (CDP). Если вы устали держать в проекте одновременно requests + Selenium + Playwright и вручально синхронизировать cookies между ними — DrissionPage решает эту проблему. В этом руководстве по DrissionPage мы разберём архитектуру фреймворка, идиоматичные паттерны работы, настройку прокси DrissionPage через ProxyHat и продакшн-паттерны для масштабного DrissionPage веб-скрапинга.
Важно: эта статья посвящена сбору публично доступных данных. Использование автоматизированных инструментов для доступа к защищённым страницам может нарушать Условия использования (ToS) сайтов, а в некоторых юрисдикциях — закон CFAA (США) или GDPR (ЕС). Уважайте
robots.txt, соблюдайте лимиты запросов и предпочитайте официальные API, если они доступны. Ответственность за соблюдение законодательства лежит на вас.
DrissionPage: зачем ещё один фреймворк
Большинство Python-скраперов начинаются с requests — быстро, лёгко, но без JavaScript. Когда целевой сайт начинает рендерить контент через React/Vue, разработчик подключает Selenium или Playwright. Теперь в проекте два HTTP-стека, две системы cookies, две стратегии прокси. DrissionPage устраняет этот разрыв: один объект страницы может работать в режиме HTTP (SessionPage) или в режиме браузера (ChromiumPage), а класс WebPage переключается между ними на лету, сохраняя cookies и состояние сессии.
Почему это снижает стоимость? Полноценный браузер Chromium потребляет 200–500 МБ RAM на одну вкладку и в 10–50 раз медленнее HTTP-запроса. Если 80% страниц вашего пайплайна можно забрать простым GET-запросом, нет смысла гонять браузер для каждого запроса. DrissionPage позволяет начать в дешёвом HTTP-режиме и эскалировать до браузера только там, где это действительно нужно.
Три модели страниц
| Класс | Движок | Когда использовать | Накладные расходы |
|---|---|---|---|
SessionPage | requests-подобный HTTP-клиент | Статичные HTML, JSON API, файлы | ~5–15 МБ RAM, ~100–300 мс на запрос |
ChromiumPage | Chromium через CDP | JS-рендеринг, SPA, интерактивные действия | ~200–500 МБ RAM, 2–10 с на страницу |
WebPage | Переключается между Session и Chromium | Смешанные пайплайны с общими cookies | Зависит от активного режима |
Ключевая идея: WebPage хранит cookies и localStorage, поэтому когда вы переключаетесь из HTTP-режима в браузерный, вам не нужно заново проходить авторизацию или решать CAPTCHA. Подробнее об архитектуре читайте в официальной документации DrissionPage.
Идиоматичный API DrissionPage
DrissionPage использует собственный синтаксис локаторов, который короче и выразительнее, чем чистый XPath. Метод ele() возвращает один элемент, eles() — список.
Локаторы ele() и eles()
Синтаксис поддерживает несколько форматов:
'@class=price'— поиск по атрибуту (префикс@).'tag:input'— поиск по тегу.'xpath://div[@id="main"]'— классический XPath с префиксомxpath:.'text:Купить'— поиск по тексту.'@class=price@@text()=1 299 ₽'— комбинированные условия через@@.
from DrissionPage import WebPage
page = WebPage()
page.get('https://example-shop.com/products')
# Один элемент
price = page.ele('@class=price').text
# Все элементы
cards = page.eles('tag:div@class=product-card')
for card in cards:
title = card.ele('tag:h2').text
link = card.ele('tag:a').attr('href')
print(title, link)
ChromiumOptions и конфигурация браузера
Для DrissionPage Chromium режимов конфигурация выполняется через объект ChromiumOptions, который передаётся в ChromiumPage или WebPage:
from DrissionPage import ChromiumOptions, WebPage
co = ChromiumOptions()
co.headless(True)
co.set_argument('--no-sandbox')
co.set_argument('--disable-gpu')
co.set_argument('--window-size=1920,1080')
co.set_user_agent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
page = WebPage(chromium_options=co)
Перехват XHR и JSON через listen.start()
Одна из самых мощных возможностей DrissionPage — мониторинг сетевых запросов в фоне. Метод listen.start() запускает прослушивание, а listen.wait() блокирует выполнение до появления нужного пакета. Это позволяет находить скрытые JSON API, которые SPA загружают через XHR/Fetch:
from DrissionPage import WebPage
page = WebPage()
page.listen.start('api/products') # фильтр по URL-паттерну
page.get('https://example-shop.com/catalog')
packet = page.listen.wait(timeout=15)
if packet:
data = packet.response.body # распарсенный JSON
print(f"Получено {len(data.get('items', []))} товаров")
Этот паттерн часто избавляет от необходимости парсить DOM вообще — вы перехватываете сырой JSON, который сайт и так загружает. Скорость сбора вырастает в 5–20 раз по сравнению с парсингом отрендеренного HTML.
Настройка прокси DrissionPage
Прокси — критический компонент любого серьёзного скрапера. Без ротации IP целевой сайт заблокирует вас после 50–200 запросов с одного адреса. DrissionPage поддерживает прокси на двух уровнях: для SessionPage (HTTP-режим) и для ChromiumPage (браузерный режим).
Прокси для SessionPage
В HTTP-режиме прокси передаются через метод set.proxies(), который принимает стандартный формат http://user:pass@host:port:
from DrissionPage import SessionPage
page = SessionPage()
page.set.proxies('http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080')
page.get('https://httpbin.org/ip')
print(page.json['origin']) # IP прокси-сервера
Прокси для ChromiumPage через ChromiumOptions
В браузерном режиме прокси настраиваются через ChromiumOptions.set_proxy(). Прокси применяется на уровне браузера, поэтому все запросы — включая XHR, Fetch, WebSocket и загрузку ресурсов — идут через указанный прокси:
from DrissionPage import ChromiumOptions, WebPage
co = ChromiumOptions()
co.set_proxy('http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080')
co.headless(True)
page = WebPage(chromium_options=co)
page.get('https://httpbin.org/ip')
print(page.ele('tag:pre').text)
Почему residential-прокси, а не datacenter
Datacenter-прокси дешевле (от $0.5/GB против $3–8/GB у residential), но они легко детектируются по ASN. Сервисы антибот-защиты (Cloudflare, Datadome, PerimeterX) проверяют, принадлежит ли IP к дата-центру, и блокируют его. Residential-прокси используют IP реальных ISP-подписчиков, что делает их неотличимыми от обычных пользователей. Для сложных целей — SERP-скрапинг, e-commerce, соцсети — residential-прокси дают success rate 90–99% против 30–60% у datacenter. Подробное сравнение типов прокси см. в статье о прокси-серверах на Wikipedia.
Runnable-пример: WebPage с переключением режимов
Теперь соберём всё вместе. Мы создадим WebPage, который начнёт в HTTP-режиме через residential-прокси ProxyHat с гео-таргетингом на США и sticky-сессией, затем эскалирует до ChromiumPage для JS-рендеринговой страницы. Имя пользователя формируется динамически через SDK-подход.
import time
import random
from DrissionPage import WebPage, ChromiumOptions
def build_proxy(country='US', session_id=None):
"""Строит URL прокси ProxyHat с гео-таргетингом и sticky-сессией."""
if session_id is None:
session_id = f'sess-{random.randint(10000, 99999)}'
username = f'user-country-{country}-session-{session_id}'
password = 'your_proxyhat_password'
return f'http://{username}:{password}@gate.proxyhat.com:8080'
# --- Шаг 1: HTTP-режим для быстрого сбора списка ---
proxy_url = build_proxy(country='US', session_id='abc123')
page = WebPage() # по умолчанию SessionPage
page.set.proxies(proxy_url)
page.get('https://httpbin.org/ip')
print('HTTP-режим IP:', page.json['origin'])
# Собираем список URL товаров со статичной страницы
page.get('https://example-shop.com/sitemap')
links = page.eles('tag:loc') # XML sitemap
product_urls = [l.text for l in links if '/product/' in l.text]
print(f'Найдено {len(product_urls)} товаров')
# --- Шаг 2: Эскалация до Chromium для JS-страницы ---
co = ChromiumOptions()
co.set_proxy(proxy_url) # тот же прокси — cookies сохраняются
co.headless(True)
co.set_argument('--no-sandbox')
page.change_mode(chromium_options=co) # переключение с сохранением cookies
# Включаем перехват XHR до загрузки страницы
page.listen.start('api/product-detail')
page.get(product_urls[0])
# Ждём JSON-ответ от SPA
packet = page.listen.wait(timeout=15)
if packet:
product_data = packet.response.body
print('Название:', product_data.get('name'))
print('Цена:', product_data.get('price'))
else:
# Fallback: парсим DOM
title = page.ele('@class=product-title').text
price = page.ele('@class=price').text
print(f'Из DOM: {title} — {price}')
time.sleep(2)
page.quit()
Обратите внимание: при вызове change_mode() cookies переносятся автоматически. Вам не нужно повторно авторизоваться или заново проходить проверку Cloudflare, которую вы могли пройти в HTTP-режиме.
Продакшн-паттерны для DrissionPage
1. Per-session прокси-пиннинг
Sticky-сессии (параметр -session-ID в имени пользователя ProxyHat) гарантируют, что все запросы в рамках одной логической сессии идут с одного IP. Это критично для сайтов, которые привязывают корзину или токен авторизации к IP-адресу. Если IP сменится посередине сессии, сервер разлогинит вас. ProxyHat поддерживает sticky-сессии до 30 минут:
session_id = f'user-{int(time.time())}'
proxy = f'http://user-country-DE-session-{session_id}:pass@gate.proxyhat.com:8080'
2. Ретраи с экспоненциальной задержкой
Даже с residential-прокси 1–5% запросов завершатся ошибкой (таймаут, 429, 503). Ретраи — обязательный паттерн:
import time
from DrissionPage import WebPage
def fetch_with_retry(page, url, max_retries=3):
for attempt in range(max_retries):
try:
resp = page.get(url, timeout=20)
if resp and page.status_code == 200:
return page
if page.status_code in (429, 503):
wait = 2 ** attempt + random.uniform(0, 1)
time.sleep(wait)
continue
except Exception as e:
print(f'Попытка {attempt + 1} не удалась: {e}')
time.sleep(2 ** attempt)
return None
3. Перехват пакетов для поиска скрытых API
Многие SPA загружают данные через внутренние эндпоинты, которые не задокументированы, но доступны напрямую. Перехват через listen — самый быстрый способ их найти:
- Откройте страницу в ChromiumPage с включённым
listen.start()без фильтра. - Соберите все URL и MIME-типы ответов.
- Найдите
application/jsonответы с нужными данными. - Перепишите скрапер на прямой HTTP-запрос к этому API через SessionPage.
Этот подход часто ускоряет сбор в 10–20 раз, потому что вы обходите рендеринг DOM целиком.
4. Конкурентность и лимиты
Chromium тяжёлый: 100 параллельных вкладок потребуют 20–50 ГБ RAM. Практические лимиты для одной машины:
- SessionPage: 100–500 одновременных запросов (ограничено пулом прокси и лимитами целевого сайта).
- ChromiumPage: 5–15 одновременных вкладок на машину с 16 ГБ RAM.
- Контейнеризация: запуск 10 контейнеров по 5 вкладок эффективнее, чем 50 вкладок в одном процессе — изоляция предотвращает утечки памяти.
# Docker-ориентированный запуск
# docker run --rm --shm-size=2g -e PROXY_URL=$PROXY_URL my-scraper
import os
proxy = os.environ.get('PROXY_URL', '')
co = ChromiumOptions()
co.set_proxy(proxy)
co.set_argument('--disable-dev-shm-usage') # важно для Docker
co.set_argument('--no-sandbox')
Когда НЕ нужно эскалировать до браузера
Преждевременное переключение в Chromium — самая частая ошибка начинающих. Прежде чем запускать браузер, проверьте:
- Статичный ли HTML? Откройте страницу в режиме инкогнито без JS. Если контент виден — SessionPage справится.
- Есть ли скрытый API? Используйте DevTools → Network → XHR. Если JSON доступен напрямую — забирайте его через HTTP.
- Нужна ли интерактивность? Если нужно кликнуть кнопку, заполнить форму или дождаться анимации — тогда Chromium оправдан.
- Стоимость vs скорость. 1000 страниц через SessionPage: ~5 минут, ~$0.01. Те же 1000 через Chromium: ~2 часа, ~$0.50 + электричество.
Правило большого пальца: начинайте с SessionPage. Эскалируйте до Chromium только когда HTTP-запрос возвращает пустой или неполный контент.
Этика и право
Сбор публичных данных легален в большинстве юрисдикций, но есть границы. CFAA (Computer Fraud and Abuse Act, США) запрещает «превышение авторизованного доступа» — если сайт требует логин, а вы скрапите за логином без разрешения, это может быть нарушением. GDPR (ЕС) требует осторожности при обработке персональных данных. Практические правила:
- Уважайте
robots.txt— DrissionPage не проверяет его автоматически, это ваша ответственность. - Не превышайте 1 запрос в секунду на домен, если нет явного разрешения.
- Предпочитайте официальные API. У Google, Amazon, Twitter есть платные API — используйте их, если бюджет позволяет.
- Не храните персональные данные дольше, чем необходимо для вашей задачи.
Подробнее о правовых аспектах автоматизированного сбора данных см. в статье о CFAA на Wikipedia.
Настройка ProxyHat для DrissionPage
ProxyHat предоставляет residential, mobile и datacenter прокси с гибким управлением через параметры в имени пользователя. Для DrissionPage рекомендуется residential-прокси для сложных целей и datacenter — для простых HTTP-запросов.
Параметры подключения
| Параметр | Значение |
|---|---|
| Шлюз | gate.proxyhat.com |
| HTTP-порт | 8080 |
| SOCKS5-порт | 1080 |
| Формат HTTP URL | http://USERNAME:PASSWORD@gate.proxyhat.com:8080 |
| Формат SOCKS5 URL | socks5://USERNAME:PASSWORD@gate.proxyhat.com:1080 |
Гео-таргетинг и сессии
Гео-таргетинг и sticky-сессии задаются прямо в имени пользователя:
user-country-US— IP из США.user-country-DE-city-berlin— IP из Берлина, Германия.user-session-abc123— sticky-сессия (один IP на все запросы).user-country-GB-session-order456— комбинированный формат.
Полный список доступных локаций см. на странице локаций ProxyHat. Тарифы — на странице цен. Документация по API доступна на docs.proxyhat.com.
SOCKS5 для DrissionPage
Если ваш целевой сайт блокирует HTTP-прокси, SOCKS5 может помочь, так как он работает на уровне TCP и менее заметен:
co = ChromiumOptions()
co.set_proxy('socks5://user-country-US-session-abc123:pass@gate.proxyhat.com:1080')
page = WebPage(chromium_options=co)
Ключевые выводы
- DrissionPage объединяет HTTP и Chromium в одном API — нет нужды держать два стека.
- Начинайте с SessionPage (быстро, дёшево), эскалируйте до ChromiumPage только при необходимости JS-рендеринга.
- Используйте
listen.start()для перехвата скрытых JSON API — это часто ускоряет сбор в 10–20 раз.- Residential-прокси через ProxyHat (
gate.proxyhat.com:8080) дают success rate 90–99% на сложных целях.- Sticky-сессии (
-session-ID) критичны для сайтов, привязывающих сессию к IP.- Конкурентность: 100–500 для SessionPage, 5–15 для ChromiumPage на машину.
- Всегда уважайте
robots.txt, лимиты запросов и право. Предпочитайте официальные API.
Готовы применить DrissionPage с residential-прокси на практике? Изучите варианты использования веб-скрапинга и SERP-трекинга с ProxyHat, или выберите тариф, который подходит вашему объёму.
FAQ
Что такое DrissionPage?
DrissionPage — это open-source Python-фреймворк для веб-автоматизации, который объединяет HTTP-клиент (SessionPage) и управление браузером Chromium через CDP (ChromiumPage) в одном API. Класс WebPage позволяет переключаться между режимами на лету, сохраняя cookies и состояние сессии. Это устраняет необходимость держать в проекте одновременно requests и Selenium/Playwright.
Зачем DrissionPage нужен прокси?
Без ротации IP целевой сайт заблокирует ваш скрапер после 50–200 запросов с одного адреса. Прокси распределяют запросы по множеству IP-адресов, а residential-прокси (IP реальных ISP-подписчиков) делают запросы неотличимыми от обычных пользователей. Это критично для SERP-скрапинга, e-commerce и соцсетей, где антибот-системы (Cloudflare, Datadome) активно детектируют datacenter-IP.
Какой тип прокси лучше для DrissionPage?
Residential-прокси — для сложных целей (SERP, e-commerce, соцсети), где datacenter-IP блокируются. Datacenter-прокси — для простых HTTP-запросов к статичным сайтам или API, где детекция не критична. Mobile-прокси — для самых защищённых целей (соцсети, тикетинг), где нужна максимальная легитимность. ProxyHat поддерживает все три типа через один шлюз gate.proxyhat.com:8080.
Как избежать блокировок при работе с DrissionPage?
Используйте residential-прокси с ротацией IP, соблюдайте лимиты запросов (не более 1 запроса в секунду на домен), добавляйте случайные задержки между запросами, используйте sticky-сессии для сайтов, привязывающих сессию к IP, и перехватывайте скрытые API через listen.start(), чтобы минимизировать количество запросов. Уважайте robots.txt и предпочитайте официальные API.
Можно ли использовать SOCKS5 с DrissionPage?
Да. DrissionPage поддерживает SOCKS5 через ChromiumOptions.set_proxy(). Формат: socks5://user-country-US-session-abc123:pass@gate.proxyhat.com:1080. SOCKS5 работает на уровне TCP и может быть менее заметен для некоторых антибот-систем. ProxyHat предоставляет SOCKS5 на порту 1080.






