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

صورة CAPTCHA تُرجع إجابة خاطئة: تحسين الجودة

في تسعٍ من كل عشر حالات، لا تكون المشكلة في محرّك الحل نفسه، بل في الصورة التي وصلته: عنصر CAPTCHA مقتطع جزئيًا، أو ترميز Base64 معطوب، أو لقطة بدقة منخفضة لا تُظهر الأحرف بوضوح. أصلِح ما تُرسله، فتُصلِح الإجابة. يمرّ هذا الدليل بمسار تشخيص مرتّب ثم ستة إصلاحات بأكواد Python تُدرِجها مباشرة في سير عملك مع CaptchaAI.


لماذا تعود إجابة CAPTCHA الصورة خاطئة؟

خمسة أسباب تتكرّر، ولكلٍّ منها إصلاح مباشر:

السبب مدى الشيوع الإصلاح
اقتصاص عنصر CAPTCHA بشكل ناقص شائع جدًا التقط عنصر CAPTCHA كاملاً
دقة منخفضة أو ضغط زائد شائع أرسل صورة بجودة أعلى
ترميز الصورة غير صحيح شائع تحقّق من ترميز Base64
غياب تلميح اللغة أو النوع أحيانًا أضف language أو textinstructions
صورة منتهية الصلاحية أحيانًا التقط صورة جديدة قبل الحل مباشرة

الأسباب الثلاثة الأولى تتعلّق بجودة البيانات الواصلة لا بقدرة الخدمة؛ فالعلاج يبدأ من طرفك.


سيناريو متكرّر من واقع الأتمتة

تخيّل فريق ضمان جودة في القاهرة أو الرياض يؤتمت اختبار نموذج تسجيل يحوي كابتشا صورة نصية. تصل الإجابات «قريبة» — حرف واحد خاطئ في كل مرة. السبب: السكربت يصوّر الصفحة كاملة ثم يقتطع منطقة الكابتشا بإحداثيات ثابتة، فتُزاح بضع بكسلات وتُقتطع حافة الأحرف.

الحل لم يكن تغيير الخدمة، بل التقاط العنصر وحده عبر مُحدِّد CSS كما في الإصلاح 5 أدناه، مع تمرير min_len وmax_len — وهو النمط الأشيع خلف بلاغات «الإجابات الخاطئة».


رتّب تشخيصك قبل تعديل أي كود

قبل تجربة الإصلاحات، احسم مصدر الخطأ في ثلاث خطوات سريعة توفّر عليك وقتًا ورصيدًا:

  1. احفظ الصورة التي أرسلتها فعليًا إلى الخدمة وافتحها بعينك؛ إن لم تستطع أنت قراءتها بوضوح فلن يقرأها المحرّك.
  2. اقرأ شكل الإجابة العائدة: حروف عشوائية تشير إلى خطأ ترميز، وإجابة «قريبة» بحرف واحد تشير إلى ضعف الجودة أو اقتطاع الحافة.
  3. طابِق العَرَض مع جدول التشخيص السريع في نهاية الدليل لتقفز مباشرة إلى الإصلاح المناسب دون تجربة عشوائية.

الإصلاح 1: افحص جودة الصورة قبل إرسالها

افحص الأبعاد والحجم ونسبة البياض قبل إرسال صورة يتعذّر حلّها. تلتقط الدالة أدناه ثلاث علامات إنذار مبكرة:

  • أبعاد أصغر من الحد الأدنى المقروء.
  • صورة شبه فارغة تجاوز فيها البياض 95%.
  • ملف بالغ الصغر أو بالغ الكبر يشير إلى التقاط معطوب.
import base64
from io import BytesIO
from PIL import Image


def validate_captcha_image(image_path):
    """Check image quality before submitting to CaptchaAI."""
    img = Image.open(image_path)
    width, height = img.size
    issues = []

    # Minimum resolution
    if width < 50 or height < 20:
        issues.append(f"Too small: {width}x{height}px (min 50x20)")

    # Check if mostly blank
    pixels = list(img.getdata())
    if img.mode == "RGB":
        white_count = sum(1 for p in pixels if p[0] > 250 and p[1] > 250 and p[2] > 250)
    else:
        white_count = sum(1 for p in pixels if p > 250)

    blank_ratio = white_count / len(pixels)
    if blank_ratio > 0.95:
        issues.append(f"Image appears blank ({blank_ratio:.0%} white)")

    # File size check
    img_bytes = BytesIO()
    img.save(img_bytes, format="PNG")
    size_kb = img_bytes.tell() / 1024
    if size_kb < 1:
        issues.append(f"File too small ({size_kb:.1f} KB) — may be empty")
    if size_kb > 600:
        issues.append(f"File too large ({size_kb:.0f} KB) — submit under 600 KB")

    return issues


issues = validate_captcha_image("captcha.png")
if issues:
    for issue in issues:
        print(f"WARNING: {issue}")
else:
    print("Image quality OK")

