← Назад в базу знаний

Парсинг Wildberries через резидентные прокси: как обойти антибот и не получить блокировку по MAC-адресу

Парсинг Wildberries через резидентные прокси: как обойти антибот и не получить блокировку по MAC-адресу

Wildberries — это не просто маркетплейс. Это гигантская распределённая система с собственным антибот-комплексом, который затачивался годами. Каждый день их инженеры выкатывают обновления, и то, что работало вчера, сегодня даёт 403. Разберём, как выглядит реальная схема обхода и почему MAC-адрес тут ни при чём.

Как устроен антибот Wildberries

Снаружи всё выглядит просто: запрос на карточку товара, JSON в ответе. На деле — трёхуровневая система фильтрации.

Первый уровень — классические заголовки. User-Agent, Accept-Language, Sec-Fetch-*. Тут отсеиваются примитивные скрипты и curl без настроек.

Второй уровень — поведенческий анализ. Частота запросов, паттерны переходов, время между действиями. Если вы долбите один и тот же SKU раз в секунду — вас вычислят за пару минут.

Третий уровень — связывание сессий. Тут уже используются отпечатки TLS, HTTP/2 fingerprinting, порядок заголовков. Именно этот уровень ловит большинство парсеров на Python.

Миф о MAC-адресе

Разберём популярное заблуждение. MAC-адрес — это канальный уровень, он не покидает пределы вашей локальной сети. Маршрутизаторы затирают его при каждом хопе. Wildberries физически не может увидеть ваш MAC.

Откуда растут ноги у этого мифа? Люди путают MAC с аппаратным отпечатком браузера. Canvas fingerprint, WebGL, список шрифтов, разрешение экрана — вот что реально собирается. Плюс WebRTC утекает реальный IP, если не отключить.

Реальная схема обхода

Собираем рабочий стек. Прокси-ротация, правильные заголовки, контроль частоты. Без этого любой антибот раскусит вас за пять минут.

```bash

curl -x http://user:pass@proxy.lexic.ml:8080 \

-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" \

-H "Accept: application/json" \

-H "Accept-Language: ru-RU,ru;q=0.9" \

-H "X-Requested-With: XMLHttpRequest" \

"https://www.wildberries.ru/webapi/product/1234567/info"

```

Обратите внимание на порядок заголовков. HTTP/2 не требует строгого порядка, но серверы часто сверяют его с эталонным браузерным. Сбейте порядок — и запрос уйдёт в мусорку.

Почему резидентные прокси работают лучше

Датацентровые IP Wildberries режет на раз. Слишком чистая история, никакого мусора, типичные подсети хостинг-провайдеров. Резидентные адреса выглядят как обычные пользователи: у них есть история, они встречаются в логах рекламных сетей, они живут в реальных подсетях.

Ключевой параметр — время жизни сессии. Один IP на один запрос — это подозрительно. Один IP на десять запросов в течение пяти минут — нормально. Тут помогает липкая сессия: прокси держит один адрес, пока вы не смените его принудительно.

Настройка Python-парсера

Берём aiohttp и настраиваем его под реальную работу. Без синхронных библиотек — только асинхронность, иначе скорость упадёт ниже плинтуса.

```python

import aiohttp

import asyncio

from random import uniform

PROXY = "http://user:pass@proxy.lexic.ml:8080"

HEADERS = {

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",

"Accept": "application/json",

"Accept-Language": "ru-RU,ru;q=0.9",

}

async def fetch_product(session, sku):

url = f"https://www.wildberries.ru/webapi/product/{sku}/info"

async with session.get(url, headers=HEADERS, proxy=PROXY) as resp:

if resp.status == 200:

return await resp.json()

elif resp.status == 403:

await asyncio.sleep(uniform(10, 20))

return None

return None

async def main():

connector = aiohttp.TCPConnector(limit=5, ttl_dns_cache=300)

async with aiohttp.ClientSession(connector=connector) as session:

for sku in range(1000, 1100):

data = await fetch_product(session, sku)

await asyncio.sleep(uniform(1.5, 3.5))

asyncio.run(main())

```

Тут важна задержка между запросами. Плюс-минус случайное значение, а не фиксированная пауза. Ровные интервалы — верный признак бота.

