Что такое DrissionPage и зачем ему прокси
Python-разработчики, занимающиеся веб-скрапингом, давно привыкли к компромиссу: requests для быстрых HTTP-запросов или Selenium/Playwright для рендеринга JavaScript. DrissionPage устраняет этот выбор, объединяя оба подхода в одном фреймворке с общим состоянием сессии. Вы начинаете с лёгкого HTTP-запроса, а при необходимости переключаетесь на полноценный браузер Chromium — без потери cookies, заголовков и контекста.
Однако даже лучший фреймворк бесполезен против жёстких антибот-систем, если все запросы идут с одного IP-адреса. Residential-прокси необходимы для обхода гео-ограничений, rate-limiting и IP-based fingerprinting. В этом руководстве мы разберём, как интегрировать DrissionPage с прокси ProxyHat для надёжного и масштабируемого скрапинга.
Правовая оговорка: статья охватывает сбор только публично доступных данных. Неправомерный доступ к защищённым системам может нарушать CFAA (США), GDPR (ЕС) и аналогичные законы других юрисдикций. Уважайте
robots.txt, условия обслуживания сайтов и ограничения по скорости. Если у сайта есть официальный API — предпочтите его.
Архитектура DrissionPage: три режима работы
DrissionPage предлагает три класса страниц, каждый из которых решает свою задачу. Понимание различий между ними — ключ к эффективному скрапингу, который не сжигает ресурсы впустую.
SessionPage — чистый HTTP
SessionPage работает поверх библиотеки requests (или urllib3). Это самый быстрый и лёгкий режим: один запрос занимает ~50ms, расход RAM — около 20MB. Идеально для статичных HTML-страниц, REST API и JSON-эндпоинтов, не требующих рендеринга JavaScript.
ChromiumPage — полноценный браузер
ChromiumPage управляет браузером через Chrome DevTools Protocol (CDP) — без Selenium WebDriver в качестве посредника. Это даёт прямой доступ к сети, DOM и JavaScript-контексту страницы. Запуск страницы занимает ~200-500ms, расход RAM — 150-300MB на инстанс. Используется, когда контент рендерится JavaScript или требует взаимодействия с динамическими элементами.
WebPage — переключение на лету
WebPage — ключевая инновация DrissionPage. Он объединяет SessionPage и ChromiumPage, позволяя переключаться между HTTP- и браузерным режимами в рамках одной сессии. Cookies, заголовки и состояние сохраняются при переключении. Это снижает стоимость скрапинга на 40-60% для сайтов, где только часть страниц требует рендеринга JS.
| Свойство | SessionPage | ChromiumPage | WebPage |
|---|---|---|---|
| Движок | requests / urllib3 | CDP → Chromium | Оба, переключение |
| Скорость запроса | ~50ms | ~200-500ms | Зависит от режима |
| JS-рендеринг | Нет | Да | Да (при переключении) |
| Расход RAM | ~20MB | 150-300MB | Зависит от режима |
| Прокси-настройка | set_proxies() | ChromiumOptions.set_proxy() | Оба метода |
| Перехват XHR | Нет | listen.start() | listen.start() |
Подробная документация по всем классам доступна на официальном сайте DrissionPage.
Идиоматичный API DrissionPage
DrissionPage имеет свой синтаксис локаторов, который компактнее XPath и гибче CSS-селекторов. Понимание этих паттернов — основа drissionpage tutorial для продакшена.
Локаторы ele() и eles()
Метод ele() возвращает первый найденный элемент, eles() — список всех совпадений. Синтаксис поддерживает несколько форматов:
from DrissionPage import WebPage
page = WebPage()
page.get('https://example.com')
# По тегу
title = page.ele('tag:h1').text
# По атрибуту
button = page.ele('@class=submit-btn')
# XPath
items = page.eles('xpath://div[@class="item"]')
# Комбинированный синтаксис: tag + атрибут
links = page.eles('tag:a@href^=https')
# Текст содержит
elem = page.ele('text:Купить')
Комбинированный синтаксис tag:a@href^=https означает: найти все теги <a>, у которых атрибут href начинается с https. Это читается проще, чем эквивалентный XPath //a[starts-with(@href, 'https')].
ChromiumOptions — конфигурация браузера
ChromiumOptions управляет параметрами запуска Chromium: headless-режим, user-agent, прокси, размер окна, расширения. Для drissionpage chromium сценариев это центральная точка конфигурации:
from DrissionPage import ChromiumOptions
co = ChromiumOptions()
co.headless(True)
co.set_argument('--no-sandbox')
co.set_argument('--disable-gpu')
co.set_user_agent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...')
co.set_proxy('http://user-country-US:pass@gate.proxyhat.com:8080')
listen.start() — перехват сетевых пакетов
Одна из самых мощных возможностей DrissionPage — перехват XHR/Fetch запросов через CDP. Вы можете слушать фоновые запросы и извлекать JSON-данные, которые сайт загружает асинхронно:
from DrissionPage import ChromiumPage
page = ChromiumPage()
page.listen.start('api/products') # фильтр по URL
page.get('https://shop.example.com/catalog')
for packet in page.listen.steps(count=10):
print(packet.url)
data = packet.response.body # JSON-ответ
print(data)
Этот паттерн часто позволяет получить структурированные данные из скрытых API, минуя парсинг HTML вообще. Если сайт загружает данные через XHR в формате JSON — нет смысла парсить DOM.
Настройка drissionpage proxy: SessionPage и ChromiumPage
Прокси-конфигурация различается между режимами. В SessionPage прокси устанавливается через метод set_proxies(), в ChromiumPage — через ChromiumOptions.set_proxy().
Прокси для SessionPage
from DrissionPage import SessionPage
page = SessionPage()
page.set_proxies('http://user-country-DE:pass@gate.proxyhat.com:8080')
page.get('https://httpbin.org/ip')
print(page.html)
Прокси для ChromiumPage
from DrissionPage import ChromiumPage, ChromiumOptions
co = ChromiumOptions()
co.set_proxy('http://user-country-DE:pass@gate.proxyhat.com:8080')
co.headless(True)
page = ChromiumPage(co)
page.get('https://httpbin.org/ip')
print(page.ele('tag:pre').text)
Почему residential-прокси, а не datacenter
Datacenter IP-адреса легко распознаются антибот-системами — Cloudflare, Akamai, PerimeterX и Datadome ведут базы диапазонов дата-центров. Residential-прокси используют IP реальных устройств, что делает их неотличимыми от обычных пользователей. Для жёстких целей — SERP-трекинг, e-commerce, социальные сети — residential-прокси обеспечивают success rate 90%+ против 30-50% у datacenter.
ProxyHat предоставляет residential-прокси с гео-таргетингом по странам и городам, а также sticky-сессии для сохранения IP между запросами. Подробности — на странице локаций ProxyHat и в официальной документации.
Практический пример: WebPage с ProxyHat
Теперь соберём всё вместе. Мы создадим WebPage, который начинает в HTTP-режиме через residential-прокси США, собирает базовые данные, а затем переключается в режим Chromium для рендеринга JS-зависимой страницы — с сохранением cookies и сессии.
from DrissionPage import WebPage
import json
# ProxyHat: residential, США, sticky-сессия
PROXY_HTTP = 'http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080'
def scrape_product(url: str) -> dict:
page = WebPage()
# --- Режим 1: SessionPage (быстрый HTTP) ---
page.set_proxies(PROXY_HTTP)
page.get(url)
# Проверяем, есть ли нужные данные в HTML
title_el = page.ele('tag:h1')
if title_el:
title = title_el.text
price_el = page.ele('@class=price')
price = price_el.text if price_el else None
if price: # Данные доступны без JS
page.close()
return {'title': title, 'price': price, 'mode': 'http'}
# --- Режим 2: переключение в Chromium ---
# Cookies и заголовки сохраняются автоматически
page.change_mode() # SessionPage → ChromiumPage
# Тот же прокси применяется к браузеру
# (настраивается через ChromiumOptions при инициализации,
# либо через page.set.proxy() после переключения)
page.get(url) # перезагружаем с рендерингом JS
page.wait.eles_loaded('@class=price')
title = page.ele('tag:h1').text
price = page.ele('@class=price').text
# Перехватываем XHR для получения структурированных данных
page.listen.start('api/product')
page.get(url)
packet = page.listen.wait()
if packet:
api_data = json.loads(packet.response.body)
price = api_data.get('price', price)
page.close()
return {'title': title, 'price': price, 'mode': 'chromium'}
result = scrape_product('https://shop.example.com/product/123')
print(json.dumps(result, indent=2))
Этот паттерн — «HTTP сначала, браузер при необходимости» — снижает расход ресурсов на 50%+ для сайтов, где только часть страниц требует рендеринга. Вы платите за браузер только тогда, когда он действительно нужен.
Продвинутая конфигурация с ProxyHat SDK
Для управления ротацией и гео-таргетингом можно построить helper, который генерирует username с нужными параметрами:
import random
import string
def build_proxyhat_username(
country: str = 'US',
city: str = None,
session_id: str = None,
mobile: bool = False
) -> str:
"""Строит username для ProxyHat с гео и сессионными параметрами."""
parts = ['user']
if mobile:
parts.append('mobile')
parts.append(f'country-{country}')
if city:
parts.append(f'city-{city.lower()}')
if session_id:
parts.append(f'session-{session_id}')
return '-'.join(parts)
def make_proxy(country='US', session_id=None):
username = build_proxyhat_username(
country=country,
session_id=session_id or ''.join(
random.choices(string.ascii_lowercase + string.digits, k=8)
)
)
return f'http://{username}:pass@gate.proxyhat.com:8080'
# Пример: sticky-сессия для одного домена
proxy = make_proxy(country='US', session_id='shop123')
# Пример: ротация при каждом запросе (без session_id)
proxy_rotating = make_proxy(country='US')
Sticky-сессии важны для сайтов, которые привязывают корзину или токен к IP-адресу. Если IP меняется в середине сессии — сайт может разлогинить пользователя. ProxyHat поддерживает sticky-сессии до 30 минут через параметр session-{id} в username. Тарифы и лимиты — на странице цен ProxyHat.
Паттерны продакшена: масштабирование DrissionPage
Переход от прототипа к продакшену требует другой архитектуры. Вот ключевые паттерны для надёжного drissionpage web scraping в продакшене.
1. Per-session proxy pinning
Каждая логическая сессия скрапинга должна привязываться к одному IP через sticky-сессию. Это предотвращает срабатывание антибот-систем, которые отслеживают смену IP в рамках одной пользовательской сессии:
from DrissionPage import WebPage
import uuid
class ScraperSession:
def __init__(self, country='US'):
self.session_id = str(uuid.uuid4())[:8]
self.proxy = make_proxy(country=country, session_id=self.session_id)
self.page = WebPage()
self.page.set_proxies(self.proxy)
def fetch(self, url):
for attempt in range(3):
try:
self.page.get(url, timeout=15)
if self.page.status_code == 200:
return self.page.html
except Exception as e:
print(f'Попытка {attempt+1} неудачна: {e}')
# Ротируем сессию при ошибке
self.session_id = str(uuid.uuid4())[:8]
self.proxy = make_proxy(country='US', session_id=self.session_id)
self.page.set_proxies(self.proxy)
return None
def close(self):
self.page.close()
2. Retries с экспоненциальной задержкой
Сетевые ошибки и временные блокировки — норма при скрапинге. Реализуйте retry с экспоненциальной задержкой и ротацией IP при повторных попытках:
- Попытка 1: базовая задержка 1s
- Попытка 2: задержка 2s, новый IP
- Попытка 3: задержка 4s, новый IP + новый User-Agent
- Попытка 4: задержка 8s, переключение в Chromium-режим
3. Packet capture для обнаружения скрытых API
Многие сайты загружают данные через XHR/Fetch в формате JSON. Вместо парсинга HTML используйте listen.start() для перехвата этих запросов. Это быстрее, надёжнее и даёт структурированные данные. Проверьте вкладку Network в DevTools — если видите JSON-ответы, DrissionPage может их перехватить программно.
4. Управление конкурентностью
ChromiumPage требует ~150-300MB RAM на инстанс. На сервере с 8GB RAM можно запускать 15-20 параллельных браузеров. Для SessionPage лимит выше — 100+ параллельных сессий на те же ресурсы. Используйте asyncio или concurrent.futures.ThreadPoolExecutor для SessionPage и пул процессов для ChromiumPage.
from concurrent.futures import ThreadPoolExecutor, as_completed
def scrape_url(url: str) -> dict:
session = ScraperSession(country='US')
try:
html = session.fetch(url)
# ... парсинг ...
return {'url': url, 'status': 'ok'}
finally:
session.close()
urls = ['https://example.com/page1', 'https://example.com/page2']
with ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(scrape_url, url) for url in urls]
for f in as_completed(futures):
result = f.result()
print(result)
5. Контейнеризация
Для масштабирования запускайте DrissionPage в Docker-контейнерах с Chromium, установленным системно. Базовый образ:
FROM python:3.11-slim
RUN apt-get update && apt-get install -y \
chromium \
chromium-driver \
fonts-liberation \
&& rm -rf /var/lib/apt/lists/*
RUN pip install DrissionPage
ENV CHROME_PATH=/usr/bin/chromium
COPY scraper.py /app/
WORKDIR /app
CMD ["python", "scraper.py"]
При горизонтальном масштабировании каждый контейнер получает свой пул прокси-сессий. Оркестрация через Kubernetes позволяет автоматически масштабировать количество подов в зависимости от нагрузки. Для SERP-трекинга с высокой частотой запросов см. use-case SERP-трекинга.
Когда НЕ переходить на браузер
Преждевременное переключение в Chromium-режим — частая ошибка. Браузер в 4-10 раз медленнее и требует в 10-15 раз больше RAM. Переходите на Chromium только если:
- Контент рендерится JavaScript (React, Vue, Angular SPA)
- Страница требует взаимодействия (клик, скролл, заполнение формы)
- Антибот-система требует выполнения JS-челленджей (Cloudflare Turnstile, reCAPTCHA)
- Нужно перехватить XHR-запросы через
listen.start()
Во всех остальных случаях SessionPage достаточен. Если сайт отдаёт HTML с данными при прямом HTTP-запросе — нет смысла запускать браузер. Проверьте: сделайте curl запрос и посмотрите, есть ли нужные данные в ответе. Если да — используйте SessionPage.
Для задач, где браузер всё-таки нужен, drissionpage chromium через CDP эффективнее Selenium, так как обходит WebDriver-обнаружение. CDP не оставляет следов navigator.webdriver, которые Selenium WebDriver выставляет по умолчанию.
Ключевые выводы
- DrissionPage объединяет HTTP и браузерный скрапинг в одном фреймворке с общим состоянием — это снижает стоимость и сложность инфраструктуры.
WebPageпозволяет переключаться между SessionPage и ChromiumPage на лету, сохраняя cookies и сессию.- Прокси настраиваются через
set_proxies()для HTTP иChromiumOptions.set_proxy()для браузера, с residential-прокси ProxyHat черезgate.proxyhat.com:8080. listen.start()перехватывает XHR/Fetch запросы — часто это лучший способ получить структурированные данные без парсинга HTML.- Sticky-сессии через
session-{id}в username сохраняют IP для одной логической сессии скрапинга. - Переходите в Chromium-режим только при необходимости — это снижает расход RAM в 10-15 раз для простых страниц.
- Уважайте
robots.txt, условия обслуживания и ограничения по скорости. Собирайте только публичные данные.
Готовы начать? Изучите use-case веб-скрапинга и тарифы ProxyHat для выбора подходящего плана residential-прокси.






