Bifrost Logo BifrostNetwork
Назад к списку статей
Техническая команда BifrostNetwork

Scraper Proxy и Playwright: резидентные прокси, сессии, повторы и проверка данных

Практическое руководство на Python: аутентификация прокси в Playwright, закреплённые сессии, 429 Retry-After, оптимизация трафика браузера и проверка данных со ссылками на официальные источники.

После подключения прокси выходной IP изменился, но цены остались от другого региона. Страница вернула HTTP 200, а пригодных для сохранения товаров нет. Даже блокировка изображений иногда не уменьшает трафик прокси. Почему?

Причины находятся на разных уровнях: сетевой выход, состояние браузера, готовность страницы и проверка данных. В рабочей интеграции scraper proxy нужно совместно управлять сессиями прокси и контекстами браузера, а успех оценивать по данным, нужным бизнесу. Разберём это на Python, Playwright и BifrostNetwork.

Источники проверены 14 сентября 2026 года. Статья опирается на официальную документацию и стандарты протоколов. Примеры показывают подключение и проверку, а не измеренные показатели успешности, задержки или экономии коммерческого прокси.

1. Определите, за какой уровень отвечает прокси

Scraper proxy — это сетевой выход, через который сборщик обращается к сайту. Proxy scraper обычно означает инструмент для сбора адресов прокси; это другая задача.

В нашей архитектуре очередь назначает время посещения, Playwright выполняет JavaScript, шлюз выбирает выход, парсер извлекает поля, а валидатор решает, что сохранить. Прокси не поддерживает селекторы и не предоставляет отсутствующие права доступа.

Условия задачиС чего начатьЧто проверять
Официальный API или экспорт предоставляет нужные поляПредпочесть этот интерфейсКвоты, права на данные, актуальность
Все данные уже есть в HTMLHTTP-клиент, при необходимости с проксиТочность разбора, требования к выходу
Нужны JavaScript или взаимодействие со страницейPlaywright с прокси для задачиГотовность, состояние контекста, ресурсы браузера
Нужны наблюдения из резидентной сети определённого рынкаПроверить резидентный выходФактическая страна, рынок страницы, непрерывность сессии

Это инженерные рекомендации, а не доказательство превосходства резидентных прокси. Сравнение затрат есть в руководстве по выбору scraper proxy.

Playwright позволяет задать прокси при запуске браузера или для отдельного BrowserContext. Независимые контексты не делятся cookies и кешем, поэтому подходят для изоляции задач. Сеть в Playwright, Browser.new_context.

2. Сначала разберитесь с протоколом и аутентификацией

Поддержка SOCKS5 в Chromium не означает поддержку пароля

Документация Chromium прямо указывает, что Chrome не поддерживает методы аутентификации SOCKSv5. Строка SOCKS5 с паролем, работающая в requests, может не работать в Playwright Chromium. Здесь используется HTTP-прокси с именем пользователя и паролем. Реализация прокси в Chromium.

proxy.username и proxy.password служат для аутентификации на прокси, а http_credentials — для HTTP-аутентификации на сайте. Не передавайте пароль прокси в настройки сайта и не отправляйте Proxy-Authorization как обычный заголовок запросов страницы. Настройки Playwright.

Адрес прокси с http:// допускает HTTPS-адрес назначения. HTTP-прокси может создать туннель CONNECT, внутри которого проходит TLS до целевого сервера. Но внешнее соединение между клиентом и прокси от этого не становится зашифрованным. Для защиты аутентификации на этом участке используйте HTTPS-прокси, явно поддерживаемый провайдером и клиентом; простой замены префикса недостаточно. RFC 9110: CONNECT, HTTP/HTTPS-прокси в Chromium.

Скопируйте реквизиты из панели и добавьте маршрутизацию в имя пользователя

Текущая документация BifrostNetwork указывает шлюз gate.bifrostnetwork.cc:9521 и поддержку HTTP/HTTPS CONNECT. Имя пользователя может включать страну, ID сессии и TTL. Базовое имя копируйте из заказа, а не угадывайте код тарифа по примеру. Документация подключения.

БАЗОВОЕ_ИМЯ-country-us-session-УНИКАЛЬНЫЙ_ID_ЗАДАЧИ-ttl-300

