Hướng Dẫn API

Sự xuống cấp một cách duyên dáng khi việc giải CAPTCHA không thành công

Việc giải quyết CAPTCHA có thể không thành công — hết thời gian chờ, tham số sai, số dư bằng 0 hoặc giới hạn tốc độ. Nếu quá trình tự động hóa của bạn gặp sự cố ở lần thất bại đầu tiên, bạn sẽ mất tất cả tiến trình. Sự xuống cấp nhẹ nhàng sẽ giúp quy trình tiếp tục chạy: bỏ qua, thử lại, xếp hàng hoặc quay lại các giải pháp thay thế.


Chế độ lỗi

Thất bại Mã lỗi Chiến lược phục hồi
Hết giờ CAPCHA_NOT_READY (vượt quá số lượt thăm dò) Thử lại với thử thách mới
Thông số xấu ERROR_BAD_PARAMETERS Ghi nhật ký và bỏ qua - sửa lỗi trích xuất
Khóa trang web sai ERROR_WRONG_GOOGLEKEY Trích xuất lại khóa trang web
Số dư bằng không ERROR_ZERO_BALANCE Tạm dừng, cảnh báo, chờ nạp tiền
Tỷ lệ giới hạn ERROR_TOO_MUCH_REQUESTS Lùi lại theo cấp số nhân
API ngừng hoạt động Lỗi kết nối Ngắt mạch + thử lại

Mẫu 1: Bỏ qua và tiếp tục

Đối với các hoạt động hàng loạt trong đó các lỗi riêng lẻ được chấp nhận:

import requests
import time

API_KEY = "YOUR_API_KEY"

def solve_or_skip(captcha_type, sitekey, page_url, max_retries=2):
    """Try to solve; return None on failure instead of crashing."""
    for attempt in range(max_retries):
        try:
            token = solve_captcha(captcha_type, sitekey, page_url)
            if token:
                return token
        except Exception as e:
            print(f"Attempt {attempt + 1} failed: {e}")

    return None  # Skip this item

def process_urls(urls):
    results = []
    skipped = []

    for url in urls:
        sitekey = extract_sitekey(url)
        if not sitekey:
            skipped.append({"url": url, "reason": "no_sitekey"})
            continue

        token = solve_or_skip("recaptcha_v2", sitekey, url)
        if token:
            data = submit_form(url, token)
            results.append({"url": url, "data": data})
        else:
            skipped.append({"url": url, "reason": "solve_failed"})

    print(f"Processed: {len(results)}, Skipped: {len(skipped)}")
    return results, skipped

Mẫu 2: Hàng đợi thử lại

Các tác vụ không thành công sẽ được xếp hàng thử lại để xử lý sau:

from collections import deque
import json

class RetryQueue:
    def __init__(self, max_retries=3, backoff_base=60):
        self.queue = deque()
        self.max_retries = max_retries
        self.backoff_base = backoff_base

    def add(self, task):
        task["retry_count"] = task.get("retry_count", 0) + 1
        if task["retry_count"] <= self.max_retries:
            task["retry_after"] = time.time() + (
                self.backoff_base * task["retry_count"]
            )
            self.queue.append(task)
            return True
        return False  # Exceeded max retries

    def get_ready(self):
        """Get tasks ready for retry."""
        ready = []
        remaining = deque()
        now = time.time()

        while self.queue:
            task = self.queue.popleft()
            if task["retry_after"] <= now:
                ready.append(task)
            else:
                remaining.append(task)

        self.queue = remaining
        return ready

    def save(self, filepath="retry_queue.json"):
        with open(filepath, "w") as f:
            json.dump(list(self.queue), f)

    def load(self, filepath="retry_queue.json"):
        try:
            with open(filepath) as f:
                self.queue = deque(json.load(f))
        except FileNotFoundError:
            pass

# Usage
retry_q = RetryQueue()

def process_with_retry(task):
    try:
        token = solve_captcha(task["type"], task["sitekey"], task["url"])
        if token:
            return submit_form(task["url"], token)
        else:
            retry_q.add(task)
    except Exception:
        retry_q.add(task)

# Process retry queue periodically
def drain_retry_queue():
    ready = retry_q.get_ready()
    for task in ready:
        process_with_retry(task)

Mẫu 3: Chế độ xuống cấp

Khi dịch vụ giải quyết không khả dụng, hãy chuyển sang chế độ giới hạn:

class CaptchaSolver:
    def __init__(self, api_key):
        self.api_key = api_key
        self.degraded = False
        self.failure_count = 0
        self.failure_threshold = 5
        self.recovery_time = None

    def solve(self, captcha_type, sitekey, page_url):
        if self.degraded:
            if time.time() < self.recovery_time:
                return self._degraded_action(page_url)
            else:
                self.degraded = False
                self.failure_count = 0

        try:
            token = self._solve_api(captcha_type, sitekey, page_url)
            self.failure_count = 0
            return token
        except Exception as e:
            self.failure_count += 1
            if self.failure_count >= self.failure_threshold:
                self._enter_degraded_mode()
            raise

    def _enter_degraded_mode(self):
        self.degraded = True
        self.recovery_time = time.time() + 300  # 5 min
        print("Entering degraded mode for 5 minutes")
        # Send alert

    def _degraded_action(self, url):
        """What to do when solving is unavailable."""
        # Option A: Skip CAPTCHA pages entirely
        return None

        # Option B: Queue for later
        # retry_queue.add({"url": url, ...})
        # return None

        # Option C: Try alternative solver
        # return self._solve_with_backup_api(...)

    def _solve_api(self, captcha_type, sitekey, page_url):
        # Normal CaptchaAI API call
        resp = requests.post("https://ocr.captchaai.com/in.php", data={
            "key": self.api_key,
            "method": "userrecaptcha",
            "googlekey": sitekey,
            "pageurl": page_url,
            "json": "1",
        }).json()

        if resp["status"] != 1:
            raise Exception(resp["request"])

        task_id = resp["request"]
        for _ in range(24):
            time.sleep(5)
            result = requests.get("https://ocr.captchaai.com/res.php", params={
                "key": self.api_key, "action": "get",
                "id": task_id, "json": "1"
            }).json()
            if result["status"] == 1:
                return result["request"]
            if result["request"] != "CAPCHA_NOT_READY":
                raise Exception(result["request"])

        raise Exception("TIMEOUT")

