عندما يفشل حل اختبار CAPTCHA في الساعة 3 صباحًا، فإن سجلات النص العادي مثل "Error solving captcha" لا تساعد. تتيح لك سجلات JSON المنظمة بمعرفات المهام وأنواع captcha وأوقات الحل وأكواد الأخطاء إمكانية التصفية والبحث والتنبيه بشأن الأخطاء التي حدثت بالضبط.
لماذا التسجيل المنظم
| نص عادي | JSON منظم |
|---|---|
Captcha solved in 12.3s |
{"event":"captcha_solved","task_id":"abc123","type":"recaptcha_v2","solve_time_ms":12300} |
| من الصعب تحليلها | يمكن قراءتها آليًا |
| بحث Grep فقط | تصفية حسب أي حقل |
| لا يوجد ارتباط | روابط معرف المهمة إرسال †’ استطلاع †’ حقن |
بايثون: سجل البنية
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()
تسجيل دورة حياة الحل
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
الإخراج:
{"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: بينو
const pino = require('pino');
const log = pino({
level: 'info',
timestamp: pino.stdTimeFunctions.isoTime,
});
تسجيل دورة حياة الحل
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;
}
مرجع حقول السجل
| الميدان | النوع | الوصف |
|---|---|---|
event |
سلسلة | اسم الحدث: captcha_submitted، captcha_solved، إلخ. |
task_id |
سلسلة | معرف المهمة CaptchaAI للارتباط |
captcha_type |
سلسلة | recaptcha_v2، turnstile، image، إلخ. |
site_url |
سلسلة | عنوان URL للصفحة المستهدفة |
solve_time_ms |
عدد صحيح | إجمالي الوقت من إرسال إلى حلها |
poll_attempts |
عدد صحيح | عدد طلبات الاستطلاع المقدمة |
error |
سلسلة | رمز الخطأ من CaptchaAI |
token_length |
عدد صحيح | طول الرمز المميز الذي تم إرجاعه |
التصفية والتنبيه
البحث عن جميع حالات الفشل في الساعة الماضية
# With jq
cat captcha.log | jq 'select(.level == "error" and .event == "captcha_solve_failed")'
تنبيه بشأن ارتفاع معدل الفشل
# 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),
)
استكشاف الأخطاء وإصلاحها
| مشكلة | السبب | إصلاح |
|---|---|---|
| سجلات مطولة جدا | تسجيل كل محاولة استطلاع | سجل فقط الأحداث التي تم إرسالها وحلها والفاشلة |
| لا يمكن ربط الأحداث | معرف المهمة مفقود | ربط task_id مبكرًا باستخدام log.bind() أو log.child() |
| سجلات غير قابلة للبحث | تنسيق نص عادي | قم بالتبديل إلى JSON باستخدام structlog أو pino |
| البيانات الحساسة في السجلات | تسجيل مفتاح API الكامل | لا تقم مطلقًا بتسجيل مفاتيح واجهة برمجة التطبيقات؛ اقتطاع مفاتيح الموقع |
الأسئلة الشائعة
هل يجب أن أقوم بتسجيل رمز CAPTCHA؟
قم بتسجيل طول الرمز المميز، وليس الرمز المميز الكامل. يمكن أن تتكون الرموز المميزة من أكثر من 500 حرف وتضيف حجم سجل غير ضروري.
ما هو مستوى السجل لـ CAPCHA_NOT_READY؟
لا تقم بتسجيله على الإطلاق، فمن المتوقع أن يتم ذلك أثناء الاقتراع، فقط قم بتسجيل النتيجة النهائية.
أنشئ سير عمل اختبار CAPTCHA يمكن ملاحظته باستخدام CaptchaAI
احصل على مفتاح API الخاص بك علىcaptchaai.com.