CAPTCHA belirteçlerinin süresi doluyor. reCAPTCHA belirteçleri 90-120 saniye sürer, Cloudflare Turnstile belirteçleri ise yaklaşık 300 saniye sürer. Redis'in yerel TTL işlemleri, süresi dolmak üzere olan belirteçleri önbelleğe almak, önceden çözümlenmiş belirteç havuzlarını korumak ve uçuş sırasındaki istekleri tekilleştirmek için onu doğal bir seçim haline getirir.
Redis'te Token Yaşam Döngüsü
Solve Request → Check Redis → Cache Hit?
│ │
│ No │ Yes → Return cached token
▼
CaptchaAI API
│
▼
Store in Redis (TTL = token_lifetime - safety_margin)
│
▼
Return token
Python Uygulaması
Bağlantı ve Yapılandırma
import os
import time
import json
import redis
import requests
r = redis.Redis(
host=os.environ.get("REDIS_HOST", "localhost"),
port=int(os.environ.get("REDIS_PORT", 6379)),
db=0,
decode_responses=True
)
API_KEY = os.environ["CAPTCHAAI_API_KEY"]
# TTLs with safety margin (seconds before actual expiration)
TOKEN_TTLS = {
"recaptcha_v2": 80, # Actual: ~120s, cache for 80s
"recaptcha_v3": 80,
"hcaptcha": 80,
"turnstile": 250, # Actual: ~300s, cache for 250s
}
Token Önbellek İşlemleri
def cache_key(sitekey, pageurl):
"""Generate Redis key for a specific CAPTCHA target."""
return f"captcha:token:{sitekey}:{pageurl}"
def get_cached_token(sitekey, pageurl):
"""Pop a cached token from the queue."""
key = cache_key(sitekey, pageurl)
token = r.lpop(key)
if token:
# Verify TTL still valid on the list
ttl = r.ttl(key)
if ttl > 10: # At least 10 seconds remaining
return token
return None
def cache_token(sitekey, pageurl, token, captcha_type="recaptcha_v2"):
"""Push a solved token to the cache with appropriate TTL."""
key = cache_key(sitekey, pageurl)
ttl = TOKEN_TTLS.get(captcha_type, 80)
r.rpush(key, token)
r.expire(key, ttl)
Önbellek ile çöz
def solve_recaptcha(sitekey, pageurl, captcha_type="recaptcha_v2"):
"""Solve reCAPTCHA with Redis cache check."""
# 1. Check cache
cached = get_cached_token(sitekey, pageurl)
if cached:
return {"solution": cached, "source": "cache"}
# 2. Check if solve is already in progress (dedup)
lock_key = f"captcha:lock:{sitekey}:{pageurl}"
if not r.set(lock_key, "1", nx=True, ex=120):
# Another worker is solving — wait for result
for _ in range(60):
time.sleep(2)
cached = get_cached_token(sitekey, pageurl)
if cached:
return {"solution": cached, "source": "cache_wait"}
return {"error": "TIMEOUT_WAITING_FOR_OTHER_WORKER"}
try:
# 3. Solve via CaptchaAI
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": pageurl,
"json": 1
})
data = resp.json()
if data.get("status") != 1:
return {"error": data.get("request")}
captcha_id = data["request"]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get",
"id": captcha_id, "json": 1
}).json()
if result.get("status") == 1:
token = result["request"]
cache_token(sitekey, pageurl, token, captcha_type)
return {"solution": token, "source": "api"}
if result.get("request") != "CAPCHA_NOT_READY":
return {"error": result.get("request")}
return {"error": "TIMEOUT"}
finally:
r.delete(lock_key)
Token Havuzu (Ön Çözme)
Yüksek verimli hedefler için hazır token havuzunu koruyun:
import threading
class TokenPool:
def __init__(self, sitekey, pageurl, pool_size=5, captcha_type="recaptcha_v2"):
self.sitekey = sitekey
self.pageurl = pageurl
self.pool_size = pool_size
self.captcha_type = captcha_type
self.pool_key = f"captcha:pool:{sitekey}:{pageurl}"
self._running = False
def start(self):
self._running = True
thread = threading.Thread(target=self._refill_loop, daemon=True)
thread.start()
def stop(self):
self._running = False
def _refill_loop(self):
while self._running:
current = r.llen(self.pool_key)
if current < self.pool_size:
self._solve_and_add()
time.sleep(2)
def _solve_and_add(self):
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": self.sitekey,
"pageurl": self.pageurl,
"json": 1
})
data = resp.json()
if data.get("status") != 1:
return
captcha_id = data["request"]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get",
"id": captcha_id, "json": 1
}).json()
if result.get("status") == 1:
ttl = TOKEN_TTLS.get(self.captcha_type, 80)
r.rpush(self.pool_key, result["request"])
r.expire(self.pool_key, ttl)
return
if result.get("request") != "CAPCHA_NOT_READY":
return
def get_token(self):
return r.lpop(self.pool_key)
# Usage
pool = TokenPool("6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", "https://example.com")
pool.start()
# When you need a token:
token = pool.get_token()
JavaScript Uygulaması
const Redis = require("ioredis");
const axios = require("axios");
const redis = new Redis(process.env.REDIS_URL || "redis://localhost:6379");
const API_KEY = process.env.CAPTCHAAI_API_KEY;
const TOKEN_TTLS = { recaptcha_v2: 80, recaptcha_v3: 80, hcaptcha: 80, turnstile: 250 };
function cacheKey(sitekey, pageurl) {
return `captcha:token:${sitekey}:${pageurl}`;
}
async function getCachedToken(sitekey, pageurl) {
const key = cacheKey(sitekey, pageurl);
const token = await redis.lpop(key);
if (token) {
const ttl = await redis.ttl(key);
if (ttl > 10) return token;
}
return null;
}
async function solveWithCache(sitekey, pageurl, type = "recaptcha_v2") {
// Check cache
const cached = await getCachedToken(sitekey, pageurl);
if (cached) return { solution: cached, source: "cache" };
// Dedup lock
const lockKey = `captcha:lock:${sitekey}:${pageurl}`;
const locked = await redis.set(lockKey, "1", "NX", "EX", 120);
if (!locked) {
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 2000));
const waitCached = await getCachedToken(sitekey, pageurl);
if (waitCached) return { solution: waitCached, source: "cache_wait" };
}
return { error: "TIMEOUT_WAITING" };
}
try {
const submit = await axios.post("https://ocr.captchaai.com/in.php", null, {
params: { key: API_KEY, method: "userrecaptcha", googlekey: sitekey, pageurl, json: 1 },
});
if (submit.data.status !== 1) return { error: submit.data.request };
const captchaId = submit.data.request;
for (let i = 0; i < 60; i++) {
await new Promise((r) => setTimeout(r, 5000));
const poll = await axios.get("https://ocr.captchaai.com/res.php", {
params: { key: API_KEY, action: "get", id: captchaId, json: 1 },
});
if (poll.data.status === 1) {
const key = cacheKey(sitekey, pageurl);
const ttl = TOKEN_TTLS[type] || 80;
await redis.rpush(key, poll.data.request);
await redis.expire(key, ttl);
return { solution: poll.data.request, source: "api" };
}
if (poll.data.request !== "CAPCHA_NOT_READY") return { error: poll.data.request };
}
return { error: "TIMEOUT" };
} finally {
await redis.del(lockKey);
}
}
Redis Anahtar Tasarımı
| Anahtar Deseni | Amaç | TTL |
|---|---|---|
captcha:token:{sitekey}:{pageurl} |
Önbelleğe alınmış çözülmüş belirteçler | 80-250 sn (tür başına) |
captcha:lock:{sitekey}:{pageurl} |
Uçuş sırasında çözümler için tekilleştirme kilidi | 120'ler |
captcha:pool:{sitekey}:{pageurl} |
Önceden çözümlenmiş jeton havuzu | 80-250'ler |
captcha:stats:{date} |
Günlük çözüm sayaçları | 7 gün |
Redis Önbellek Performansını İzleme
def cache_stats():
info = r.info("stats")
hits = info.get("keyspace_hits", 0)
misses = info.get("keyspace_misses", 0)
total = hits + misses
return {
"hit_rate": f"{hits / total * 100:.1f}%" if total else "0%",
"hits": hits,
"misses": misses,
"active_keys": r.dbsize()
}
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| Önbelleğe alınmış jeton hedef site tarafından reddedildi | Belirtecin kullanımdan önce süresi doldu | TTL güvenlik marjını azaltın veya jetonları hemen kullanın |
| Kilit hiç açılmadı | Çözüm sırasında işçi kaza yaptı | Kilit anahtarındaki TTL otomatik temizleme (120s) |
| Jeton havuzu her zaman boş | Çözme süresi yeniden doldurma oranını aşıyor | Havuz boyutunu artırın veya daha fazla yeniden doldurma iş parçacığı ekleyin |
| Redis belleği büyüyor | Anahtarlarda TTL yok | Her anahtarın bir TTL'si olmalıdır; redis-cli --bigkeys ile kontrol edin |
SSS
CAPTCHA belirteçlerini önbelleğe almalı mıyım?
Yalnızca aynı site anahtarını hedefleyen yüksek verimli senaryolar için. Tekli çözümler için önbelleğe alma, fayda sağlamadan karmaşıklığı artırır. Bir saniyenin altındaki CAPTCHA yanıtlarına ihtiyaç duyduğunuzda, önceden çözülmüş jeton havuzları parlar.
Doğru TTL güvenlik marjı nedir?
Gerçek jeton ömründen 30-40 saniye çıkarın. reCAPTCHA belirteçleri yaklaşık 120 saniye sürer, yani 80 saniyelik önbelleğe alma. Bu, uygulamanıza belirteci tüketmesi için 40 saniye verir.
Redis önbelleğini birden fazla çalışan arasında paylaşabilir miyim?
Evet - birincil kullanım durumu budur. Tüm çalışanlar aynı önbelleği kontrol eder ve doldurur. Tekilleştirme kilidi, birden fazla çalışanın aynı CAPTCHA'yı aynı anda çözmesini engeller.
Sonraki Adımlar
Redis destekli jeton önbelleğe alma ile CAPTCHA işlem hattınızı hızlandırın -CaptchaAI API anahtarınızı alın.
İlgili kılavuzlar: