Пропуск всего трафика через один ключ API создает единую точку отказа. Если у ключа заканчивается баланс, достигаются ограничения скорости или он деактивируется, весь ваш конвейер останавливается. Ротация ключей распределяет нагрузку между несколькими ключами и обеспечивает автоматическое переключение при сбое.
Круговая ротация
Самая простая стратегия — равномерно переключать клавиши:
Питон
import itertools
import requests
API_KEYS = [
"KEY_ACCOUNT_1",
"KEY_ACCOUNT_2",
"KEY_ACCOUNT_3",
]
key_cycle = itertools.cycle(API_KEYS)
def get_next_key():
return next(key_cycle)
def solve_captcha(sitekey, page_url):
api_key = get_next_key()
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": "1",
})
data = resp.json()
if data["status"] != 1:
raise Exception(f"[{api_key[:8]}...] {data['request']}")
print(f"Submitted with key {api_key[:8]}...")
return data["request"], api_key
task_id, used_key = solve_captcha("6Le-SITEKEY", "https://example.com")
Взвешенное вращение с осознанием баланса
Направьте больше трафика на ключи с более высоким балансом:
import random
import requests
import threading
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"
class KeyRotator:
def __init__(self, keys):
self.keys = {k: {"balance": 0, "failures": 0, "disabled": False} for k in keys}
self._lock = threading.Lock()
self.refresh_balances()
def refresh_balances(self):
for key in self.keys:
try:
resp = requests.get(RESULT_URL, params={
"key": key, "action": "getbalance", "json": "1"
}, timeout=10).json()
if resp["status"] == 1:
self.keys[key]["balance"] = float(resp["request"])
self.keys[key]["disabled"] = False
else:
self.keys[key]["disabled"] = True
except Exception:
self.keys[key]["disabled"] = True
def get_key(self):
with self._lock:
available = {
k: v for k, v in self.keys.items()
if not v["disabled"] and v["balance"] > 0.01
}
if not available:
raise Exception("No API keys with balance available")
# Weighted random by balance
keys = list(available.keys())
weights = [available[k]["balance"] for k in keys]
return random.choices(keys, weights=weights, k=1)[0]
def report_failure(self, key, error_code):
with self._lock:
self.keys[key]["failures"] += 1
if error_code in ("ERROR_WRONG_USER_KEY", "ERROR_KEY_DOES_NOT_EXIST",
"ERROR_ZERO_BALANCE", "ERROR_IP_NOT_ALLOWED"):
self.keys[key]["disabled"] = True
print(f"[rotator] Disabled key {key[:8]}...: {error_code}")
def report_success(self, key, cost=0.003):
with self._lock:
self.keys[key]["balance"] -= cost
self.keys[key]["failures"] = 0
rotator = KeyRotator(["KEY_1", "KEY_2", "KEY_3"])
# Usage
api_key = rotator.get_key()
# ... solve captcha ...
rotator.report_success(api_key)
Ротация аварийного переключения
Попробуйте следующий ключ, если один не сработает:
Питон
def solve_with_failover(sitekey, page_url, max_attempts=3):
for attempt in range(max_attempts):
api_key = rotator.get_key()
try:
resp = requests.post(SUBMIT_URL, data={
"key": api_key,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": "1",
}, timeout=15)
data = resp.json()
if data["status"] != 1:
rotator.report_failure(api_key, data["request"])
continue
rotator.report_success(api_key)
return data["request"], api_key
except requests.RequestException:
rotator.report_failure(api_key, "NETWORK_ERROR")
continue
raise Exception(f"All {max_attempts} keys failed")
JavaScript
const axios = require('axios');
class KeyRotator {
constructor(keys) {
this.keys = keys.map(k => ({ key: k, disabled: false, failures: 0 }));
this.index = 0;
}
getKey() {
const available = this.keys.filter(k => !k.disabled);
if (available.length === 0) throw new Error('No API keys available');
const entry = available[this.index % available.length];
this.index++;
return entry.key;
}
disable(key, reason) {
const entry = this.keys.find(k => k.key === key);
if (entry) {
entry.disabled = true;
console.log(`[rotator] Disabled ${key.substring(0, 8)}...: ${reason}`);
}
}
}
const rotator = new KeyRotator(['KEY_1', 'KEY_2', 'KEY_3']);
async function solveWithFailover(sitekey, pageurl, maxAttempts = 3) {
for (let i = 0; i < maxAttempts; i++) {
const apiKey = rotator.getKey();
try {
const resp = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: { key: apiKey, method: 'userrecaptcha', googlekey: sitekey, pageurl, json: 1 }
});
if (resp.data.status !== 1) {
rotator.disable(apiKey, resp.data.request);
continue;
}
return { taskId: resp.data.request, apiKey };
} catch (err) {
rotator.disable(apiKey, 'NETWORK_ERROR');
}
}
throw new Error('All keys failed');
}
Загрузка ключей из переменных среды
Никогда не кодируйте ключи API жестко. Загрузка из среды:
import os
API_KEYS = os.environ["CAPTCHAAI_KEYS"].split(",")
# Set: CAPTCHAAI_KEYS=key1,key2,key3
rotator = KeyRotator(API_KEYS)
const API_KEYS = process.env.CAPTCHAAI_KEYS.split(',');
const rotator = new KeyRotator(API_KEYS);
Плановое обновление баланса
Для длительных процессов периодически обновляйте балансы:
import threading
def periodic_refresh(rotator, interval=300):
def refresh():
while True:
rotator.refresh_balances()
for key, info in rotator.keys.items():
print(f" {key[:8]}...: ${info['balance']:.2f} "
f"{'(disabled)' if info['disabled'] else '(active)'}")
threading.Event().wait(interval)
t = threading.Thread(target=refresh, daemon=True)
t.start()
periodic_refresh(rotator, interval=300) # every 5 minutes
Поиск неисправностей
| Проблема | Причина | Исправить |
|---|---|---|
| Все клавиши отключены | Баланс нулевой на всех счетах | Пополните счета, проверьте ERROR_ZERO_BALANCE |
| Всегда использует один и тот же ключ | Индекс циклического анализа не растет | Проверьте безопасность заправки с помощью замка |
| Ключ отключен неправильно | Временная ошибка рассматривается как постоянная | Отключить только на ERROR_WRONG_USER_KEY, ERROR_ZERO_BALANCE, ERROR_IP_NOT_ALLOWED. |
Часто задаваемые вопросы
Сколько ключей API мне следует использовать?
Два ключа обеспечивают базовое аварийное переключение. Три или более клавиш позволяют распределять нагрузку. Для операций большого объема (более 1000 решений/day) рассмотрите возможность использования 3–5 ключей.
Могу ли я использовать ключи от разных аккаунтов CaptchaAI?
Да. Каждый ключ имеет свои ограничения по балансу и ставкам. Ротатор обрабатывает их независимо.
Масштабируйте решение CAPTCHA с помощью вращения нескольких клавиш.
Получите ключ API по адресуcaptchaai.com.
Связанные руководства
- CaptchaAI Белый список IP-адресов и безопасность ключей API
- Защита учетных данных CaptchaAI в переменных среды
- CaptchaAI Проверка баланса и автоматическое пополнение