الإصلاح 2: صحّح ترميز Base64 للصورة

أشيع خطأ يُنتج «حروفًا عشوائية» هو ترميز اسم الملف بدل محتواه. تحقّق من الترميز ذهابًا وإيابًا:

import base64


def encode_captcha(image_path):
    """Properly encode a CAPTCHA image to base64."""
    with open(image_path, "rb") as f:
        raw = f.read()

    encoded = base64.b64encode(raw).decode("ascii")

    # Verify round-trip
    decoded = base64.b64decode(encoded)
    assert decoded == raw, "Base64 encoding corrupted the image"

    return encoded


# WRONG — encoding a file path string
bad = base64.b64encode(b"captcha.png").decode()  # Encodes filename, not image!

# CORRECT — encoding file contents
with open("captcha.png", "rb") as f:
    good = base64.b64encode(f.read()).decode()

الإصلاح 3: طبّق معالجة مسبقة لرفع دقة الـ OCR

للصور الصغيرة أو الباهتة فقط: كبّر الأبعاد وزِد التباين واشحذ الحواف. تعمل الدالة أدناه على ثلاث مراحل متتابعة:

  • تكبير أي صورة أقل من 200 بكسل عرضًا حتى يتّسع المحرّك للتفاصيل الدقيقة.
  • رفع التباين لفصل الأحرف عن خلفيتها المشوّشة.
  • شحذ الحواف لإبراز حدود كل حرف قبل الترميز.
from PIL import Image, ImageFilter, ImageEnhance
from io import BytesIO
import base64


def preprocess_captcha(image_path):
    """Improve image quality for better OCR accuracy."""
    img = Image.open(image_path)

    # Convert to RGB if needed
    if img.mode != "RGB":
        img = img.convert("RGB")

    # Upscale small images
    width, height = img.size
    if width < 200:
        scale = 200 / width
        img = img.resize(
            (int(width * scale), int(height * scale)),
            Image.LANCZOS,
        )

    # Increase contrast
    enhancer = ImageEnhance.Contrast(img)
    img = enhancer.enhance(1.5)

    # Sharpen
    img = img.filter(ImageFilter.SHARPEN)

    # Convert to PNG bytes
    buffer = BytesIO()
    img.save(buffer, format="PNG")
    return base64.b64encode(buffer.getvalue()).decode()

الإصلاح 4: مرّر تلميحات النوع واللغة إلى الطلب

إذا عرفت أن الإجابة أرقام فقط أو بطول محدّد، فبلّغ الخدمة عبر المعلمات الاختيارية لتضييق مجال القراءة. أكثرها فائدة:

  • numeric=1 للأرقام فقط، وnumeric=2 للأحرف فقط.
  • min_len وmax_len لتثبيت عدد الأحرف المتوقّع.
  • language لاختيار الأبجدية، وtextinstructions لتعليمات نصية مثل حساسية حالة الأحرف.
import requests


def solve_image(api_key, image_base64, **hints):
    """Submit image CAPTCHA with quality hints."""
    data = {
        "key": api_key,
        "method": "base64",
        "body": image_base64,
        "json": 1,
    }

    # Add optional hints for better accuracy
    if "language" in hints:
        data["language"] = hints["language"]  # 0=default, 1=Cyrillic, 2=Latin
    if "textinstructions" in hints:
        data["textinstructions"] = hints["textinstructions"]
    if "numeric" in hints:
        data["numeric"] = hints["numeric"]  # 1=digits only, 2=letters only
    if "min_len" in hints:
        data["min_len"] = hints["min_len"]
    if "max_len" in hints:
        data["max_len"] = hints["max_len"]

    resp = requests.post("https://ocr.captchaai.com/in.php", data=data, timeout=30)
    return resp.json()


# Example: Digits-only CAPTCHA, 4-6 characters
result = solve_image(
    "YOUR_API_KEY",
    encoded_image,
    numeric=1,
    min_len=4,
    max_len=6,
)

# Example: Case-sensitive text
result = solve_image(
    "YOUR_API_KEY",
    encoded_image,
    textinstructions="Case-sensitive, enter exactly as shown",
)

الإصلاح 5: التقط عنصر CAPTCHA وحده لا الصفحة كاملة

بدل الاقتطاع بإحداثيات ثابتة، صوّر عنصر الكابتشا مباشرة عبر مُحدِّد CSS — هذا وحده يعالج أشيع الأخطاء:

from selenium import webdriver
from selenium.webdriver.common.by import By
import base64


def capture_captcha_element(driver, selector):
    """Screenshot only the CAPTCHA element, not the full page."""
    element = driver.find_element(By.CSS_SELECTOR, selector)

    # Element screenshot (better than page crop)
    png_bytes = element.screenshot_as_png

    # Verify it's not empty
    if len(png_bytes) < 500:
        raise ValueError("Screenshot too small — element may not be visible")

    return base64.b64encode(png_bytes).decode()


