الدروس التطبيقية

كيف تعالج 10 آلاف اختبار CAPTCHA في الساعة باستخدام CaptchaAI

العائق أمام معالجة 10 آلاف اختبار CAPTCHA في الساعة ليس سرعة الخدمة، بل عدد العمليات التي تُبقيها قيد التنفيذ في وقت واحد. فإذا انتظرت انتهاء كل حل قبل إرسال الطلب التالي، فلن تتجاوز بضع مئات في الساعة مهما كانت الخدمة سريعة. المفتاح هو التزامن: أرسِل عشرات الطلبات وتراكبها بحيث يكتمل ما يكفي منها داخل النافذة الزمنية نفسها.

في هذا الدليل نحسب أولًا عدد العمليات المتزامنة التي تحتاجها فعليًا، ثم نبني خط معالجة كاملًا بـ Python وNode.js عبر CaptchaAI، ثم نربطه بعدد الـ Threads في خطتك، ونضبط المعاملات للوصول إلى الهدف بثبات.

الحسبة السريعة: كم عملية متزامنة تحتاج؟

لنفترض أن حلّ reCAPTCHA v2 واحد يستغرق نحو 15 ثانية في المتوسط. عند المعالجة التسلسلية — طلب واحد في كل مرة — تكون النتيجة:

  • تسلسليًا: 3600 ثانية ÷ 15 ثانية = 240 حلًا في الساعة
  • للوصول إلى 10,000 في الساعة: عليك إبقاء ~42 عملية متزامنة قيد التنفيذ في كل لحظة

بعبارة أخرى، أنت لا تطلب من CaptchaAI أن يكون أسرع؛ بل تُراكب طلبات كافية بحيث يكتمل 42 حلًا خلال نفس نافذة الـ 15 ثانية. هذا الرقم — نحو 42 عملية متزامنة — هو حجر الأساس الذي تُبنى عليه بقية القرارات، من عدد الـ Threads إلى قيم الضبط.

بنية خط المعالجة عالي الإنتاجية

┌──────────┐     ┌────────────┐     ┌─────────────┐     ┌──────────┐
│  Task     │────▶│  Submit    │────▶│  CaptchaAI  │────▶│  Result  │
│  Queue    │     │  Workers   │     │  API        │     │  Store   │
│  (Redis)  │     │  (async)   │     │             │     │  (DB)    │
└──────────┘     └────────────┘     └─────────────┘     └──────────┘
                       │                    ▲
                       │    ┌──────────┐    │
                       └───▶│  Poll    │────┘
                            │  Workers │
                            └──────────┘

يتكوّن الخط من أربعة أجزاء تعمل بالتوازي:

  1. قائمة انتظار المهام — تخزّن مهام CAPTCHA المعلّقة مع مفتاح الموقع (sitekey) وعنوان الصفحة
  2. عمّال الإرسال — يرسلون المهام إلى CaptchaAI API بشكل غير متزامن دون انتظار
  3. عمّال الاستطلاع — يفحصون النتائج على فترات محسّنة إلى أن يجهز الرمز
  4. مخزن النتائج — يحفظ الرموز المحلولة فور وصولها لتستخدمها بقية سير العمل

كم Thread تحتاج؟ اربط التزامن بخطتك في CaptchaAI

عدد العمليات المتزامنة الذي سنراه في الكود (50 أو 100) لا يعيش في السكربت وحده؛ فهو مرتبط مباشرةً بعدد الـ Threads في خطتك. يحاسب CaptchaAI على أساس الـ Thread المتزامن لا على أساس كل عملية حل، وتشمل كل خطة عددًا غير محدود من الحلول لكل Thread خلال الشهر. الـ Thread الواحد يعني اختبار CAPTCHA واحدًا قيد التنفيذ؛ وبمجرد انتهائه يلتقط المهمة التالية. عمليًا هذا يعني أن سقف التزامن الفعّال لديك يساوي عدد الـ Threads المتاح:

  • خطة ADVANCE بسعر 90 دولارًا شهريًا تمنحك 50 Thread — كافية لضبط MAX_CONCURRENT عند 50 وبلوغ ما يقارب 10 آلاف حل في الساعة.
  • خطة PREMIUM بسعر 170 دولارًا شهريًا تمنحك 100 Thread، وهي المسار المناسب إذا أردت رفع التزامن إلى 100 لتجاوز 15 ألف حل في الساعة.

