152 lines
11 KiB
Markdown
152 lines
11 KiB
Markdown
---
|
||
title: Robotex API для Автоматизации Браузера
|
||
date: 2026-10-09T01:59:39+04:00
|
||
draft: false
|
||
tags:
|
||
- parsing
|
||
- anti-bot
|
||
- api
|
||
- saas
|
||
summary: Как боту спарсить сайт за анти-бот защитой или со сложным JS
|
||
aliases:
|
||
- /blog/robotex-brouser-automation-api/
|
||
---
|
||
|
||
Каждый бот под сайт рано или поздно упирается в одну из трех проблем:
|
||
|
||
1. капча
|
||
2. анти-бот защита
|
||
3. сложный JS, который нужно отрендерить, чтобы отправить форму
|
||
|
||
Паук, который ходит по сайту сырыми http запросами, тут бессилен. Решение одно - запустить браузер и поручить ему пройти сложный момент. Но и браузер нужно уметь прятать. Под капотом он шлет те же http запросы, что и паук на Python, только делает это из контекста работающего JS. А этот контекст полон маркеров, по которым сайт понимает, что браузером кто-то управляет.
|
||
|
||
Под эту задачу я написал микросервис [Robotex](https://git.sokolab.xyz/s0k0l/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](https://git.sokolab.xyz/s0k0l/robotex). Там же в `docs` лежит ТЗ на модуль обхода анти-бот защиты, если интересно, как он устроен изнутри.
|
||
|
||
Используйте только на сайтах, где у вас есть на это право. |