DrissionPage и прокси: полное руководство по веб-скрапингу с переключением HTTP и Chromium

Практическое руководство по DrissionPage — Python-фреймворку, объединяющему requests-стиль HTTP и управление Chromium через CDP. Настройка прокси, переключение режимов, перехват XHR и продакшн-паттерны с ProxyHat.

DrissionPage Proxy Guide: HTTP + Chromium Scraping with Residential IPs

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-режиме и эскалировать до браузера только там, где это действительно нужно.

Три модели страниц

КлассДвижокКогда использоватьНакладные расходы
SessionPagerequests-подобный HTTP-клиентСтатичные HTML, JSON API, файлы~5–15 МБ RAM, ~100–300 мс на запрос
ChromiumPageChromium через CDPJS-рендеринг, 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 — самый быстрый способ их найти:

  1. Откройте страницу в ChromiumPage с включённым listen.start() без фильтра.
  2. Соберите все URL и MIME-типы ответов.
  3. Найдите application/json ответы с нужными данными.
  4. Перепишите скрапер на прямой 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 URLhttp://USERNAME:PASSWORD@gate.proxyhat.com:8080
Формат SOCKS5 URLsocks5://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.

Готовы начать?

Доступ к более чем 50 млн резидентных IP в 148+ странах с AI-фильтрацией.

Смотреть ценыРезидентные прокси
← Вернуться в Блог