Wenn eine CAPTCHA-Lösung um 3 Uhr morgens fehlschlägt, helfen Klartextprotokolle wie "Error solving captcha" nicht weiter. Mit strukturierten JSON-Protokollen mit Aufgaben-IDs, Captcha-Typen, Lösungszeiten und Fehlercodes können Sie genau filtern, suchen und benachrichtigen, was schief gelaufen ist.
Warum strukturierte Protokollierung?
| Klartext | Strukturiertes JSON |
|---|---|
Captcha solved in 12.3s |
{"event":"captcha_solved","task_id":"abc123","type":"recaptcha_v2","solve_time_ms":12300} |
| Schwer zu analysieren | Maschinenlesbar |
| Nur Grep-Suche | Filtern Sie nach einem beliebigen Feld |
| Keine Korrelation | Aufgaben-ID-Links „Senden“ → „Umfrage“ → „Injizieren“. |
Python: structlog
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()
Protokollierung des Lösungslebenszyklus
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
Ausgabe:
{"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,
});
Protokollierung des Lösungslebenszyklus
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;
}
Referenz zu Protokollfeldern
| Feld | Typ | Beschreibung |
|---|---|---|
event |
Zeichenfolge | Ereignisname: captcha_submitted, captcha_solved usw. |
task_id |
Zeichenfolge | CaptchaAI Aufgaben-ID für die Korrelation |
captcha_type |
Zeichenfolge | recaptcha_v2, turnstile, image usw. |
site_url |
Zeichenfolge | URL der Zielseite |
solve_time_ms |
ganze Zahl | Gesamtzeit von der Übermittlung bis zur Lösung |
poll_attempts |
ganze Zahl | Anzahl der gestellten Umfrageanfragen |
error |
Zeichenfolge | Fehlercode von CaptchaAI |
token_length |
ganze Zahl | Länge des zurückgegebenen Tokens |
Filtern und Alarmieren
Finden Sie alle Fehler der letzten Stunde
# With jq
cat captcha.log | jq 'select(.level == "error" and .event == "captcha_solve_failed")'
Warnung bei hoher Ausfallrate
# 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),
)
Fehlerbehebung
| Problem | Ursache | Lösung |
|---|---|---|
| Protokolle zu ausführlich | Protokollierung jedes Umfrageversuchs | Protokollieren Sie nur Übermittlungs-, gelöste und fehlgeschlagene Ereignisse |
| Ereignisse können nicht korreliert werden | Fehlende Aufgaben-ID | Binden Sie task_id frühzeitig mit log.bind() oder log.child() |
| Protokolle nicht durchsuchbar | Nur-Text-Format | Wechseln Sie mit structlog oder pino zu JSON |
| Sensible Daten in Protokollen | Protokollierung des vollständigen API-Schlüssels | Protokollieren Sie niemals API-Schlüssel; Sitekeys abschneiden |
FAQ
Soll ich das CAPTCHA-Token protokollieren?
Protokollieren Sie die Tokenlänge, nicht das vollständige Token. Token können mehr als 500 Zeichen lang sein und unnötiges Protokollvolumen verursachen.
Welche Protokollebene für CAPCHA_NOT_READY?
Protokollieren Sie es überhaupt nicht – es wird während der Umfrage erwartet. Protokollieren Sie nur das Endergebnis.
Erstellen Sie beobachtbare CAPTCHA-Workflows mit CaptchaAI
Holen Sie sich Ihren API-Schlüssel untercaptchaai.com.
Verwandte Leitfäden
- Speichern von CAPTCHA-Ergebnissen in PostgreSQL
- Erstellen eines CaptchaAI-Nutzungs-Dashboards
- Überwachen der Lösungsraten mit Prometheus und Grafana
Diskussionen (0)
Beteiligen Sie sich an der Unterhaltung
Melden Sie sich an, um Ihre Meinung zu teilen.
AnmeldenNoch keine Kommentare.