Кейс: 403 на третьем запросе

Сервер на nginx 1.24, парсер на Node.js, прокси — резидентные. Первые два запроса проходят, третий возвращает 403 с телом `{"error":"access denied"}`.

Причина — отсутствие cookie-сессии. Wildberries выдаёт `__wbl` cookie при первом заходе и ждёт её в последующих запросах. Без обработки cookie-заголовков любой антибот зарубит вас на третьем шаге.

Решение — использовать `aiohttp.CookieJar` с сохранением состояния. Первый запрос идёт на главную страницу, получает cookie, затем уже идут запросы к API. Плюс нужно обрабатывать заголовок `Set-Cookie` при каждом ответе.

Кейс: блокировка по отпечатку TLS

Парсер на Python с библиотекой requests. Всё работает неделю, потом разом падает. Wildberries обновил фильтры и начал распознавать отпечаток TLS от OpenSSL.

Решение — использовать curl_cffi или httpx с поддержкой HTTP/2 и настройкой TLS. Библиотека имитирует отпечаток браузера Chrome, и сервер перестаёт отличать вас от настоящего пользователя.

```python

from curl_cffi import requests

session = requests.Session(impersonate="chrome")

resp = session.get(

"https://www.wildberries.ru/webapi/product/1234567/info",

proxies={"https": "http://user:pass@proxy.lexic.ml:8080"}

)

```

Работает, пока Wildberries не обновит свою базу отпечатков. Это гонка вооружений, и выигрывает тот, кто быстрее адаптируется.

Кейс: ротация IP внутри одной сессии

Парсер собирает цены по 10 000 товаров. Скорость — 50 запросов в минуту. Всё летает, но через час прилетает блокировка на 24 часа.

Причина — все запросы шли через один IP. Даже с резидентным адресом такой поток выглядит подозрительно. Нужна ротация: каждые 100-200 запросов менять IP.

```python

from itertools import cycle

PROXIES = [

"http://user:pass@proxy1.lexic.ml:8080",

"http://user:pass@proxy2.lexic.ml:8080",

"http://user:pass@proxy3.lexic.ml:8080",

]

proxy_pool = cycle(PROXIES)

async def fetch_with_rotation(session, sku):

proxy = next(proxy_pool)

url = f"https://www.wildberries.ru/webapi/product/{sku}/info"

async with session.get(url, proxy=proxy) as resp:

return await resp.json()

```

Тут важно не менять IP на каждый запрос. Липкая сессия на 50-100 запросов — оптимальный вариант. Слишком частая смена тоже выглядит неестественно.

Заголовки, которые реально проверяются

Wildberries смотрит не только на стандартный набор. Есть специфические заголовки, которые выдают парсеры с головой.

`X-Client-Name` — должен быть `wbx`, иначе сервер вернёт ошибку. `X-Requested-With` — обязателен для AJAX-запросов. `Origin` — должен совпадать с доменом. Отсутствие любого из них — повод для подозрения.

Плюс проверяется `Accept-Encoding`. Если вы не поддерживаете gzip и brotli — вы бот. Браузеры всегда принимают сжатие, а скрипты часто забывают про этот заголовок.

Что делать при блокировке

Первое — стоп. Не долбите дальше, иначе получите бан по IP-диапазону. Подождите 10-15 минут, смените прокси.

Второе — проверьте cookie. Очистите сессию и начните заново. Часто блокировка цепляется именно к старой куке.

Третье — смените отпечаток TLS. Если используете requests — переходите на curl_cffi. Если уже на нём — попробуйте `impersonate="firefox"` вместо Chrome.

Итоговая схема

Рабочий парсер Wildberries выглядит так: резидентные прокси с липкой сессией, curl_cffi с имитацией Chrome, обработка cookie, случайные задержки 2-5 секунд, ротация IP каждые 100 запросов. Плюс мониторинг кодов ответа — если пошла серия 403, останавливаемся и меняем тактику.

Никакой магии. Только внимательность к деталям и понимание, как работает антибот. Обновляйте подход регулярно — Wildberries не спит, их инженеры тоже читают документацию.

✔️Купить прокси