CAPTCHA çözümü sabah 3'te başarısız olduğunda "Error solving captcha" gibi düz metin günlükleri yardımcı olmaz. Görev kimlikleri, captcha türleri, çözüm süreleri ve hata kodları içeren yapılandırılmış JSON günlükleri, tam olarak neyin yanlış gittiğini filtrelemenize, aramanıza ve uyarmanıza olanak tanır.
Neden yapılandırılmış günlük kaydı
| Düz metin | Yapılandırılmış JSON |
|---|---|
Captcha solved in 12.3s |
{"event":"captcha_solved","task_id":"abc123","type":"recaptcha_v2","solve_time_ms":12300} |
| Ayrıştırılması zor | Makine tarafından okunabilir |
| Yalnızca Grep araması | Herhangi bir alana göre filtrele |
| Korelasyon yok | Görev Kimliği bağlantıları gönder – anket – enjekte |
Python: yapı günlüğü
import structlog
import time
structlog.configure(
processors=[
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.add_log_level,
structlog.processors.JSONRenderer(),
],
logger_factory=structlog.PrintLoggerFactory(),
)
log = structlog.get_logger()
Çözüm yaşam döngüsünü günlüğe kaydetme
import requests
API_KEY = "YOUR_API_KEY"
def solve_captcha(captcha_type, sitekey, page_url, proxy=None):
solve_log = log.bind(
captcha_type=captcha_type,
site_url=page_url,
sitekey=sitekey[:12] + "...",
)
# Submit
start = time.time()
solve_log.info("captcha_submit_start")
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": API_KEY,
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"json": "1",
}).json()
if resp["status"] != 1:
solve_log.error("captcha_submit_failed", error=resp["request"])
return None
task_id = resp["request"]
submit_ms = int((time.time() - start) * 1000)
solve_log = solve_log.bind(task_id=task_id)
solve_log.info("captcha_submitted", submit_ms=submit_ms)
# Poll
for attempt in range(24):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id, "json": "1"
}).json()
if result["status"] == 1:
solve_ms = int((time.time() - start) * 1000)
solve_log.info(
"captcha_solved",
solve_time_ms=solve_ms,
poll_attempts=attempt + 1,
token_length=len(result["request"]),
)
return result["request"]
if result["request"] != "CAPCHA_NOT_READY":
solve_log.error(
"captcha_solve_failed",
error=result["request"],
poll_attempts=attempt + 1,
)
return None
solve_log.warning("captcha_solve_timeout", poll_attempts=24)
return None
Çıktı:
{"event":"captcha_submit_start","captcha_type":"recaptcha_v2","site_url":"https://example.com","sitekey":"6Le-wvkSAAAA...","timestamp":"2025-07-15T10:30:00Z","level":"info"}
{"event":"captcha_submitted","task_id":"71845302","submit_ms":245,"timestamp":"2025-07-15T10:30:00Z","level":"info"}
{"event":"captcha_solved","task_id":"71845302","solve_time_ms":18230,"poll_attempts":4,"token_length":580,"timestamp":"2025-07-15T10:30:18Z","level":"info"}
Node.js: pino
const pino = require('pino');
const log = pino({
level: 'info',
timestamp: pino.stdTimeFunctions.isoTime,
});
Çözüm yaşam döngüsünü günlüğe kaydetme
const axios = require('axios');
const API_KEY = 'YOUR_API_KEY';
async function solveCaptcha(captchaType, sitekey, pageUrl) {
const taskLog = log.child({
captchaType,
siteUrl: pageUrl,
sitekey: sitekey.substring(0, 12) + '...',
});
const start = Date.now();
taskLog.info('captcha_submit_start');
const submit = await axios.post('https://ocr.captchaai.com/in.php', null, {
params: {
key: API_KEY, method: 'userrecaptcha',
googlekey: sitekey, pageurl: pageUrl, json: 1,
},
});
if (submit.data.status !== 1) {
taskLog.error({ error: submit.data.request }, 'captcha_submit_failed');
return null;
}
const taskId = submit.data.request;
const boundLog = taskLog.child({ taskId });
boundLog.info({ submitMs: Date.now() - start }, 'captcha_submitted');
for (let attempt = 1; attempt <= 24; attempt++) {
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: taskId, json: 1 },
});
if (poll.data.status === 1) {
boundLog.info({
solveTimeMs: Date.now() - start,
pollAttempts: attempt,
tokenLength: poll.data.request.length,
}, 'captcha_solved');
return poll.data.request;
}
if (poll.data.request !== 'CAPCHA_NOT_READY') {
boundLog.error({ error: poll.data.request, pollAttempts: attempt }, 'captcha_solve_failed');
return null;
}
}
boundLog.warn({ pollAttempts: 24 }, 'captcha_solve_timeout');
return null;
}
Günlük alanları referansı
| Alan | Tür | Açıklama |
|---|---|---|
event |
dize | Etkinlik adı: captcha_submitted, captcha_solved, vb. |
task_id |
dize | Korelasyon için CaptchaAI görev kimliği |
captcha_type |
dize | recaptcha_v2, turnstile, image, vb. |
site_url |
dize | Hedef sayfa URL'si |
solve_time_ms |
tamsayı | Gönderimden çözülene kadar geçen toplam süre |
poll_attempts |
tamsayı | Yapılan anket isteği sayısı |
error |
dize | CaptchaAI'den gelen hata kodu |
token_length |
tamsayı | İade edilen jetonun uzunluğu |
Filtreleme ve uyarı
Son saatteki tüm arızaları bulun
# With jq
cat captcha.log | jq 'select(.level == "error" and .event == "captcha_solve_failed")'
Yüksek başarısızlık oranı konusunda uyarı
# Count errors vs successes in a rolling window
from collections import deque
class ErrorRateMonitor:
def __init__(self, window_size=100, threshold=0.2):
self.results = deque(maxlen=window_size)
self.threshold = threshold
def record(self, success):
self.results.append(success)
if len(self.results) >= 50:
error_rate = 1 - sum(self.results) / len(self.results)
if error_rate > self.threshold:
log.warning(
"captcha_error_rate_high",
error_rate=round(error_rate, 3),
window=len(self.results),
)
Sorun giderme
| Sorun | Sebep | Düzeltme |
|---|---|---|
| Günlükler çok ayrıntılı | Her anket girişiminin günlüğe kaydedilmesi | Yalnızca gönderilen, çözülen ve başarısız olan olayları günlüğe kaydet |
| Olaylar ilişkilendirilemiyor | Eksik görev kimliği | task_id'yi log.bind() veya log.child() ile erken bağlayın |
| Günlükler aranamıyor | Düz metin formatı | structlog veya pino ile JSON'a geçin |
| Günlüklerdeki hassas veriler | Tam API anahtarının günlüğe kaydedilmesi | API anahtarlarını hiçbir zaman kaydetmeyin; site anahtarlarını kısalt |
SSS
CAPTCHA jetonunu kaydetmeli miyim?
Tokenın tamamını değil, token uzunluğunu kaydedin. Belirteçler 500'den fazla karakter olabilir ve gereksiz günlük hacmi ekleyebilir.
CAPCHA_NOT_READY için hangi günlük düzeyi?
Hiçbir şekilde kaydetmeyin, oylama sırasında olması beklenir. Yalnızca nihai sonucu kaydedin.
CaptchaAI ile gözlemlenebilir CAPTCHA iş akışları oluşturun
API anahtarınızı şu adresten alın:captchaai.com.