-country-us запрашивает выход в США, -session-… — закреплённую сессию, а -ttl-300 задаёт 300 секунд. Если TTL не указан, документированное значение по умолчанию — 600 секунд. Неподдерживаемые комбинации региона и ASN могут приводить к выбору запасного маршрута, поэтому имя пользователя не доказывает фактическую страну. Параметры сессий и географии.

3. Один процесс — один контекст и одна сессия прокси

Список товаров → выбор рынка → открытие карточки → чтение цены — единый процесс с состоянием. Свяжите с ID задачи:

task_id
  ├─ country + proxy_session_id
  ├─ BrowserContext (cookies, хранилище сайта, locale)
  └─ время начала/окончания + результат проверки данных

Закрывайте контекст по завершении процесса и создавайте новый ID сессии для следующей независимой задачи. Не переключайте конфигурацию прокси между навигацией, скриптами и XHR одной страницы; не меняйте только выход, сохраняя cookies предыдущего рынка.

Это изоляция задач, а не гарантия выдачи ранее не использовавшегося IP каждой новой сессии. На результат влияют повторное использование соединений, доступность узлов и маршрутизация. Одна проверка выхода не доказывает, что все последующие подзапросы пройдут через тот же узел. В длинных процессах проверяйте выход на ключевых шагах и переносите задачи, превышающие запланированное время сессии.

Проверяйте отдельно страну IP, locale браузера, страну доставки и валюту сайта. locale="en-US" влияет на языковое поведение браузера, но не создаёт американский IP и не заменяет выбор рынка на странице. Настройка locale.

4. Пример Python: проверьте одну страницу до расширения очереди

Установите Playwright и соответствующий Chromium в отдельном окружении Python. В рабочей системе фиксируйте версии Python, Playwright и браузера для воспроизводимых регрессионных проверок. Установка Playwright.

python -m pip install playwright
python -m playwright install chromium

Передайте переменные через локальное окружение или менеджер секретов. Не сохраняйте пароли в репозитории или общей истории shell.

ПеременнаяЗначение
BIFROST_BASE_USERNAMEБазовое имя из панели без добавляемых ниже параметров маршрутизации
BIFROST_PASSWORDПароль прокси
TARGET_URLHTTPS-страница, сбор которой вы проверили на допустимость
READY_SELECTORCSS-селектор одного уникального элемента с нужными данными
EXPECTED_TEXTНепустой текст, который должен содержаться в элементе
BIFROST_PROXY_SERVERНеобязательно; по умолчанию http://gate.bifrostnetwork.cc:9521

Сохраните код как scraper_proxy.py и выполните python scraper_proxy.py. Он посещает страницу один раз. Ошибки аутентификации, HTTP и содержимого передаются планировщику без скрытой смены IP или повторов.

import asyncio
import json
import os
import time
import uuid
from urllib.parse import urlsplit

from playwright.async_api import async_playwright, expect


async def main():
    target = os.environ["TARGET_URL"]
    selector = os.environ["READY_SELECTOR"]
    expected = os.environ["EXPECTED_TEXT"].strip()
    parsed = urlsplit(target)
    if parsed.scheme != "https" or not parsed.hostname or not expected:
        raise ValueError("Нужны корректный HTTPS-адрес и непустой ожидаемый текст")

    task_id = uuid.uuid4().hex[:16]
    base = os.environ["BIFROST_BASE_USERNAME"]
    proxy = {
        "server": os.environ.get(
            "BIFROST_PROXY_SERVER", "http://gate.bifrostnetwork.cc:9521"
        ),
        "username": f"{base}-country-us-session-{task_id}-ttl-300",
        "password": os.environ["BIFROST_PASSWORD"],
    }

    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        try:
            context = await browser.new_context(proxy=proxy, locale="en-US")
            try:
                page = await context.new_page()
                started = time.monotonic()
                response = await page.goto(
                    target, wait_until="domcontentloaded", timeout=30_000
                )
                if response is None:
                    raise RuntimeError("Навигация не вернула ответ основного документа")
                if not 200 <= response.status < 300:
                    # Планировщик может записать и разобрать значение; не повторяйте запрос сразу здесь.
                    raise RuntimeError(json.dumps({
                        "task_id": task_id,
                        "status": response.status,
                        "retry_after": response.headers.get("retry-after"),
                    }))

                ready = page.locator(selector)
                await expect(ready).to_have_count(1, timeout=10_000)
                await expect(ready).to_be_visible(timeout=10_000)
                await expect(ready).to_contain_text(expected, timeout=10_000)
                print(json.dumps({
                    "task_id": task_id,
                    "status": response.status,
                    "elapsed_ms": round((time.monotonic() - started) * 1000),
                    "content_check": "passed",
                }))
            finally:
                await context.close()
        finally:
            await browser.close()


