Каждый бот под сайт рано или поздно упирается в одну из трех проблем:
- капча
- анти-бот защита
- сложный JS, который нужно отрендерить, чтобы отправить форму
Паук, который ходит по сайту сырыми http запросами, тут бессилен. Решение одно - запустить браузер и поручить ему пройти сложный момент. Но и браузер нужно уметь прятать. Под капотом он шлет те же http запросы, что и паук на Python, только делает это из контекста работающего JS. А этот контекст полон маркеров, по которым сайт понимает, что браузером кто-то управляет.
Под эту задачу я написал микросервис Robotex. Ниже расскажу, как он устроен и зачем он нужен, если уже есть Scrapling и FlareSolverr.
Чем пользовались раньше и сейчас#
Раньше я брал Selenium. Firefox он запускает через geckodriver по протоколу Marionette и заметно палится: navigator.webdriver, следы драйвера в окружении страницы и прочее. Почти все это можно скрыть аддоном, который настраивает контекст страницы до загрузки сайта. Я так и делал, но это постоянная гонка за каждой новой проверкой.
Сейчас появились инструменты, которые решают это на уровне самого браузера:
- Camoufox - сборка Firefox, где отпечатки (экран, шрифты, WebGL, число ядер и т.д.) подменяются в коде движка, а не через JS.
- Patchright - пропатченный Playwright, который убирает утечки CDP, по которым анти-боты узнают автоматизацию Chromium.
Поверх них работает Scrapling. У него есть готовый режим для прохождения анти-бот страниц, и я подсмотрел у него алгоритм. Оказалось, что прохождение Cloudflare это не решение головоломки. Если окружение браузера выглядит по-человечески, а IP нормальный, достаточно дождаться виджета и тыкнуть чекбокс со случайным смещением и задержкой. Вся сложность в том, чтобы правильно определить, что перед тобой проверка, и чтобы к моменту клика браузер уже не вызывал подозрений.
Для небольших объемов без аккаунтов Scrapling хватает. Проблемы начинаются, когда появляются аккаунты. Тогда IP, User-Agent, куки и отпечаток браузера должны быть связаны в один профиль и жить вместе. Сменил прокси, а куки оставил старые - аккаунт улетает в проверку или в бан. Защита начинает задалбывать капчами, аккаунты дохнут.
Что такое Robotex#
Robotex берет на себя всю работу с браузером: проходит анти-бот, выполняет сценарий на странице и отдает боту куки, с которыми тот спокойно ходит по сайту дальше обычными запросами.
От FlareSolverr и Byparr он отличается тем, что те умеют только открыть страницу и получить cf_clearance. Robotex выполняет сценарий: заполнить форму, кликнуть, решить капчу, дождаться элемента. А от Scrapling тем, что это не библиотека внутри вашего процесса, а отдельный сервис. Бот может быть написан на чем угодно, ему нужен только http клиент.
Под капотом FastAPI и настоящий Chrome, которым управляет Patchright. Обертку над браузером я перенес из Scrapling. Начинал я с Camoufox, но в итоге остановился на Chrome.
Как это работает#
Бот отправляет сценарий:
POST /v1/solve
Content-Type: application/json
X-API-Key: <key>
{
"url": "https://example.com/login",
"actions": [
{"type": "fill", "selector": "#email", "value": "user@example.com"},
{"type": "fill", "selector": "#password", "value": "..."},
{"type": "mouse_move", "selector": "#submit"},
{"type": "click", "selector": "#submit"},
{"type": "wait_for", "selector": ".dashboard", "timeout": 30}
],
"proxy": "socks5://user:pass@host:port",
"html": true,
"timeout": 120
}Сценарий заполняет форму входа и ждет, пока загрузится личный кабинет. Кроме этих действий есть submit (клик с ожиданием перехода на новую страницу), delay, inner_html (забрать кусок страницы) и captcha, про нее ниже.
Так как в запросе нет куки session_id, сервис создает новый профиль браузера и возвращает его в заголовке Set-Cookie. Профиль хранится на диске: куки, local storage и отпечаток. Локаль и часовой пояс браузера подбираются по гео прокси, чтобы IP и окружение не противоречили друг другу. Если боту снова нужен браузер, он передает эту куку, и Robotex продолжит работу в том же профиле. Для сайта это все тот же пользователь.
В ответе:
{
"status": "ok",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) ...",
"cookies": [
{"name": "sessionid", "value": "...", "domain": ".example.com", "path": "/"}
],
"actions": [
{"type": "fill", "ok": true},
{"type": "fill", "ok": true},
{"type": "mouse_move", "ok": true},
{"type": "click", "ok": true},
{"type": "wait_for", "ok": true}
],
"html": "<head>...</head><body>...</body>"
}Дальше бот ходит по сайту сам, с этими куками, тем же User-Agent и через тот же прокси. Если какое-то действие упало, status будет err, а в actions видно, на каком шаге и почему.
Капча#
Если на форме ожидается капча, добавляем шаг для нее и ключ сервиса распознавания (сейчас подключен 2captcha):
{
"url": "https://example.com/login",
"actions": [
{"type": "fill", "selector": "#email", "value": "user@example.com"},
{"type": "fill", "selector": "#password", "value": "..."},
{"type": "captcha", "selector": "#captcha", "value": "hcaptcha"},
{"type": "click", "selector": "#submit"},
{"type": "wait_for", "selector": ".dashboard", "timeout": 30}
],
"captcha": "<ключ 2captcha>",
"proxy": "socks5://user:pass@host:port"
}Капча будет решена до клика на submit.
Анти-бот страница#
Анти-бот страница может появиться в любой момент, а может и не появиться. Поэтому это не шаг сценария, а настройка всего запроса:
{
"url": "https://example.com/login",
"actions": [ ... ],
"captcha_type": "cloudflare",
"captcha_detect_locator": "#anti-bot-page-only-id",
"captcha_success_locator": "#site-only-id",
"captcha": "<ключ 2captcha>",
"proxy": "socks5://user:pass@host:port"
}captcha_detect_locator это селектор, который есть только на странице проверки, captcha_success_locator есть только на самом сайте. Сразу после загрузки страницы и до выполнения сценария Robotex проверяет, не стоит ли перед ним преграда. Если стоит, проходит ее сам: ждет, тыкает чекбокс. Если проверка эскалировалась до полноценной капчи с картинками, отправляет ее в сервис распознавания. Если проверка всплыла посреди сценария, для этого есть отдельное действие pass_challenge.
Для тяжелых сайтов есть еще пара полезных опций: disable_resources отключает загрузку картинок и шрифтов, blocked_domains режет запросы к ненужным доменам вроде аналитики, а через cookies можно передать уже готовые куки.
Ограничения#
Серебряной пули тут нет:
- Это ранний MVP. Проверка API ключей, очередь задач и биллинг пока в планах
- браузер ест сотни мегабайт памяти, поэтому на один инстанс сейчас 10 одновременных сессий
- качество прокси решает очень многое, на грязном IP не поможет никакой отпечаток
- Turnstile проходит не на каждом сайте, над стабильностью еще работаю. Анти-боты обновляются, и проход конкретного сайта нужно проверять и поддерживать
Зато бот остается легким: браузер нужен ему только в тех местах, где без него никак, а все остальное время он работает быстрыми http запросами.
Код#
Исходники: git.sokolab.xyz/s0k0l/robotex. Там же в docs лежит ТЗ на модуль обхода анти-бот защиты, если интересно, как он устроен изнутри.
Используйте только на сайтах, где у вас есть на это право.