اختر الخطة بناءً على قيمة التزامن التي تنوي تشغيلها، لا العكس؛ فرفع MAX_CONCURRENT فوق عدد الـ Threads المتاح لا يضيف إنتاجية.

التنفيذ في Python: خط أنابيب غير متزامن

يجمع السكربت التالي المنطق كله في مكان واحد: يرسل المهمة، ينتظر قبل أول استطلاع، ثم يستطلع النتيجة ضمن حدّ للتزامن يفرضه Semaphore. اضبط MAX_CONCURRENT ليطابق عدد الـ Threads في خطتك، وستحصل على إحصاءات الإنتاجية في نهاية التشغيل.

# high_throughput_solver.py
import os
import asyncio
import time
import aiohttp

API_KEY = os.environ.get("CAPTCHAAI_KEY", "YOUR_API_KEY")
BASE_URL = "https://ocr.captchaai.com"
MAX_CONCURRENT = 50  # Max simultaneous solves
POLL_INTERVAL = 5    # Seconds between polls
INITIAL_WAIT = 12    # Seconds before first poll

semaphore = asyncio.Semaphore(MAX_CONCURRENT)
stats = {"submitted": 0, "solved": 0, "failed": 0, "start": 0}

async def solve_one(session, sitekey, pageurl, task_num):
    """Submit and poll a single CAPTCHA."""
    async with semaphore:
        try:
            # Submit
            async with session.get(f"{BASE_URL}/in.php", params={
                "key": API_KEY, "method": "userrecaptcha",
                "googlekey": sitekey, "pageurl": pageurl, "json": "1",
            }) as resp:
                result = await resp.json(content_type=None)

            if result.get("status") != 1:
                stats["failed"] += 1
                return None

            stats["submitted"] += 1
            task_id = result["request"]

            # Wait before first poll
            await asyncio.sleep(INITIAL_WAIT)

            # Poll
            for _ in range(25):
                async with session.get(f"{BASE_URL}/res.php", params={
                    "key": API_KEY, "action": "get",
                    "id": task_id, "json": "1",
                }) as resp:
                    poll_result = await resp.json(content_type=None)

                if poll_result.get("status") == 1:
                    stats["solved"] += 1
                    return poll_result["request"]

                if poll_result.get("request") != "CAPCHA_NOT_READY":
                    stats["failed"] += 1
                    return None

                await asyncio.sleep(POLL_INTERVAL)

            stats["failed"] += 1
            return None

        except Exception as e:
            stats["failed"] += 1
            return None

async def run_batch(tasks):
    """Process a batch of CAPTCHA tasks concurrently."""
    connector = aiohttp.TCPConnector(
        limit=MAX_CONCURRENT,
        keepalive_timeout=60,
    )
    async with aiohttp.ClientSession(connector=connector) as session:
        coros = [
            solve_one(session, task["sitekey"], task["pageurl"], i)
            for i, task in enumerate(tasks)
        ]
        results = await asyncio.gather(*coros)
    return results

async def main():
    # Generate test tasks (replace with your task source)
    tasks = [
        {
            "sitekey": "6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
            "pageurl": "https://www.google.com/recaptcha/api2/demo",
        }
        for _ in range(100)  # Start with 100 tasks
    ]

    stats["start"] = time.time()
    print(f"Processing {len(tasks)} tasks with {MAX_CONCURRENT} concurrent workers")

    results = await run_batch(tasks)
    elapsed = time.time() - stats["start"]

    print(f"\nCompleted in {elapsed:.0f}s")
    print(f"Submitted: {stats['submitted']}")
    print(f"Solved: {stats['solved']}")
    print(f"Failed: {stats['failed']}")
    print(f"Throughput: {stats['solved'] / (elapsed / 3600):.0f} solves/hour")

asyncio.run(main())

التنفيذ في JavaScript وNode.js: تزامن مُدار

النسخة نفسها في Node.js تعتمد على axios ووكيل https مع إبقاء الاتصال حيًا (keep-alive) لإعادة استخدام الاتصالات، وتتحكم في التزامن عبر مجموعة executing بدلًا من الـ Semaphore، مع الحفاظ على المنطق ذاته: إرسال، ثم انتظار، ثم استطلاع.

