docs: README и docs приведены к реализации (#50)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
437ea27be7
commit
a399f7f8cc
4 files changed
+130
-81
No files matched your search
+46
-35
@@ -1,8 +1,12 @@
|
||||
# API
|
||||
|
||||
Один эндпоинт: `POST /v1/solve`. Открывает страницу в Chrome через прокси клиента, при необходимости проходит
|
||||
Основной эндпоинт: `POST /v1/solve`. Открывает страницу в Chrome (через прокси клиента, если он задан), при необходимости проходит
|
||||
антибот (Cloudflare Turnstile, reCAPTCHA), выполняет список действий и возвращает cookies, результаты действий и,
|
||||
по запросу, HTML.
|
||||
по запросу, HTML и скриншот.
|
||||
|
||||
`GET /health` (и `GET /`) — `{"status": "ok", "browser_slots": N, "free_slots": M}`.
|
||||
|
||||
> `X-API-Key` пока не проверяется ([#4](https://redmine.sokolab.xyz/issues/4)).
|
||||
|
||||
## Запрос
|
||||
|
||||
@@ -27,15 +31,16 @@ Cookie: session_id=<id> # необязательно, см. «Сесси
|
||||
| Поле | Тип | По умолчанию | Описание |
|
||||
|---|---|---|---|
|
||||
| `url` | string | — | **обязательно**. Страница, которую открываем |
|
||||
| `proxy` | string | — | **обязательно**. `http://`, `https://` или `socks5://` (Chrome не поддерживает socks5 с логином/паролем). По exit-IP прокси выставляются locale и timezone браузера |
|
||||
| `proxy` | string | `null` | `scheme://[user:pass@]host:port`, схема `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 страницы после выполнения действий |
|
||||
| `screenshot` | bool | `false` | вернуть скриншот видимой области (PNG, base64) после действий — в том числе при ошибке действия или антибота |
|
||||
| `timeout` | int, с | `60` | таймаут навигации |
|
||||
| `user_agent` | string | `null` | свой User-Agent; без него берётся UA установленного Chrome |
|
||||
| `user_agent` | string | `null` | свой User-Agent; запоминается в сессии (см. «Сессии»). Без него — UA сессии или UA установленного Chrome |
|
||||
| `cookies` | array | `null` | cookies для установки до навигации, формат Playwright: `{name, value, domain, path, expires, httpOnly, secure, sameSite}` |
|
||||
| `disable_resources` | bool | `false` | не грузить картинки, шрифты, медиа |
|
||||
| `blocked_domains` | array | `null` | домены, запросы к которым блокируются |
|
||||
@@ -46,25 +51,30 @@ Cookie: session_id=<id> # необязательно, см. «Сесси
|
||||
|
||||
### Действия
|
||||
|
||||
Выполняются по порядку после прохождения антибота. На первой ошибке выполнение останавливается.
|
||||
Выполняются по порядку после прохождения антибота. Если антибот не пройден, действия не выполняются
|
||||
(`code: challenge_failed`). На первой ошибке действия выполнение останавливается.
|
||||
|
||||
Обязательные поля проверяются до запуска браузера: неизвестный `type`, нет `selector`/`value`, `captcha` без ключа
|
||||
в запросе, неверный `proxy` — ответ `422` с описанием в `detail` (стандартный формат FastAPI).
|
||||
|
||||
| `type` | Поля | Что делает |
|
||||
|---|---|---|
|
||||
| `wait_for` | `selector`, `timeout` (1–7200 с) | ждёт появления элемента; при таймауте — ошибка действия |
|
||||
| `wait_for` | `selector`, `timeout` (1–7200 с, по умолчанию 30) | ждёт появления элемента; при таймауте — ошибка действия |
|
||||
| `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` |
|
||||
| `mouse_move` | `selector` | наведение курсора на элемент; нет элемента — ошибка `selector not found` |
|
||||
| `delay` | `value` (секунды строкой, 0–600) | пауза |
|
||||
| `inner_html` | `selector` | возвращает HTML элемента в `result`; нет элемента — ошибка `selector not found` |
|
||||
| `captcha` | `selector`, `value` (тип: `cloudflare`, `recaptcha`, `hcaptcha`) | решить капчу внутри страницы через 2captcha, нужен `captcha` в запросе |
|
||||
| `pass_challenge` | `selector` (локатор успеха, необязательно) | повторно пройти антибот, например после перехода на другую страницу; если не пройден — ошибка действия |
|
||||
|
||||
## Ответ
|
||||
|
||||
HTTP-статус всегда `200`, результат — в теле.
|
||||
Формат один для всех случаев: `status` — `"ok"` или `"err"`, при ошибке — `code` и `error`. Поля без значения не
|
||||
возвращаются.
|
||||
|
||||
Успех (антибот пройден, действия выполнены):
|
||||
Успех (антибот пройден, действия выполнены), HTTP `200`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -72,51 +82,52 @@ HTTP-статус всегда `200`, результат — в теле.
|
||||
"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}
|
||||
{"type": "wait_for", "ok": true, "duration_ms": 14}
|
||||
],
|
||||
"html": "<head>...</head><body>...</body>"
|
||||
"html": "<head>...</head><body>...</body>",
|
||||
"duration_ms": 6405
|
||||
}
|
||||
```
|
||||
|
||||
| Поле | Описание |
|
||||
|---|---|
|
||||
| `status` | `"ok"` — все действия выполнены, `"err"` — одно из действий упало (выполнение на нём остановлено) |
|
||||
| `status` | `"ok"` — антибот пройден и все действия выполнены, иначе `"err"` |
|
||||
| `code` | при `"err"`: причина, см. таблицу ниже |
|
||||
| `error` | при `"err"`: текст ошибки; для упавшего действия — `<type>: <текст>` |
|
||||
| `user_agent` | UA браузера, с которым проходили антибот (нужен клиенту вместе с `cf_clearance`) |
|
||||
| `cookies` | все cookies контекста |
|
||||
| `actions` | по элементу на выполненное действие: `type`, `ok`, `result` (результат или текст ошибки) |
|
||||
| `actions` | по элементу на выполненное действие: `type`, `ok`, `result` (результат или текст ошибки), `duration_ms` |
|
||||
| `html` | только при `"html": true` |
|
||||
| `error` | при `status: "err"`: `<type>: <текст ошибки>` упавшего действия |
|
||||
| `screenshot` | только при `"screenshot": true`: PNG в base64 |
|
||||
| `duration_ms` | общее время обработки запроса |
|
||||
|
||||
Ошибка с упавшим действием:
|
||||
| `code` | HTTP | Когда | Что ещё есть в ответе |
|
||||
|---|---|---|---|
|
||||
| `no_slots` | `503` + `Retry-After` | все браузеры заняты (`BROWSER_SLOTS`), запрос не ставится в очередь | — |
|
||||
| `request_failed` | `200` | ошибка до действий: навигация, прокси, неизвестный `captcha_type` | `actions: []` |
|
||||
| `challenge_failed` | `200` | антибот не пройден за отведённое время, действия не выполнялись | cookies, html, screenshot |
|
||||
| `action_failed` | `200` | упало действие, выполнение остановлено на нём | cookies, html, screenshot, `actions` до упавшего включительно |
|
||||
|
||||
Примеры:
|
||||
|
||||
```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. ..."
|
||||
}
|
||||
{"status": "err", "code": "action_failed", "error": "inner_html: selector not found: #missing",
|
||||
"actions": [{"type": "inner_html", "ok": false, "result": "selector not found: #missing", "duration_ms": 26}], "...": "..."}
|
||||
```
|
||||
|
||||
Ошибка до выполнения действий (навигация, прокси, неизвестный `captcha_type`):
|
||||
|
||||
```json
|
||||
{"status": false, "error": "unknown captcha_type 'datadome', expected one of: recaptcha, cloudflare"}
|
||||
{"status": "err", "code": "challenge_failed", "error": "cloudflare not passed: timeout (stage: checkbox)", "actions": [], "...": "..."}
|
||||
```
|
||||
|
||||
Нет свободных браузеров (лимит `BROWSER_SLOTS`):
|
||||
|
||||
```json
|
||||
{"ok": false, "error": "No slots available"}
|
||||
{"status": "err", "code": "no_slots", "error": "No slots available"}
|
||||
```
|
||||
|
||||
> Форматы ошибок пока не унифицированы (тех. долг): `status` бывает `"ok"`/`"err"`/`false`, а при занятых слотах
|
||||
> поля `status` нет вовсе. Успех — строго `status == "ok"`.
|
||||
|
||||
## Сессии
|
||||
|
||||
Ответ ставит cookie `session_id`. Если передать её в следующем запросе, браузер откроется с тем же профилем
|
||||
(`extra/user_data_dir/<session_id>`): cookies, localStorage и отпечаток сохраняются, повторно проходить Cloudflare
|
||||
обычно не нужно. Без cookie каждый запрос получает новый профиль.
|
||||
Ответ ставит cookie `session_id` (UUID). Если передать её в следующем запросе, браузер откроется с тем же профилем
|
||||
(`extra/user_data_dir/<session_id>`): cookies, localStorage, отпечаток и `user_agent` сохраняются, повторно проходить Cloudflare
|
||||
обычно не нужно. Без cookie или с некорректным значением (не UUID) запрос получает новый профиль.
|
||||
|
||||
Один профиль нельзя использовать в двух запросах одновременно: Chrome заблокирует каталог профиля.
|
||||
|
||||
|
||||
Reference in new issue
Block a user