حالات الاستخدام

حلّ CAPTCHA العربية والنصوص RTL عبر CaptchaAI

يتعامل CaptchaAI مع صورة CAPTCHA المكتوبة بالخط العربي مثل أي صورة أخرى: ترسل الصورة إلى محرّك OCR مع المعامل language=2 لدعم الأحرف غير اللاتينية، ثم تستطلع النتيجة فتحصل على النص جاهزاً للحقن في النموذج. المشكلة الحقيقية لا تكمن في الخدمة نفسها، بل في طبيعة الخط العربي — إذ تتصل الحروف وتتغيّر أشكالها حسب موضعها — وفي تخطيطات صفحات RTL التي تعكس مواضع العناصر مقارنةً بالصفحات اللاتينية. هذا الدليل يوضّح كيف تعالج الجانبين معاً ببضعة أسطر من التعليمات البرمجية في Python وJavaScript.

لماذا يصعب حلّ CAPTCHA العربية تلقائياً

قبل كتابة أي سطر برمجي، يفيدك فهم ما يجعل النص العربي أصعب على أدوات OCR من نظيره اللاتيني. المواقع العربية والفارسية والعبرية تشترك في اتجاه الكتابة من اليمين إلى اليسار، لكن الخط العربي تحديداً يضيف طبقة من التعقيد لأن الحرف الواحد قد يظهر بأربعة أشكال مختلفة. الجدول التالي يلخّص أبرز ما ستواجهه:

التحدي التفاصيل
اتصال الحروف يتغيّر شكل الحرف العربي (أولي أو متوسط أو نهائي أو معزول) حسب موضعه في الكلمة
القراءة من اليمين إلى اليسار يُقرأ نص اختبار CAPTCHA بترتيب معاكس لما تتوقعه أدوات LTR
الاتجاه المختلط تختلط الأرقام والنص اللاتيني مع العربية في سلسلة واحدة ثنائية الاتجاه
علامات التشكيل النقاط والحركات فوق الحروف أو تحتها تفرّق بين حروف متشابهة مثل "شين" و"سين"
تخطيط صفحة RTL تختلف مواضع حقول النموذج وموضع اختبار CAPTCHA عن الصفحات اللاتينية

سيناريو عملي: جمع بيانات من بوابة عربية

تخيّل أنك مسؤول بيانات تجمع إعلانات عقارية عامة من بوابة خليجية تعرض صورة CAPTCHA عربية عند كل عملية بحث. من دون أتمتة، ستُدخل النص يدوياً في كل مرة؛ ومع CaptchaAI تُرسل الصورة برمجياً وتستعيد النص خلال ثوانٍ، فيستمرّ سكربت جمع البيانات دون توقف.

بالنسبة للحجم، خطة BASIC ($15 شهرياً، 5 خيوط) تكفي لمهمة متوسطة تعالج بضع مئات من الطلبات يومياً، لأن كل خيط يقبل عدداً غير محدود من عمليات الحل خلال الشهر ويتحرّر فور انتهاء الطلب الحالي. وإذا زاد التزامن المطلوب، فالانتقال إلى STANDARD ($30 شهرياً، 15 خيطاً) يضاعف الطاقة ثلاث مرات تقريباً دون أي رسوم إضافية لكل عملية حل. هذا النموذج القائم على الخيوط يجعل تكلفة أتمتة موقع عربي متوسط الحجم قابلة للتنبؤ مسبقاً.

حلّ صورة CAPTCHA العربية في Python

الدالة أدناه تقرأ ملف الصورة، تُحوّله إلى Base64، ثم ترسله إلى نقطة النهاية in.php مع language=2، وتستطلع res.php كل خمس ثوانٍ حتى تكتمل النتيجة. لاحظ ترويسة Accept-Language في دالة إرسال النموذج، فهي تجعل الموقع العربي يعيد المحتوى المتوقّع بالترميز الصحيح:

import requests
import base64
import time

API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"


def solve_arabic_captcha(image_path: str) -> str:
    """Solve an Arabic script image CAPTCHA."""
    with open(image_path, "rb") as f:
        image_b64 = base64.b64encode(f.read()).decode()

    resp = requests.post(SUBMIT_URL, data={
        "key": API_KEY,
        "method": "base64",
        "body": image_b64,
        "language": 2,          # Non-Latin character support
        "json": 1,
    }, timeout=30).json()

    if resp.get("status") != 1:
        raise RuntimeError(f"Submit: {resp.get('request')}")

    task_id = resp["request"]
    for _ in range(24):
        time.sleep(5)
        poll = requests.get(RESULT_URL, params={
            "key": API_KEY, "action": "get", "id": task_id, "json": 1,
        }, timeout=15).json()

        if poll.get("request") == "CAPCHA_NOT_READY":
            continue
        if poll.get("status") == 1:
            return poll["request"]
        raise RuntimeError(f"Solve: {poll.get('request')}")

    raise RuntimeError("Timeout")