// high_throughput_solver.js
const axios = require('axios');
const https = require('https');

const API_KEY = process.env.CAPTCHAAI_KEY || 'YOUR_API_KEY';
const BASE = 'https://ocr.captchaai.com';
const MAX_CONCURRENT = 50;

const agent = new https.Agent({ keepAlive: true, maxSockets: MAX_CONCURRENT });
const api = axios.create({ baseURL: BASE, httpsAgent: agent, timeout: 30000 });

const stats = { submitted: 0, solved: 0, failed: 0 };

async function solveOne(sitekey, pageurl) {
  try {
    const submit = await api.get('/in.php', {
      params: { key: API_KEY, method: 'userrecaptcha', googlekey: sitekey, pageurl, json: '1' },
    });
    if (submit.data.status !== 1) { stats.failed++; return null; }
    stats.submitted++;

    await new Promise(r => setTimeout(r, 12000));

    for (let i = 0; i < 25; i++) {
      const poll = await api.get('/res.php', {
        params: { key: API_KEY, action: 'get', id: submit.data.request, json: '1' },
      });
      if (poll.data.status === 1) { stats.solved++; return poll.data.request; }
      if (poll.data.request !== 'CAPCHA_NOT_READY') { stats.failed++; return null; }
      await new Promise(r => setTimeout(r, 5000));
    }
    stats.failed++;
    return null;
  } catch { stats.failed++; return null; }
}

async function runWithConcurrency(tasks, limit) {
  const results = [];
  const executing = new Set();

  for (const task of tasks) {
    const p = solveOne(task.sitekey, task.pageurl).then(r => {
      executing.delete(p);
      return r;
    });
    executing.add(p);
    results.push(p);

    if (executing.size >= limit) {
      await Promise.race(executing);
    }
  }
  return Promise.all(results);
}

(async () => {
  const tasks = Array.from({ length: 100 }, () => ({
    sitekey: '6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
    pageurl: 'https://www.google.com/recaptcha/api2/demo',
  }));

  const start = Date.now();
  console.log(`Processing ${tasks.length} tasks, ${MAX_CONCURRENT} concurrent`);

  await runWithConcurrency(tasks, MAX_CONCURRENT);
  const elapsed = (Date.now() - start) / 1000;

  console.log(`\nDone in ${elapsed.toFixed(0)}s`);
  console.log(`Solved: ${stats.solved}, Failed: ${stats.failed}`);
  console.log(`Throughput: ${(stats.solved / (elapsed / 3600)).toFixed(0)} solves/hour`);

  agent.destroy();
})();

اضبط المعاملات لموازنة السرعة والاستقرار

تخيّل فريق مراقبة أسعار يتابع آلاف المنتجات عبر متاجر إلكترونية إقليمية خلال موسم تخفيضات مثل الجمعة البيضاء؛ يحتاج إلى تحديث القوائم بالكامل كل ساعة، ما يترجم إلى نحو 10 آلاف اختبار CAPTCHA في الساعة عند الذروة. لا توجد قيمة واحدة مثالية؛ ابدأ محافظًا ثم تدرّج. يلخّص الجدول ثلاث توليفات شائعة:

الأرقام التالية تستند إلى بيانات مرصودة وتقارير مستخدمين. قد تختلف النتائج بحسب بيئة التشغيل والحجم والتوقيت ونوع الـ CAPTCHA.

المعامل محافظ متوازن عدواني
MAX_CONCURRENT 20 50 100
INITIAL_WAIT 15 ثانية 12 ثانية 10 ثوانٍ
POLL_INTERVAL 7 ثوانٍ 5 ثوانٍ 3 ثوانٍ
MAX_POLL_ATTEMPTS 30 25 20
الإنتاجية المتوقعة ~4,800/ساعة ~10,000/ساعة ~18,000/ساعة

ابدأ عند قيمة محافظة وارفع MAX_CONCURRENT تدريجيًا حتى تلاحظ تراجع العائد أو ارتفاع معدل الأخطاء؛ عندها تكون قد بلغت السقف العملي لبيئتك وخطتك.

راقب الإنتاجية لحظة بلحظة

