- docker-compose: cpus/mem_limit через API_CPUS/API_MEM_LIMIT, прокси gost в профиле loadtest - tests/loadtest.py: параллельные запросы к /v1/solve + пики docker stats - docs/API.md: справочник по запросу, действиям, ответу и сессиям - docs/Deployment.md: результаты замеров и правило подбора BROWSER_SLOTS Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
127 lines
7.5 KiB
Markdown
127 lines
7.5 KiB
Markdown
# API
|
||
|
||
Один эндпоинт: `POST /v1/solve`. Открывает страницу в Chrome через прокси клиента, при необходимости проходит
|
||
антибот (Cloudflare Turnstile, reCAPTCHA), выполняет список действий и возвращает cookies, результаты действий и,
|
||
по запросу, HTML.
|
||
|
||
## Запрос
|
||
|
||
```http
|
||
POST /v1/solve
|
||
Content-Type: application/json
|
||
X-API-Key: <key>
|
||
Cookie: session_id=<id> # необязательно, см. «Сессии»
|
||
|
||
{
|
||
"url": "https://freelancehunt.com/projects",
|
||
"proxy": "http://user:pass@host:port",
|
||
"captcha_type": "cloudflare",
|
||
"actions": [
|
||
{"type": "wait_for", "selector": "a[href*=\"/project/\"]", "timeout": 60}
|
||
],
|
||
"html": true,
|
||
"timeout": 120
|
||
}
|
||
```
|
||
|
||
| Поле | Тип | По умолчанию | Описание |
|
||
|---|---|---|---|
|
||
| `url` | string | — | **обязательно**. Страница, которую открываем |
|
||
| `proxy` | string | — | **обязательно**. `http://`, `https://` или `socks5://` (Chrome не поддерживает socks5 с логином/паролем). По exit-IP прокси выставляются locale и timezone браузера |
|
||
| `actions` | array | — | **обязательно**, может быть пустым. Действия, см. ниже |
|
||
| `captcha_type` | string | `null` | провайдер антибота: `cloudflare` или `recaptcha`. Без него шаг антибота пропускается — для сайтов за Cloudflare обязательно |
|
||
| `captcha` | string | `null` | ключ сервиса распознавания (2captcha), если антибот не проходится без решения капчи |
|
||
| `captcha_detect_locator` | string | `null` | локатор, по которому определяется, что на странице антибот |
|
||
| `captcha_success_locator` | string | `null` | локатор, по которому определяется, что антибот пройден |
|
||
| `html` | bool | `false` | вернуть HTML страницы после выполнения действий |
|
||
| `timeout` | int, с | `60` | таймаут навигации |
|
||
| `user_agent` | string | `null` | свой User-Agent; без него берётся UA установленного Chrome |
|
||
| `cookies` | array | `null` | cookies для установки до навигации, формат Playwright: `{name, value, domain, path, expires, httpOnly, secure, sameSite}` |
|
||
| `disable_resources` | bool | `false` | не грузить картинки, шрифты, медиа |
|
||
| `blocked_domains` | array | `null` | домены, запросы к которым блокируются |
|
||
| `retries` | int | `1` | попыток навигации |
|
||
| `retry_delay` | float, с | `1.0` | пауза между попытками |
|
||
| `wait` | int, мс | `0` | пауза после загрузки страницы |
|
||
| `google_search` | bool | `false` | выставить Referer как переход из поиска Google |
|
||
|
||
### Действия
|
||
|
||
Выполняются по порядку после прохождения антибота. На первой ошибке выполнение останавливается.
|
||
|
||
| `type` | Поля | Что делает |
|
||
|---|---|---|
|
||
| `wait_for` | `selector`, `timeout` (1–7200 с) | ждёт появления элемента; при таймауте — ошибка действия |
|
||
| `click` | `selector` | клик по элементу |
|
||
| `submit` | `selector` | клик и ожидание навигации |
|
||
| `fill` | `selector`, `value` | вставка значения в поле |
|
||
| `mouse_move` | `selector` | наведение курсора на элемент |
|
||
| `delay` | `value` (секунды строкой) | пауза |
|
||
| `inner_html` | `selector` | возвращает HTML элемента в `result` |
|
||
| `captcha` | `selector`, `value` (тип: `cloudflare`, `recaptcha`, `hcaptcha`) | решить капчу внутри страницы через 2captcha, нужен `captcha` |
|
||
| `pass_challenge` | `selector` (локатор успеха, необязательно) | повторно пройти антибот, например после перехода на другую страницу; если не пройден — ошибка действия |
|
||
|
||
## Ответ
|
||
|
||
HTTP-статус всегда `200`, результат — в теле.
|
||
|
||
Успех (антибот пройден, действия выполнены):
|
||
|
||
```json
|
||
{
|
||
"status": "ok",
|
||
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) ... Chrome/155.0.0.0 Safari/537.36",
|
||
"cookies": [{"name": "cf_clearance", "value": "...", "domain": ".freelancehunt.com", "...": "..."}],
|
||
"actions": [
|
||
{"type": "wait_for", "ok": true}
|
||
],
|
||
"html": "<head>...</head><body>...</body>"
|
||
}
|
||
```
|
||
|
||
| Поле | Описание |
|
||
|---|---|
|
||
| `status` | `"ok"` — все действия выполнены, `"err"` — одно из действий упало (выполнение на нём остановлено) |
|
||
| `user_agent` | UA браузера, с которым проходили антибот (нужен клиенту вместе с `cf_clearance`) |
|
||
| `cookies` | все cookies контекста |
|
||
| `actions` | по элементу на выполненное действие: `type`, `ok`, `result` (результат или текст ошибки) |
|
||
| `html` | только при `"html": true` |
|
||
| `error` | при `status: "err"`: `<type>: <текст ошибки>` упавшего действия |
|
||
|
||
Ошибка с упавшим действием:
|
||
|
||
```json
|
||
{
|
||
"status": "err",
|
||
"actions": [{"type": "wait_for", "ok": false, "result": "Page.wait_for_selector: Timeout 3000ms exceeded. ..."}],
|
||
"error": "wait_for: Page.wait_for_selector: Timeout 3000ms exceeded. ..."
|
||
}
|
||
```
|
||
|
||
Ошибка до выполнения действий (навигация, прокси, неизвестный `captcha_type`):
|
||
|
||
```json
|
||
{"status": false, "error": "unknown captcha_type 'datadome', expected one of: recaptcha, cloudflare"}
|
||
```
|
||
|
||
Нет свободных браузеров (лимит `BROWSER_SLOTS`):
|
||
|
||
```json
|
||
{"ok": false, "error": "No slots available"}
|
||
```
|
||
|
||
> Форматы ошибок пока не унифицированы (тех. долг): `status` бывает `"ok"`/`"err"`/`false`, а при занятых слотах
|
||
> поля `status` нет вовсе. Успех — строго `status == "ok"`.
|
||
|
||
## Сессии
|
||
|
||
Ответ ставит cookie `session_id`. Если передать её в следующем запросе, браузер откроется с тем же профилем
|
||
(`extra/user_data_dir/<session_id>`): cookies, localStorage и отпечаток сохраняются, повторно проходить Cloudflare
|
||
обычно не нужно. Без cookie каждый запрос получает новый профиль.
|
||
|
||
Один профиль нельзя использовать в двух запросах одновременно: Chrome заблокирует каталог профиля.
|
||
|
||
## Производительность
|
||
|
||
Каждый запрос запускает отдельный Chrome: около 0,6 ГБ памяти и до 3–4 ядер на пике при прохождении Cloudflare.
|
||
Замеры и рекомендации по лимитам — в [Deployment.md](Deployment.md#нагрузка).
|