استكشاف الأخطاء

حل أخطاء BLS CAPTCHA: من التشخيص إلى الإصلاح

في معظم الحالات لا يعود فشل BLS CAPTCHA إلى الخدمة نفسها، بل إلى تفاصيل صغيرة في طريقة استخراج الصور وتجهيز الطلب قبل إرساله. إذا كنت تبني سكربت أتمتة لحجز موعد تأشيرة عبر مراكز BLS International — وهي شائعة الاستخدام في مصر ودول الخليج لطلبات تأشيرات الدول الأوروبية — فغالباً ما يكون اختبار CAPTCHA هو النقطة التي يتعثر عندها المسار كله. الخبر الجيد أن هذه الأخطاء تتجمّع في أربع فئات فقط: أخطاء الإرسال إلى الـ API، وأخطاء استخراج الصور، وتعارض مؤشرات الحل، وانتهاء المهلة. عالِج الفئة الصحيحة وستحلّ معظم الحالات دفعة واحدة.

يتناول هذا الدليل كل فئة على حدة — العَرَض الظاهر، والسبب الجذري، والإصلاح مع مثال برمجي جاهز. وهذه الفئات الأربع في سطور:

  • أخطاء الإرسال إلى الـ API — يرفض الخادم الطلب قبل أن يحاول حلّه أصلاً.
  • أخطاء استخراج الصور — تصل الصور ناقصة أو تالفة أو بترتيب خاطئ إلى الخدمة.
  • أخطاء تطبيق الحل — تعود النتيجة صحيحة لكن النقر أو إرسال النموذج يخطئ.
  • أخطاء المهلة — ينتهي الرمز قبل أن يكتمل الحل ويُرسل.

لماذا يحتاج BLS CAPTCHA إلى معالجة خاصة

على عكس reCAPTCHA أو Cloudflare Turnstile التي تعتمد على مفتاح موقع (sitekey) ثابت، يستخدم BLS تطبيقاً مخصّصاً يعرض شبكة صور مع تعليمات نصية، ويولّد صوراً فريدة لكل جلسة. هذا يعني أن مهمتك تنقسم إلى جزأين منفصلين: استخراج الصور والتعليمات من الصفحة بدقة، ثم إرسالها إلى CaptchaAI بالمعلمة method=bls. أغلب المشكلات تولد في الجزء الأول — داخل المتصفح — قبل أن يصل الطلب إلى الخدمة أصلاً. لذلك يبدأ التشخيص دائماً بالتأكد من أن ما ترسله يطابق تماماً ما يراه المستخدم على الشاشة. عملياً ينقسم عملك إلى مسارين مستقلين:

  • الاستخراج داخل المتصفح — التقاط الصور ونص التعليمات بدقة تطابق ما يظهر على الشاشة.
  • الإرسال إلى الخدمة — تمرير الحمولة إلى CaptchaAI بالمعلمة method=bls دون تشويه.

عندما تفصل بين المسارين يصبح تحديد مصدر الخطأ أسرع بكثير.


أخطاء الإرسال إلى الـ API

ERROR_BAD_PARAMETERS

  • السبب: معلمة مطلوبة مفقودة — إما نص التعليمات أو الصور نفسها.
  • الإصلاح: أرفق حقل instructions دائماً إلى جانب الصور، فالتعليمات ليست اختيارية في method=bls:
# WRONG — missing instructions
response = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY, "method": "bls",
    "image_base64_1": img1, "json": 1
})

# CORRECT — include instructions
response = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY, "method": "bls",
    "instructions": "Select all images with a car",
    "image_base64_1": img1, "json": 1
})

ERROR_WRONG_FILE_EXTENSION

السبب: بيانات الصورة ليست base64 صالحة أو أنها بتنسيق غير مدعوم.

الإصلاح:

  • تأكد أن الصور بترميز base64 وبتنسيق PNG أو JPEG.
  • احذف البادئة data:image/...;base64, قبل الإرسال.
  • تحقق من أن سلسلة base64 غير مقتطعة.
import base64

# Strip the data URI prefix
src = img_element.get_attribute("src")
if src.startswith("data:image"):
    b64 = src.split(",")[1]
else:
    # Download and encode
    img_data = requests.get(src).content
    b64 = base64.b64encode(img_data).decode()

ERROR_CAPTCHA_UNSOLVABLE

السبب: جودة الصور منخفضة أو غير واضحة، أو أن نص التعليمات غامض.