Node.js: Mẫu kết hợp

class ResilientSolver {
  constructor(apiKey) {
    this.apiKey = apiKey;
    this.retryQueue = [];
    this.failureCount = 0;
    this.degraded = false;
  }

  async solve(type, sitekey, pageUrl) {
    if (this.degraded) {
      this.retryQueue.push({ type, sitekey, pageUrl, addedAt: Date.now() });
      return null;
    }

    try {
      const token = await this._callApi(type, sitekey, pageUrl);
      this.failureCount = 0;
      return token;
    } catch (err) {
      this.failureCount++;

      if (err.message === 'ERROR_ZERO_BALANCE') {
        this._enterDegraded(600000); // 10 min
        return null;
      }

      if (this.failureCount >= 5) {
        this._enterDegraded(300000); // 5 min
      }

      this.retryQueue.push({ type, sitekey, pageUrl, addedAt: Date.now() });
      return null;
    }
  }

  _enterDegraded(durationMs) {
    this.degraded = true;
    console.warn(`Degraded mode for ${durationMs / 1000}s`);
    setTimeout(() => {
      this.degraded = false;
      this.failureCount = 0;
      this.drainRetryQueue();
    }, durationMs);
  }

  async drainRetryQueue() {
    const tasks = this.retryQueue.splice(0);
    for (const task of tasks) {
      await this.solve(task.type, task.sitekey, task.pageUrl);
    }
  }

  async _callApi(type, sitekey, pageUrl) {
    // Standard submit + poll
    const axios = require('axios');
    const submit = await axios.post('https://ocr.captchaai.com/in.php', null, {
      params: { key: this.apiKey, method: 'userrecaptcha', googlekey: sitekey, pageurl: pageUrl, json: 1 },
    });
    if (submit.data.status !== 1) throw new Error(submit.data.request);

    const taskId = submit.data.request;
    for (let i = 0; i < 24; i++) {
      await new Promise(r => setTimeout(r, 5000));
      const poll = await axios.get('https://ocr.captchaai.com/res.php', {
        params: { key: this.apiKey, action: 'get', id: taskId, json: 1 },
      });
      if (poll.data.status === 1) return poll.data.request;
      if (poll.data.request !== 'CAPCHA_NOT_READY') throw new Error(poll.data.request);
    }
    throw new Error('TIMEOUT');
  }
}

Thử lại ma trận quyết định

  • Chỉ thử lại khi lỗi có vẻ thoáng qua và trạng thái phiên xung quanh vẫn hợp lệ.
  • Thực hiện lại bước khi yêu cầu có thể được xây dựng lại một cách xác định mà không lặp lại hành động của người dùng.
  • Bỏ qua hoặc tạm dừng quy trình làm việc khi những nỗ lực tiếp theo sẽ chỉ lãng phí sự cân bằng hoặc tăng rủi ro bị phát hiện.

Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
Tất cả nhiệm vụ bị bỏ qua Chế độ xuống cấp được kích hoạt quá mạnh mẽ Tăng ngưỡng thất bại
Hàng đợi thử lại tăng lên mãi mãi Nhiệm vụ không bao giờ thành công Đặt số lần thử tối đa; di chuyển đến hàng đợi thư chết
Phục hồi quá chậm Thời gian chờ xuống cấp dài Giảm thời gian phục hồi; thêm đầu dò kiểm tra sức khỏe
Mất nhiệm vụ xếp hàng khi khởi động lại Hàng đợi trong bộ nhớ Kiên trì xếp hàng vào tập tin hoặc cơ sở dữ liệu

Câu hỏi thường gặp

Sự khác biệt giữa suy thoái duyên dáng và bộ ngắt mạch là gì?

Bộ ngắt mạch ngăn chặn hoàn toàn các cuộc gọi khi phát hiện lỗi. Sự xuống cấp một cách duyên dáng có phạm vi rộng hơn — nó bao gồm các hành vi dự phòng, bỏ qua logic và các quy trình công việc thay thế. Chúng phối hợp tốt với nhau.

Tôi có nên luôn thử lại các tác vụ thất bại không?

Không dành cho ERROR_BAD_PARAMETERS hoặc ERROR_WRONG_GOOGLEKEY — những thứ đó sẽ không thành công khi thử lại. Chỉ thử lại các lỗi nhất thời như thời gian chờ và giới hạn tốc độ.


Xây dựng tính năng tự động hóa CAPTCHA linh hoạt với CaptchaAI

Nhận khóa API của bạn tạicaptchaai.com.


Hướng dẫn liên quan

Os comentários estão desativados para este artigo.