def solve_arabic_captcha_from_url(session: requests.Session,
                                   captcha_url: str) -> str:
    """Download and solve an Arabic CAPTCHA from a URL."""
    resp = session.get(captcha_url, timeout=15)
    image_b64 = base64.b64encode(resp.content).decode()

    submit = requests.post(SUBMIT_URL, data={
        "key": API_KEY,
        "method": "base64",
        "body": image_b64,
        "language": 2,
        "json": 1,
    }, timeout=30).json()

    if submit.get("status") != 1:
        raise RuntimeError(f"Submit: {submit.get('request')}")

    task_id = submit["request"]
    for _ in range(24):
        time.sleep(5)
        poll = requests.get(RESULT_URL, params={
            "key": API_KEY, "action": "get", "id": task_id, "json": 1,
        }, timeout=15).json()

        if poll.get("request") == "CAPCHA_NOT_READY":
            continue
        if poll.get("status") == 1:
            return poll["request"]
        raise RuntimeError(f"Solve: {poll.get('request')}")

    raise RuntimeError("Timeout")


# --- RTL-aware form submission ---

def submit_form_with_arabic_captcha(
    form_url: str,
    captcha_url: str,
    form_data: dict,
    captcha_field: str = "captcha",
) -> requests.Response:
    """Complete an Arabic website form with CAPTCHA."""
    session = requests.Session()
    session.headers.update({
        "Accept-Language": "ar-SA,ar;q=0.9",
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
    })

    # Load the form page to establish session
    session.get(form_url, timeout=15)

    # Solve the CAPTCHA
    captcha_text = solve_arabic_captcha_from_url(session, captcha_url)
    print(f"Arabic CAPTCHA solved: {captcha_text}")

    # Submit with the solved text
    form_data[captcha_field] = captcha_text
    response = session.post(form_url, data=form_data, timeout=30)

    return response


# --- Usage ---

# Simple Arabic image CAPTCHA
text = solve_arabic_captcha("arabic_captcha.png")
print(f"Arabic text: {text}")

# Form submission on Arabic site
response = submit_form_with_arabic_captcha(
    form_url="https://example.sa/registration",
    captcha_url="https://example.sa/captcha/generate",
    form_data={
        "name": "اسم المستخدم",
        "email": "user@example.com",
    },
)

حقن الرمز في صفحات RTL عبر JavaScript وPlaywright

في المتصفح، الفارق الوحيد الذي يهمّك هو أن تخطيط RTL قد يضع الصورة والحقل في موضع معكوس. الحل هو تحديد العناصر عبر المحدِّدات (selectors) أو المعرّفات بدلاً من الموضع البصري. الدالة solveAndInjectRTL تلتقط رابط الصورة، تحلّها عبر CaptchaAI، ثم تملأ الحقل مباشرة — وحقل الإدخال في صفحة RTL يتكفّل باتجاه النص تلقائياً:

const API_KEY = "YOUR_API_KEY";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";
const fs = require("fs");

async function solveArabicCaptcha(imagePath) {
  const imageB64 = fs.readFileSync(imagePath, "base64");

  const body = new URLSearchParams({
    key: API_KEY,
    method: "base64",
    body: imageB64,
    language: "2",
    json: "1",
  });

  const resp = await (await fetch(SUBMIT_URL, { method: "POST", body })).json();
  if (resp.status !== 1) throw new Error(`Submit: ${resp.request}`);

  const taskId = resp.request;
  for (let i = 0; i < 24; i++) {
    await new Promise((r) => setTimeout(r, 5000));
    const url = `${RESULT_URL}?key=${API_KEY}&action=get&id=${taskId}&json=1`;
    const poll = await (await fetch(url)).json();
    if (poll.request === "CAPCHA_NOT_READY") continue;
    if (poll.status === 1) return poll.request;
    throw new Error(`Solve: ${poll.request}`);
  }
  throw new Error("Timeout");
}