if __name__ == "__main__":
    asyncio.run(main())

Подберите селектор и ожидаемый текст для реальной страницы: универсального селектора для всех магазинов нет. В рабочем варианте проверяйте также конечный URL, ID товара, цену, валюту, рынок и время сбора, удаляя дубликаты по бизнес-ключу. Пример показывает лишь условие готовности, способное явно завершиться ошибкой. Пустой селектор, несколько совпадений или тайм-аут не означают автоматически сбой прокси. Locator assertions повторяют проверку до истечения заданного времени. Locator assertions.

page.goto() не выбрасывает исключение автоматически для корректных HTTP-статусов вроде 404 и 500: проверяйте ответ. Возвращается ответ основного документа, а не результат последующего API товаров. domcontentloaded обозначает событие DOM; готовность данных требует отдельных проверок. Документация не рекомендует networkidle: отсутствие сетевой активности не доказывает полноту данных. Page.goto.

5. Повторяйте запросы по причине ошибки, а не сразу меняйте IP при 429

СимптомЧто выяснить сначалаДействие планировщика
407 или исключение аутентификации проксиИмя, пароль, протокол, состояние тарифаОстановить использование конфигурации, исправить реквизиты
Ошибка CONNECT или тайм-аут соединенияДоступность шлюза, протокол, соединение выхода с цельюДиагностика по уровням; ограниченные повторы временных сбоев
401 / 403Аутентификация цели, правила доступа, содержимое ответаПроверить условия доступа, исключить бесконечные повторы
429Ограничение частоты и его областьРазобрать Retry-After и снизить соответствующую нагрузку
502 / 503 / 504Источник — шлюз или цель; временный ли сбойЗаписать признаки источника, выдержать паузу в пределах бюджета
200 с пропущенными полями или неверным региономСостояние страницы, API, парсер, рынокОшибка содержимого; повтор после исправления

401, 403 и 407 относятся соответственно к аутентификации цели, отказу в обработке и аутентификации прокси. Ошибка создания туннеля может проявиться исключением вместо ответа страницы. Статусы RFC 9110.

RFC 6585 не требует считать запросы только по IP: лимит может зависеть от аккаунта, cookies или ресурса. Смена IP после 429 не обязательно снимает ограничение и не контролирует общую нагрузку системы на цель. RFC 6585, раздел 4.

Retry-After допускает неотрицательное целое число секунд или HTTP-дату. Поддерживайте оба формата; для даты рассчитывайте ожидание относительно текущего UTC и учитывайте расхождение часов. RFC 9110: Retry-After.

Ограниченная политика повторов должна учитывать правила цели и бюджет задачи:

Нет распознаваемого Retry-After: экспоненциальная пауза со случайным разбросом
Retry-After корректен: ждать не меньше указанного и добавить небольшой разброс
Ожидание превышает оставшийся бюджет: перенести или завершить задачу, не сокращая паузу
Достигнут предел попыток: очередь ошибок с сохранением категории сбоя

Объединяйте ограничения как минимум по домену цели; при квотах аккаунта делите его бюджет и между доменами. Воркеры должны разделять состояние ожидания: малая параллельность каждого не исключает превышения общего лимита. Одна навигация создаёт запросы скриптов, изображений и API, поэтому число задач страниц не равно числу HTTP-запросов.

В текущем Scrapy список RetryMiddleware по умолчанию включает 429, но сама возможность повтора не реализует всю политику ожидания сервера. AutoThrottle учитывает задержку и не позволяет быстрым ответам, отличным от 200, уменьшать паузу. Проверяйте поведение на своей конфигурации. RetryMiddleware, AutoThrottle.