تابِع هذه المؤشرات آنيًا لتكتشف الاختناقات مبكرًا قبل أن تنهار الإنتاجية:

  • الحلول في الدقيقة — ينبغي أن تدور حول 167 للحفاظ على هدف 10 آلاف في الساعة
  • معدل الأخطاء — أبقِه دون 5%؛ إذا قفز فخفّض التزامن فورًا
  • عمق قائمة الانتظار — إذا تزايد فزد عدد العمّال، وإذا فرغ باستمرار فأنت تملك طاقة فائضة
  • زمن الحل عند المئين 90 (P90) — إذا ارتفع فقد تكون الخدمة تُطبّق تحديدًا لمعدل الطلبات

عالج المشكلات الشائعة عند التوسّع

المشكلة السبب المحتمل الإجراء
تثبّت الإنتاجية عند ~5 آلاف في الساعة التزامن غير كافٍ ارفع MAX_CONCURRENT نحو 80–100 بما يوافق عدد الـ Threads المتاح
تجاوز معدل الأخطاء 10% إغراق الـ API أو خوادم وسيطة ضعيفة خفّض التزامن وتحقّق من صحة البروكسي
نمو استهلاك الذاكرة باطّراد تراكم غير محدود للمهام في الذاكرة عالج النتائج فور وصولها بدل تخزينها دفعةً واحدة
ظهور ERROR_NO_SLOT_AVAILABLE امتلاء قائمة CaptchaAI مؤقتًا تراجع وأعد المحاولة بعد 5 ثوانٍ

أسئلة شائعة

كم عدد الـ Threads اللازم للوصول إلى 10 آلاف حل في الساعة؟

عند متوسط حل يقارب 15 ثانية، تحتاج إلى نحو 42–50 عملية متزامنة، أي 50 Thread على الأقل.

خطة ADVANCE بسعر 90 دولارًا شهريًا (50 Thread) تغطّي هذا الهدف؛ وإذا أردت هامش أمان أو إنتاجية أعلى فانتقل إلى PREMIUM بسعر 170 دولارًا شهريًا (100 Thread).

هل تتغيّر الإنتاجية القصوى باختلاف نوع CAPTCHA؟

نعم، فزمن الحل هو ما يحدّد سقف الإنتاجية عند عدد Threads ثابت:

  • reCAPTCHA v2 — الأساس المستخدم في حساباتنا (نحو 15 ثانية للحل الواحد)
  • Cloudflare Turnstile — أسرع عادةً، فيرفع الإنتاجية عند نفس عدد الـ Threads
  • الأنواع الأثقل — تطيل زمن الدورة وتخفض الرقم النهائي

قِس زمن الحل الفعلي لكل نوع في بيئتك قبل تثبيت هدف الإنتاجية.

كيف أوزّع الحِمل على عدة خوادم دون تكرار المهام؟

استخدم قائمة انتظار مشتركة مثل Redis أو RabbitMQ، وشغّل سكربت العامل على أكثر من خادم.

يسحب كل عامل المهام بشكل ذرّي من القائمة نفسها، فلا تُعالَج المهمة مرتين، ويتوزّع التزامن الكلي بين الخوادم.

ما مقدار الرصيد الذي يستهلكه معدل 10 آلاف حل في الساعة؟

بما أن CaptchaAI يحاسب على أساس الـ Thread لا على كل حل، تبقى تكلفتك الشهرية ثابتة بحسب خطتك ما دمت ضمن حدود الـ Threads، بصرف النظر عن عدد الحلول.

راقب مع ذلك حالة حسابك عبر لوحة التحكم ونقطة النهاية res.php?action=getbalance، وفعّل تنبيهات مبكرة عند اقتراب أي حد حتى لا يتوقف الخط فجأة عند الذروة.

هل يلزمني استخدام خوادم وسيطة (proxies) على هذا الحجم؟

يعمل الكود دون بروكسي في الاختبارات الافتراضية، لكن عند الحجم الكبير على مواقع حسّاسة لسمعة عنوان IP قد تحتاج إلى خوادم وسيطة سكنية لتوزيع الطلبات. ابدأ من دون بروكسي، وأضِفه فقط إذا ارتفع معدل الرفض من الموقع المستهدف.


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

أدلة ذات صلة

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