diff --git a/content/.obsidian/workspace-mobile.json b/content/.obsidian/workspace-mobile.json index 46a26cd..df30414 100644 --- a/content/.obsidian/workspace-mobile.json +++ b/content/.obsidian/workspace-mobile.json @@ -4,11 +4,11 @@ "type": "split", "children": [ { - "id": "96157e4ac078880c", + "id": "42735efee397e5a3", "type": "tabs", "children": [ { - "id": "c7f1a1406c49ff51", + "id": "0cf7e4d9ccb89b7b", "type": "leaf", "state": { "type": "empty", @@ -166,8 +166,10 @@ "bases:Создать новую базу": false } }, - "active": "c7f1a1406c49ff51", + "active": "0cf7e4d9ccb89b7b", "lastOpenFiles": [ + "blog/robotex-brouser-automation-api/index.md", + "blog/zero-setup-debian-server/index.md", "blog/hello/index.md", "blog/hello/schema.jpeg", "blog/how-to-make-blog/index.md" diff --git a/content/blog/robotex-brouser-automation-api/index.md b/content/blog/robotex-brouser-automation-api/index.md new file mode 100644 index 0000000..4697431 --- /dev/null +++ b/content/blog/robotex-brouser-automation-api/index.md @@ -0,0 +1,150 @@ +--- +title: Robotex API для Автоматизации Бразуера +date: 2026-10-09T01:59:38+04:00 +draft: false +tags: + - parsing + - anti-bot + - api + - saas +summary: Как боту спарсить сайт за анти-бот защитой или со слжным JS +--- + +Каждый бот под сайт рано или поздно упирается в одну из трех проблем: + +1. капча +2. анти-бот защита +3. сложный JS, который нужно отрендерить, чтобы отправить форму + +Паук, который ходит по сайту сырыми http запросами, тут бессилен. Решение одно - запустить браузер и поручить ему пройти сложный момент. Но и браузер нужно уметь прятать. Под капотом он шлет те же http запросы, что и паук на Python, только делает это из контекста работающего JS. А этот контекст полон маркеров, по которым сайт понимает, что браузером кто-то управляет. + +Под эту задачу я написал микросервис [Robotex](https://git.sokolab.xyz/HumanAutomation/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: + +{ + "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": "......" +} +``` + +Дальше бот ходит по сайту сам, с этими куками, **тем же 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/HumanAutomation/robotex](https://git.sokolab.xyz/HumanAutomation/robotex). Там же в `docs` лежит ТЗ на модуль обхода анти-бот защиты, если интересно, как он устроен изнутри. + +Используйте только на сайтах, где у вас есть на это право. \ No newline at end of file