6. Измерьте обычную загрузку перед блокировкой ресурсов

Изображения и медиа могут быть не нужны для ваших полей, но блокировка всего, кроме HTML, ломает страницы. Сначала измерьте обычную загрузку, затем экспериментально исключайте подтверждённо ненужные ресурсы. Сравнивайте полноту полей, время задачи и оплачиваемый трафик.

Включение context.route() отключает HTTP-кеш. Запросы, обработанные Service Worker, могут обходить этот перехват. Документация рекомендует рассмотреть service_workers="block", но это меняет поведение зависимых от Service Worker страниц. Если процесс из нескольких страниц раньше использовал кеш повторно, после перехвата измерьте общую стоимость заново. BrowserContext.route.

После завершения запросов используйте request.sizes() для поиска крупных ресурсов. responseBodySize — число байт закодированного тела ответа. Это не сумма в счёте прокси: отдельно проверяйте служебный трафик протоколов, неудачные запросы и границы учёта провайдера. Request.sizes.

len(page.content()) — длина строки отрисованного HTML, а не все сетевые байты и не размер всех ресурсов страницы.

7. Оцените BifrostNetwork на фиксированной выборке

Выберите URL основных шаблонов и рынков. Зафиксируйте версии браузера, окно измерений, число задач, бюджет повторов и правила полей. Размер выборки зависит от разнообразия и изменчивости страниц. Ниже приведён способ оценки, а не гарантии сервиса.

МетрикаКак записыватьНа какой вопрос отвечает
Соответствие выхода и рынкаФактический IP, источник геолокации, страна и валюта страницыДанные относятся к нужному рынку?
Доля корректного содержимогоПринятые задачи ÷ все задачиСколько результатов пригодно помимо HTTP-успеха?
Изменения сессииВыход и состояние сайта в ключевых точкахСохраняются ли условия длинного процесса?
Распределение задержкиP50/P95 успешных задач; ошибки и тайм-ауты отдельноУкладывается ли сбор в срок?
Увеличение работы из-за повторовВсе попытки ÷ задачиСколько работы добавляет нестабильность?
Стоимость 1 000 корректных записейОбщие затраты ÷ принятые записи без дубликатов × 1 000Экономически оправдан ли масштаб?

В общие затраты включайте прокси, вычисления браузера и относимое к задаче сопровождение. При нуле корректных записей удельная стоимость не определена, а испытание не пройдено. Сравнивайте тарифы по одинаковым правилам: лучший запуск не является средним результатом.

В существующий конвейер Playwright BifrostNetwork подключается через proxy. Получите реквизиты в панели, организуйте задачи по стране и сессии из документации и рассчитайте бюджет по текущим ценам и счёту пробного запуска. Статья не заявляет неизмеренную пропускную способность и не приравнивает динамическую резидентную сессию к SLA выделенного статического IP.

Перед запуском проверьте API цели, правила доступа и допустимую частоту. robots.txt задаёт правила для роботов; RFC 9309 прямо говорит, что они не являются разрешением доступа. Пример не загружает и не применяет robots автоматически: это нужно делать при приёме задач. RFC 9309.

Частые вопросы

Почему через прокси США отображается другая валюта?

Проверьте реальный выход, страну доставки, cookies, рынок аккаунта и полученные данные. Геолокация IP — лишь один фактор; учитывайте документированный запасной маршрут BifrostNetwork.

Будет ли стабильнее менять IP для каждого запроса?

В связанной цепочке навигации и XHR смена выхода усложняет диагностику несогласованного состояния. Начните с сессии на задачу; создавайте новый контекст и сессию, когда ротация нужна следующей независимой задаче.

Почему HTTP 200 недостаточно для успеха?

Основной документ может быть пустой оболочкой, API товаров может завершиться ошибкой, а страница — оказаться формой входа. Считайте данные пригодными только после проверки полей, рынка, времени и удаления дубликатов.

Можно ли сразу запустить сотни параллельных задач?

Сначала измерьте ресурсы браузера и нагрузку на цель на одну задачу. Затем добавьте ограниченную очередь, общее состояние ожидания и бюджет ошибок. Параллельность ограничена мощностью системы; увеличение числа воркеров не заменяет допустимую частоту запросов к цели.