kioess / API_POLLING.md
kines9661's picture
Upload 20 files
f301753 verified

提交-輪詢 API 文檔

概述

本地 Playwright 服務現已支持類似 2captcha 的提交-輪詢 API 模式。

API 端點

1. 提交任務

端點: POST /api/v1/captcha/submit

請求:

{
  "url": "https://example.com",
  "sitekey": "0x4AAAAAAAxxxxxx",
  "timeout": 30000
}

參數:

  • url (string, 必需) - 包含 Turnstile 的網頁 URL
  • sitekey (string, 必需) - Turnstile sitekey
  • timeout (integer, 可選) - 超時時間(毫秒),默認 30000

響應 (200 OK):

{
  "task_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "pending",
  "message": "任務已提交,請輪詢查詢結果"
}

示例:

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):

待處理狀態:

{
  "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"
}

處理中狀態:

{
  "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"
}

完成狀態:

{
  "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"
}

失敗狀態:

{
  "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"
}

示例:

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):

{
  "task_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "processing",
  "message": "處理中"
}

示例:

curl http://localhost:7860/api/v1/captcha/status/550e8400-e29b-41d4-a716-446655440000

4. 獲取統計信息

端點: GET /api/v1/captcha/stats

響應 (200 OK):

{
  "total": 10,
  "pending": 2,
  "processing": 1,
  "ready": 5,
  "failed": 2
}

示例:

curl http://localhost:7860/api/v1/captcha/stats

5. 刪除任務

端點: DELETE /api/v1/captcha/{task_id}

參數:

  • task_id (string, 必需) - 任務 ID

響應 (200 OK):

{
  "success": true,
  "message": "任務已刪除"
}

示例:

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

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

// 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

# 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 秒查詢一次
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. 超時處理

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. 錯誤處理

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
  • 討論:加入社區