Вызывайте solvethree из бэкенда FastAPI
Возвращайте задачу после создания, а не после полного завершения решения. Вызывающий клиент получает ее статус, пока он не станет ready или failed, а затем отправляет токен целевому сайту, если решение завершилось успешно.
На этой странице
Настройте сервер и целевой сайт
Используйте Python 3.10 или более позднюю версию. Установите FastAPI командой python -m pip install "fastapi[standard]", затем установите официальный SDK командой python -m pip install https://solvethree.com/downloads/solvethree_sdk-0.1.0-py3-none-any.whl.
Перед запуском приложения задайте в серверном процессе следующие переменные окружения:
SOLVETHREE_API_KEY: API-ключ вашего рабочего пространства. Храните его на сервере; SDK использует его для аутентификации в solvethree.INTEGRATION_KEY: отдельный секрет, который клиенты отправляют в заголовкеX-Integration-Keyдля аутентификации в ваших маршрутах FastAPI.CAPTCHA_SITE: имя целевого хоста, а не полный URL.SOLVETHREE_PROXY: URL HTTP- или HTTPS-прокси, используемого для этой задачи, без пути, строки запроса и фрагмента.
Перед вызовом маршрута создайте в рабочем пространстве активный профиль для целевого сайта. В примере зафиксировано действие login, поэтому профиль и предполагаемый запрос к целевому сайту должны соответствовать этому сценарию. Передача имени хоста не создает профиль; см. настройку профиля сайта.
Добавьте и запустите маршруты FastAPI
Сохраните этот пример как main.py. Оба маршрута требуют X-Integration-Key. Маршрут создания формирует задачу полностью из серверной конфигурации; клиенты не передают сайт, действие или прокси в теле запроса.
# pip install "fastapi[standard]" and the official solvethree SDK wheel.
import hmac
import os
from fastapi import FastAPI, HTTPException, Request
from fastapi.concurrency import run_in_threadpool
from solvethree import Solvethree, SolvethreeError
app = FastAPI()
def authorize(request):
if not hmac.compare_digest(request.headers.get("x-integration-key", ""), os.environ["INTEGRATION_KEY"]):
raise HTTPException(status_code=401, detail="Unauthorized")
@app.post("/captcha/tasks")
async def create(request: Request):
authorize(request)
task = {"site": os.environ["CAPTCHA_SITE"], "action": "login", "proxy": os.environ["SOLVETHREE_PROXY"]}
if request.headers.get("x-request-id"):
task["requestId"] = request.headers["x-request-id"]
def submit():
return Solvethree(os.environ["SOLVETHREE_API_KEY"]).create_task(task, wait_ms=0, timeout=20)
try:
return await run_in_threadpool(submit)
except ValueError:
raise HTTPException(status_code=400, detail="Invalid task input")
except SolvethreeError as error:
raise HTTPException(status_code=502, detail={"requestId": error.request_id, "taskId": error.task_id})
@app.get("/captcha/tasks/{task_id}")
async def retrieve(task_id: str, request: Request):
authorize(request)
def fetch():
return Solvethree(os.environ["SOLVETHREE_API_KEY"]).get_task(task_id, wait_ms=15000, timeout=25)
try:
return await run_in_threadpool(fetch)
except ValueError:
raise HTTPException(status_code=400, detail="Invalid task ID")
except SolvethreeError as error:
raise HTTPException(status_code=502, detail={"requestId": error.request_id, "taskId": error.task_id})По умолчанию задача использует reCAPTCHA Enterprise v3. Она отправляет site, action и один proxy, без полей type и url.
Python SDK синхронный. Его прямой вызов внутри async def заблокировал бы цикл событий, поэтому оба обработчика используют run_in_threadpool. При создании используется wait_ms=0 с тайм-аутом запроса SDK 20 секунд; при получении допускается ожидание 15 секунд с тайм-аутом запроса SDK 25 секунд. Ни один обработчик не ожидает полного завершения решения через client.solve.
Для локальной разработки выполните fastapi dev main.py из каталога с файлом. Маршруты: POST http://127.0.0.1:8000/captcha/tasks и GET http://127.0.0.1:8000/captcha/tasks/{task_id}. FastAPI обнаруживает объект app; отдельный URLconf регистрировать не нужно.
Создание и получение задачи, восстановление прерванных запросов
- 1.
Создавайте задачу один раз со стабильным ID запроса
Отправьте POST /captcha/tasks с X-Integration-Key и X-Request-ID, который вы сохраните для этой логической задачи. ID запроса должен содержать 1–64 ASCII-буквы, цифры, символы подчеркивания или дефисы. Маршрут передает его в solvethree как requestId. Сохраните возвращенный id задачи.
- 2.
Проверяйте HTTP-статус перед чтением статуса задачи
Обертка возвращает 401 при ошибке аутентификации, 400 при ошибках входных данных ValueError и 502 при перехваченных исключениях SolvethreeError. Поле detail ответа 502 содержит requestId и taskId из ошибки SDK. Обработайте эту HTTP-ошибку, прежде чем рассматривать ответ как задачу.
- 3.
Получение существующей задачи
Вызывайте GET /captcha/tasks/{task_id} с X-Integration-Key. Проверяйте status после каждого успешного HTTP-ответа. Запрос получения может вернуть задачу в незавершенном состоянии даже после окончания ожидания; повторно запросите ту же задачу вместо создания новой.
- 4.
Восстановление создания с неизвестным результатом
Если время ожидания создания истекло и у вас есть ID задачи, запросите ее. В противном случае повторите POST с исходным X-Request-ID и неизменными серверными входными данными задачи. Повторное использование этого ID с той же задачей возвращает существующую задачу; измененные входные данные вызывают конфликт. Храните исходный ID отдельно, не заменяя его значением requestId из ответа с ошибкой.
| Статус задачи | Действие клиента |
|---|---|
| pending или solving | Продолжайте запрашивать ту же задачу. Пригодного для использования решения пока нет. |
| готово | Прочитайте solution и подготовьте запрос к целевому сайту. |
| failed | Прекратите опрос. Проверьте errorCode и error, прежде чем решать, есть ли смысл создавать новую задачу; средства за неудачные решения возвращаются. |
Отправьте токен с исходным прокси и возвращенными идентификационными данными
Эти маршруты возвращают данные задачи; они ничего не отправляют на целевой сайт. Когда status станет ready, компонент, выполняющий запрос к целевому сайту, должен использовать solution.token, а не ID задачи.
Выполняйте отправку через тот же прокси, который использовался при создании задачи, с возвращенными идентификационными данными браузера solution.userAgent и solution.secChUa. Сохраняйте исходную конфигурацию задачи, а не полагайтесь на то, что в текущем окружении по-прежнему указан тот же прокси. Вспомогательная функция SDK successful_proxy(original_task, ready_result) выбирает прокси из этой исходной задачи.
Сохраняйте привязку отправки к нужному целевому сайту и действию. Задача со статусом ready означает, что solvethree сгенерировал решение; только ответ целевого сайта показывает, был ли принят запрос приложения.
Источники и справочник API
Запустите первую задачу.
Начните с $5 на балансе рабочего пространства.