# Usage
driver = webdriver.Chrome()
driver.get("https://example.com")
image_b64 = capture_captcha_element(driver, "img#captchaImage")

الإصلاح 6: تعامل مع كابتشا الصور المتغيّرة أو منتهية الصلاحية

بعض كابتشا الصور تنتهي صلاحيته خلال ثوانٍ. التقط الصورة وأرسلها فورًا، ثم استطلع النتيجة على فترات قصيرة:

import time


def solve_with_fresh_image(driver, api_key, captcha_selector):
    """Capture and solve CAPTCHA immediately to avoid expiry."""
    # Wait for CAPTCHA to load fully
    time.sleep(2)

    # Capture fresh
    element = driver.find_element(By.CSS_SELECTOR, captcha_selector)
    png_bytes = element.screenshot_as_png
    body = base64.b64encode(png_bytes).decode()

    # Submit immediately
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": api_key,
        "method": "base64",
        "body": body,
        "json": 1,
    }, timeout=30)
    result = resp.json()

    if result.get("status") != 1:
        raise RuntimeError(result.get("request"))

    task_id = result["request"]

    # Poll — image CAPTCHAs solve fast
    time.sleep(5)
    for _ in range(12):
        resp = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": api_key, "action": "get",
            "id": task_id, "json": 1,
        }, timeout=15)
        data = resp.json()

        if data.get("status") == 1:
            return data["request"]
        if data["request"] != "CAPCHA_NOT_READY":
            raise RuntimeError(data["request"])
        time.sleep(3)

    raise TimeoutError("Image solve timeout")

جدول تشخيص سريع حسب العَرَض

العَرَض التشخيص الإصلاح
الإجابة حروف عشوائية غير مفهومة ترميز Base64 خاطئ تحقّق من الترميز ذهابًا وإيابًا
الإجابة قريبة لكنها خاطئة جودة الصورة منخفضة معالجة مسبقة: تكبير وشحذ وتباين
عدد أحرف الإجابة غير صحيح غياب تلميحات الطول أضف min_len وmax_len
الإجابة تخلط الحروف بالأرقام غياب تلميح النوع أضف numeric=1 أو numeric=2
الإجابة تعود فارغة صورة فارغة أو تالفة تحقّق من الصورة قبل الإرسال
الإجابة صحيحة لكن الموقع يرفضها حساسية حالة الأحرف أضف textinstructions لتحديد الحالة

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

لماذا تعود الإجابة صحيحة تقريبًا مع خطأ في حرف واحد؟

غالبًا لأن الصورة مقتطعة عند الحافة أو منخفضة الدقة، فيقرأ المحرّك معظم الأحرف ويخطئ في أحدها. التقط العنصر كاملاً وثبّت الطول عبر min_len وmax_len.

هل يؤثر تنسيق الصورة على دقة الحل؟

الأهم هو الوضوح لا التنسيق. أرسل PNG غير مضغوط بدقة كافية بدل JPEG شديد الضغط الذي يُضيف تشويشًا حول الأحرف، وتجنّب تكبير صورة صغيرة داخل المتصفح ثم التقاطها.

كيف أتعامل مع كابتشا الصور التي تنتهي صلاحيتها بسرعة؟

لا تحفظها لمعالجتها لاحقًا. التقطها وأرسلها في اللحظة نفسها كما في الإصلاح 6، واستطلع النتيجة على فترات قصيرة لأن كابتشا الصور يُحَلّ سريعًا.

هل يمكنني الإبلاغ عن إجابة خاطئة لاستعادة الرصيد؟

نعم. استخدم نقطة النهاية reportbad مع معرّف المهمة للإبلاغ عن إجابة غير صحيحة؛ فذلك يحسّن الدقة وقد يُعيد رصيدًا لحسابك.

ما الحجم والدقة المناسبان لصورة الكابتشا قبل الإرسال؟

اجعل عرض الصورة 200 بكسل على الأقل وحجمها دون 600 كيلوبايت، وتجنّب الضغط الزائد. تفحص الدالة في الإصلاح 1 هذه الحدود تلقائيًا وتنبّهك قبل أن تستهلك رصيدًا على صورة رديئة.


خلاصة عملية

معظم بلاغات «الإجابة الخاطئة» تُحَلّ من طرفك قبل لمس أي إعداد في الخدمة. راجع هذه القائمة قبل كل إرسال:

  • التقط عنصر الكابتشا وحده لا الصفحة كاملة.
  • تأكّد من ترميز Base64 لمحتوى الملف لا لاسمه.
  • عالِج الصور الباهتة مسبقًا: تكبير وتباين وشحذ.
  • مرّر تلميحات الطول والنوع كلما عرفتها مسبقًا.
  • أرسل الصورة فور التقاطها وتجنّب الصور منتهية الصلاحية.

أدلة ذات صلة


حلّ صور الكابتشا بدقة أعلى — ابدأ مع CaptchaAI.

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