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.