الإصلاح:

  • التقط الصور بالدقة الكاملة دون تصغير.
  • تأكد من استخراج نص التعليمات بشكل صحيح وكامل.
  • أعد المحاولة — بعض التحديات أصعب بطبيعتها وقد تنجح في المحاولة التالية.

نصيحة: أعد المحاولة مرة أو مرتين فقط قبل تسجيل الحالة كفشل؛ التكرار اللانهائي يستهلك رصيدك دون أن يرفع فرص النجاح.


أخطاء استخراج الصور

هذه أكثر الفئات شيوعاً، لأن تطبيقات BLS تعرض الصور بطرق مختلفة من مركز لآخر.

الصور تُحمَّل ديناميكياً

  • المشكلة: الصور غير موجودة في DOM لحظة تحميل الصفحة أول مرة.
  • الإصلاح: انتظر حتى يُعرض اختبار CAPTCHA بالكامل قبل الاستخراج:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# Wait for captcha images to load
WebDriverWait(driver, 10).until(
    EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".captcha-image img"))
)

الصور معروضة على عناصر canvas لا img

  • المشكلة: بعض تطبيقات BLS ترسم الصور على عناصر <canvas> بدلاً من <img>.
  • الإصلاح: استخرج بيانات اللوحة (canvas) بصيغة base64 مباشرة:
canvas_elements = driver.find_elements(By.CSS_SELECTOR, ".captcha-canvas")
for i, canvas in enumerate(canvas_elements, 1):
    b64 = driver.execute_script(
        "return arguments[0].toDataURL('image/png').split(',')[1];",
        canvas
    )
    payload[f"image_base64_{i}"] = b64

نصيحة: حتى لو ظهرت الصور كعناصر <img> عادية، جرّب مسار الـ canvas أولاً عند مراكز BLS التي تحجب الجلب الخارجي؛ فهو يعمل في الحالتين.

الصور محمية بمنع الربط المباشر (anti-hotlinking)

  • المشكلة: روابط الصور تُرجع الرمز 403 عند جلبها من خارج المتصفح.
  • الإصلاح: استخرج بيانات الصورة من داخل سياق المتصفح نفسه:
# Get image data from within the browser
b64 = driver.execute_script("""
    var img = arguments[0];
    var canvas = document.createElement('canvas');
    canvas.width = img.naturalWidth;
    canvas.height = img.naturalHeight;
    canvas.getContext('2d').drawImage(img, 0, 0);
    return canvas.toDataURL('image/png').split(',')[1];
""", img_element)

أخطاء تطبيق الحل

بعد أن تُرجع CaptchaAI النتيجة، يبقى تطبيقها على الصفحة بشكل صحيح. هنا تكمن أخطاء دقيقة تمرّ دون ملاحظة.

اختيار صور خاطئة

  • السبب: عدم تطابق ترتيب الصور بين لحظة الاستخراج ولحظة العرض.
  • الإصلاح: حافِظ على ترتيب موحّد يطابق ترتيب العرض:
# Ensure images are indexed in display order
captcha_imgs = driver.find_elements(By.CSS_SELECTOR, ".captcha-image img")
# The order of find_elements matches DOM order = display order
for i, img in enumerate(captcha_imgs, 1):
    payload[f"image_base64_{i}"] = extract_base64(img)

تعارض مؤشرات الحل

  • السبب: تُرجع CaptchaAI مؤشرات تبدأ من الرقم 1، بينما يستخدم الكود لديك مصفوفات تبدأ من الصفر.
  • الإصلاح: اطرح 1 قبل الوصول إلى عناصر المصفوفة:
solution = result["request"]  # e.g., "1,3,5"
indices = [int(i) for i in solution.split(",")]

# Convert to 0-based for array access
for idx in indices:
    captcha_imgs[idx - 1].click()  # 1-based → 0-based

نصيحة: خطأ الإزاحة بمقدار واحد (off-by-one) هو أكثر الأخطاء خداعاً هنا، لأن السكربت لا يتعطّل بل ينقر ببساطة على الصورة المجاورة الخاطئة.

فشل إرسال النموذج رغم الاختيار الصحيح

  • السبب: حقول نموذج إضافية أو رموز مخفية لم تُرسَل مع الطلب.
  • الإصلاح: ابحث عن الحقول المخفية التي يجب إرسالها إلى جانب نتيجة CAPTCHA:
# Look for hidden captcha tokens
hidden_fields = driver.find_elements(By.CSS_SELECTOR, "input[type='hidden']")
for field in hidden_fields:
    name = field.get_attribute("name")
    value = field.get_attribute("value")
    print(f"Hidden field: {name}={value}")

أخطاء المهلة وانتهاء الصلاحية

