# 提交-輪詢 API 文檔 ## 概述 本地 Playwright 服務現已支持類似 2captcha 的提交-輪詢 API 模式。 ## API 端點 ### 1. 提交任務 **端點:** `POST /api/v1/captcha/submit` **請求:** ```json { "url": "https://example.com", "sitekey": "0x4AAAAAAAxxxxxx", "timeout": 30000 } ``` **參數:** - `url` (string, 必需) - 包含 Turnstile 的網頁 URL - `sitekey` (string, 必需) - Turnstile sitekey - `timeout` (integer, 可選) - 超時時間(毫秒),默認 30000 **響應 (200 OK):** ```json { "task_id": "550e8400-e29b-41d4-a716-446655440000", "status": "pending", "message": "任務已提交,請輪詢查詢結果" } ``` **示例:** ```bash curl -X POST http://localhost:7860/api/v1/captcha/submit \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com", "sitekey": "0x4AAAAAAAxxxxxx", "timeout": 30000 }' ``` --- ### 2. 查詢結果 **端點:** `GET /api/v1/captcha/result/{task_id}` **參數:** - `task_id` (string, 必需) - 任務 ID **響應 (200 OK):** **待處理狀態:** ```json { "task_id": "550e8400-e29b-41d4-a716-446655440000", "status": "pending", "token": null, "error": null, "created_at": "2024-04-04T20:00:00.000000", "updated_at": "2024-04-04T20:00:00.000000" } ``` **處理中狀態:** ```json { "task_id": "550e8400-e29b-41d4-a716-446655440000", "status": "processing", "token": null, "error": null, "created_at": "2024-04-04T20:00:00.000000", "updated_at": "2024-04-04T20:00:05.000000" } ``` **完成狀態:** ```json { "task_id": "550e8400-e29b-41d4-a716-446655440000", "status": "ready", "token": "0.xxxxxxxxxxxxx", "error": null, "created_at": "2024-04-04T20:00:00.000000", "updated_at": "2024-04-04T20:00:30.000000" } ``` **失敗狀態:** ```json { "task_id": "550e8400-e29b-41d4-a716-446655440000", "status": "failed", "token": null, "error": "無法獲取 Turnstile token", "created_at": "2024-04-04T20:00:00.000000", "updated_at": "2024-04-04T20:00:30.000000" } ``` **示例:** ```bash curl http://localhost:7860/api/v1/captcha/result/550e8400-e29b-41d4-a716-446655440000 ``` --- ### 3. 查詢狀態 **端點:** `GET /api/v1/captcha/status/{task_id}` **參數:** - `task_id` (string, 必需) - 任務 ID **響應 (200 OK):** ```json { "task_id": "550e8400-e29b-41d4-a716-446655440000", "status": "processing", "message": "處理中" } ``` **示例:** ```bash curl http://localhost:7860/api/v1/captcha/status/550e8400-e29b-41d4-a716-446655440000 ``` --- ### 4. 獲取統計信息 **端點:** `GET /api/v1/captcha/stats` **響應 (200 OK):** ```json { "total": 10, "pending": 2, "processing": 1, "ready": 5, "failed": 2 } ``` **示例:** ```bash curl http://localhost:7860/api/v1/captcha/stats ``` --- ### 5. 刪除任務 **端點:** `DELETE /api/v1/captcha/{task_id}` **參數:** - `task_id` (string, 必需) - 任務 ID **響應 (200 OK):** ```json { "success": true, "message": "任務已刪除" } ``` **示例:** ```bash curl -X DELETE http://localhost:7860/api/v1/captcha/550e8400-e29b-41d4-a716-446655440000 ``` --- ## 任務生命週期 ``` 提交 → pending → processing → ready/failed ↓ ↓ submit poll poll poll ↓ 返回 token ``` ### 狀態說明 | 狀態 | 說明 | 可操作 | |------|------|--------| | `pending` | 等待處理 | 輪詢 | | `processing` | 處理中 | 輪詢 | | `ready` | 已完成 | 獲取 token | | `failed` | 已失敗 | 查看錯誤 | --- ## 使用示例 ### Python ```python import requests import time # 1. 提交任務 response = requests.post( 'http://localhost:7860/api/v1/captcha/submit', json={ 'url': 'https://example.com', 'sitekey': '0x4AAAAAAAxxxxxx', 'timeout': 30000 } ) data = response.json() task_id = data['task_id'] print(f"任務已提交: {task_id}") # 2. 輪詢結果 while True: response = requests.get( f'http://localhost:7860/api/v1/captcha/result/{task_id}' ) result = response.json() status = result['status'] print(f"狀態: {status}") if status == 'ready': print(f"Token: {result['token']}") break elif status == 'failed': print(f"錯誤: {result['error']}") break time.sleep(2) # 等待 2 秒後重新輪詢 ``` ### JavaScript ```javascript // 1. 提交任務 const response = await fetch('http://localhost:7860/api/v1/captcha/submit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: 'https://example.com', sitekey: '0x4AAAAAAAxxxxxx', timeout: 30000 }) }); const data = await response.json(); const taskId = data.task_id; console.log(`任務已提交: ${taskId}`); // 2. 輪詢結果 const pollResult = async () => { while (true) { const response = await fetch( `http://localhost:7860/api/v1/captcha/result/${taskId}` ); const result = await response.json(); const status = result.status; console.log(`狀態: ${status}`); if (status === 'ready') { console.log(`Token: ${result.token}`); break; } else if (status === 'failed') { console.log(`錯誤: ${result.error}`); break; } await new Promise(resolve => setTimeout(resolve, 2000)); } }; pollResult(); ``` ### cURL ```bash # 1. 提交任務 TASK_ID=$(curl -s -X POST http://localhost:7860/api/v1/captcha/submit \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com", "sitekey": "0x4AAAAAAAxxxxxx", "timeout": 30000 }' | jq -r '.task_id') echo "任務已提交: $TASK_ID" # 2. 輪詢結果 while true; do RESULT=$(curl -s http://localhost:7860/api/v1/captcha/result/$TASK_ID) STATUS=$(echo $RESULT | jq -r '.status') echo "狀態: $STATUS" if [ "$STATUS" = "ready" ]; then TOKEN=$(echo $RESULT | jq -r '.token') echo "Token: $TOKEN" break elif [ "$STATUS" = "failed" ]; then ERROR=$(echo $RESULT | jq -r '.error') echo "錯誤: $ERROR" break fi sleep 2 done ``` --- ## 最佳實踐 ### 1. 輪詢間隔 建議輪詢間隔: - 第一次:立即查詢 - 後續:每 2-5 秒查詢一次 ```python import time # 指數退避策略 poll_interval = 1 max_interval = 10 while True: result = query_result(task_id) if result['status'] in ['ready', 'failed']: break time.sleep(poll_interval) poll_interval = min(poll_interval * 1.5, max_interval) ``` ### 2. 超時處理 ```python import time start_time = time.time() timeout = 60 # 60 秒超時 while time.time() - start_time < timeout: result = query_result(task_id) if result['status'] in ['ready', 'failed']: return result time.sleep(2) raise TimeoutError("任務超時") ``` ### 3. 錯誤處理 ```python try: # 提交任務 response = requests.post(url, json=payload) response.raise_for_status() task_id = response.json()['task_id'] # 輪詢結果 while True: response = requests.get(f'{url}/{task_id}') response.raise_for_status() result = response.json() if result['status'] == 'ready': return result['token'] elif result['status'] == 'failed': raise Exception(result['error']) time.sleep(2) except requests.RequestException as e: print(f"請求失敗: {e}") except Exception as e: print(f"錯誤: {e}") ``` --- ## 與 2captcha 的相似性 | 功能 | 2captcha | 本地服務 | |------|----------|---------| | 提交任務 | POST /api/captcha | POST /api/v1/captcha/submit | | 查詢結果 | GET /api/result | GET /api/v1/captcha/result/{id} | | 任務 ID | captcha_id | task_id | | 狀態 | 0=pending, 1=ready | pending/processing/ready/failed | | 費用 | 按次計費 | 免費 | --- ## 常見問題 **Q: 任務多久過期?** A: 默認 30 分鐘後自動過期並刪除。 **Q: 可以同時提交多少個任務?** A: 無限制,但受系統資源限制。 **Q: 輪詢頻率有限制嗎?** A: 無限制,但建議每 2-5 秒輪詢一次。 **Q: 任務失敗後可以重新提交嗎?** A: 可以,直接提交新任務即可。 --- ## 支持 - 文檔:查看本文件 - 問題:提交 Issue - 討論:加入社區