// Inject CAPTCHA token into RTL page with Playwright
async function solveAndInjectRTL(page) {
  // RTL pages may position the CAPTCHA differently
  const captchaImg = await page.locator("img[id*='captcha'], img[class*='captcha']");
  const imgSrc = await captchaImg.getAttribute("src");

  // Download the image
  const buffer = await (await fetch(imgSrc)).arrayBuffer();
  const imageB64 = Buffer.from(buffer).toString("base64");

  // Solve
  const body = new URLSearchParams({
    key: API_KEY, method: "base64", body: imageB64,
    language: "2", json: "1",
  });
  const resp = await (await fetch(SUBMIT_URL, { method: "POST", body })).json();
  if (resp.status !== 1) throw new Error(`Submit: ${resp.request}`);

  const taskId = resp.request;
  for (let i = 0; i < 24; i++) {
    await new Promise((r) => setTimeout(r, 5000));
    const url = `${RESULT_URL}?key=${API_KEY}&action=get&id=${taskId}&json=1`;
    const poll = await (await fetch(url)).json();
    if (poll.request === "CAPCHA_NOT_READY") continue;
    if (poll.status === 1) {
      // Fill the input — RTL input handles text direction automatically
      await page.locator("input[name*='captcha']").fill(poll.request);
      return poll.request;
    }
    throw new Error(`Solve: ${poll.request}`);
  }
}

// Usage
const text = await solveArabicCaptcha("arabic_captcha.png");
console.log(`Arabic text: ${text}`);

أنظمة الكتابة RTL المدعومة

المعامل language=2 لا يقتصر على العربية، بل يغطي عائلة كاملة من الأنظمة الكتابية غير اللاتينية. الجدول التالي يوضّح ما يمكن للمحرّك قراءته:

نظام الكتابة اللغات أمثلة على الأحرف
العربية العربية، الأردية، الباشتو عربي - أبجدية
الفارسية الفارسية فارسی - حروف
العبرية العبرية עברית - אותיות

معالجة النص ثنائي الاتجاه واستكشاف الأخطاء

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

المشكلة السبب الإجراء
نتيجة OCR خاطئة للنص العربي الصورة منخفضة الدقة أو الحروف متشابهة بصرياً أرسل الصورة بدقة أعلى؛ يفيد تكبيرها بمقدار الضعف قبل الإرسال
الكلمات مقلوبة أو ترتيبها خاطئ عدم مراعاة اتجاه النص أثناء تحليل الاستجابة استخدم مكتبة bidi لإعادة ترتيب النص ثنائي الاتجاه قبل حقنه
رفض النموذج للنص الصحيح الموقع يتوقّع أحرفاً بترميز Unicode موحّد طبّع النص عبر unicodedata.normalize('NFC', text) قبل الإرسال
اختلاط الأرقام مع النص العربي خلط ثنائي الاتجاه يشوّش ترتيب الأحرف افصل الأرقام والنص اللاتيني ثم أعد تجميع السلسلة النهائية

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

ما قيمة المعامل language التي أضبطها للنص العربي؟

اضبط language=2 عند إرسال أي صورة تحتوي على أحرف غير لاتينية، بما في ذلك العربية والفارسية والعبرية. هذه القيمة تُفعّل مجموعة الأحرف الموسّعة في محرّك OCR، فلا حاجة لتحديد اللغة بدقة أكبر من ذلك.

لماذا تظهر الأرقام مختلطة مع النص العربي، وكيف أصلح ذلك؟

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

هل أحتاج إلى معالجة الصورة قبل إرسالها لتحسين الدقة؟

ليس دائماً، لكن الصور منخفضة الدقة التي تختفي فيها علامات التشكيل هي أكثر أسباب الأخطاء شيوعاً. إذا لاحظت خلطاً بين حروف متشابهة مثل الباء والتاء، فأرسل نسخة أعلى دقة أو كبّر الصورة قبل ترميزها إلى Base64.

أي خطة CaptchaAI تناسب أتمتة نماذج متوسطة الحجم على موقع عربي؟

للمهام التي تعالج مئات الطلبات يومياً، تكفي خطة BASIC ($15 شهرياً، 5 خيوط) لأن الحل غير محدود لكل خيط. وعند الحاجة إلى تزامن أعلى، تمنحك STANDARD ($30 شهرياً، 15 خيطاً) طاقة أكبر بتكلفة ثابتة قابلة للتنبؤ.

الخطوات التالية

أدلة ذات صلة

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