انتهاء صلاحية الرمز قبل اكتمال الحل

المشكلة: لدى BLS CAPTCHA نافذة صلاحية قصيرة، فإذا تأخرت انتهت قبل أن تُرسل النتيجة.

الإصلاح:

  • استخرج الصور وأرسلها إلى CaptchaAI فوراً دون تأخير.
  • لا تستخرج الصور ثم تنتظر قبل الإرسال.
  • إذا تجاوز الحل 60 ثانية، فقد يكون الرمز قد انتهت صلاحيته — حدِّث الصفحة وأعد المحاولة.

الاستطلاع الدوري يستغرق وقتاً طويلاً

  • المشكلة: الاستطلاع دون سقف واضح للمحاولات يعلّق السكربت لدقائق دون نتيجة حاسمة.
  • الإصلاح: استطلِع النتيجة بالنمط الصحيح مع حد أقصى واضح للمحاولات:
# Standard polling pattern
for _ in range(30):  # 30 attempts × 5 seconds = 150 seconds max
    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.get("status") == 1:
        return result["request"]
    if result.get("request") == "ERROR_CAPTCHA_UNSOLVABLE":
        # Don't keep polling — start over
        raise Exception("Unsolvable")

نصيحة: توقّف فوراً عند أول ERROR_CAPTCHA_UNSOLVABLE بدل الاستمرار في الاستطلاع؛ فالرمز غالباً يكون قد انتهت صلاحيته وتحتاج إلى بدء دورة جديدة بصور محدّثة.


قائمة تحقق سريعة قبل التصعيد

قبل أن تفترض وجود مشكلة في الخدمة، راجع هذه النقاط بالترتيب:

النقطة الإجراء
التعليمات مستخرَجة؟ اطبع نص التعليمات وتحقق منه
الصور صالحة؟ احفظ base64 في ملف وافتحه للتأكد
عدد الصور صحيح؟ قارن عدد الصور المرسَلة بالمعروضة
ترتيب الصور صحيح؟ تأكد من تطابق ترتيب DOM مع ترتيب العرض
البادئة Base64 محذوفة؟ أزِل data:image/...;base64,
صيغة الحل مفهومة؟ حلِّل المؤشرات المفصولة بفواصل والبادئة من 1
تحويل المؤشرات؟ اطرح 1 للوصول إلى مصفوفة تبدأ من الصفر

الأسئلة الشائعة

لماذا يختار السكربت صوراً غير التي حدّدتها الخدمة؟

في الغالب بسبب تعارض المؤشرات: تُرجع CaptchaAI مؤشرات تبدأ من 1، فإذا استخدمتها مباشرة على مصفوفة تبدأ من الصفر ستنقر على الصورة التالية لكل مؤشر. اطرح 1 قبل الوصول إلى العنصر، وتأكد أيضاً أن ترتيب الاستخراج يطابق ترتيب العرض.

ما أسرع طريقة لتفادي انتهاء صلاحية رمز BLS أثناء الحل؟

قلّل الفجوة الزمنية بين الاستخراج والإرسال قدر الإمكان: استخرج الصور والتعليمات ثم أرسلها في الطلب نفسه دون خطوات وسيطة. تجنّب أي انتظار أو تحميل صفحات بينهما، وإذا تجاوز الحل 60 ثانية فحدِّث الرمز وابدأ من جديد بدلاً من إرسال نتيجة منتهية.

هل يمكنني إرسال الصور من عنصر canvas مباشرةً؟

نعم. عندما يعرض مركز BLS الصور على <canvas> بدل <img>، استخرج بياناتها بدالة toDataURL ثم أرسلها في حقول image_base64_1 وما بعدها تماماً كأي صورة عادية.

كم عدد الصور التي أرسلها في الطلب الواحد؟

أرسل جميع الصور المعروضة في الاختبار، وعددها عادةً بين 3 و9، عبر الحقول من image_base64_1 حتى image_base64_9. إرسال عدد ناقص أو زائد قد يؤدي إلى نتيجة خاطئة أو خطأ في الإرسال.

هل تختلف خطوات الحل باختلاف مركز BLS أو الدولة؟

منطق الاستخراج قد يختلف قليلاً (img مقابل canvas، أو حماية ضد الربط المباشر)، لكن معلمات CaptchaAI تبقى ثابتة: method=bls مع التعليمات والصور. عند تغيّر تطبيق المركز، عدِّل كود الاستخراج فقط دون المساس بطريقة الإرسال.


أدلة ذات صلة

التعليقات غير مفعّلة لهذا المقال.