في تسعٍ من كل عشر حالات، لا تكون المشكلة في محرّك الحل نفسه، بل في الصورة التي وصلته: عنصر CAPTCHA مقتطع جزئيًا، أو ترميز Base64 معطوب، أو لقطة بدقة منخفضة لا تُظهر الأحرف بوضوح. أصلِح ما تُرسله، فتُصلِح الإجابة. يمرّ هذا الدليل بمسار تشخيص مرتّب ثم ستة إصلاحات بأكواد Python تُدرِجها مباشرة في سير عملك مع CaptchaAI.
لماذا تعود إجابة CAPTCHA الصورة خاطئة؟
خمسة أسباب تتكرّر، ولكلٍّ منها إصلاح مباشر:
| السبب | مدى الشيوع | الإصلاح |
|---|---|---|
| اقتصاص عنصر CAPTCHA بشكل ناقص | شائع جدًا | التقط عنصر CAPTCHA كاملاً |
| دقة منخفضة أو ضغط زائد | شائع | أرسل صورة بجودة أعلى |
| ترميز الصورة غير صحيح | شائع | تحقّق من ترميز Base64 |
| غياب تلميح اللغة أو النوع | أحيانًا | أضف language أو textinstructions |
| صورة منتهية الصلاحية | أحيانًا | التقط صورة جديدة قبل الحل مباشرة |
الأسباب الثلاثة الأولى تتعلّق بجودة البيانات الواصلة لا بقدرة الخدمة؛ فالعلاج يبدأ من طرفك.
سيناريو متكرّر من واقع الأتمتة
تخيّل فريق ضمان جودة في القاهرة أو الرياض يؤتمت اختبار نموذج تسجيل يحوي كابتشا صورة نصية. تصل الإجابات «قريبة» — حرف واحد خاطئ في كل مرة. السبب: السكربت يصوّر الصفحة كاملة ثم يقتطع منطقة الكابتشا بإحداثيات ثابتة، فتُزاح بضع بكسلات وتُقتطع حافة الأحرف.
الحل لم يكن تغيير الخدمة، بل التقاط العنصر وحده عبر مُحدِّد CSS كما في الإصلاح 5 أدناه، مع تمرير min_len وmax_len — وهو النمط الأشيع خلف بلاغات «الإجابات الخاطئة».
رتّب تشخيصك قبل تعديل أي كود
قبل تجربة الإصلاحات، احسم مصدر الخطأ في ثلاث خطوات سريعة توفّر عليك وقتًا ورصيدًا:
- احفظ الصورة التي أرسلتها فعليًا إلى الخدمة وافتحها بعينك؛ إن لم تستطع أنت قراءتها بوضوح فلن يقرأها المحرّك.
- اقرأ شكل الإجابة العائدة: حروف عشوائية تشير إلى خطأ ترميز، وإجابة «قريبة» بحرف واحد تشير إلى ضعف الجودة أو اقتطاع الحافة.
- طابِق العَرَض مع جدول التشخيص السريع في نهاية الدليل لتقفز مباشرة إلى الإصلاح المناسب دون تجربة عشوائية.
الإصلاح 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.