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

التعامل مع اختبارات CAPTCHA المتعددة في صفحة واحدة

تعرض بعض الصفحات اثنين أو أكثر من اختبارات CAPTCHA - نموذج تسجيل دخول باستخدام reCAPTCHA واشتراك في النشرة الإخبارية باستخدام reCAPTCHA ثانٍ، أو نموذج متعدد الخطوات حيث تؤدي كل خطوة إلى التحدي الخاص بها. يحتوي كل اختبار CAPTCHA على مفتاح موقع فريد وعنصر مستهدف، لذلك تحتاج إلى اكتشافها جميعًا، وحلها بالتوازي، وإدخال كل رمز مميز في رد الاتصال الصحيح.


اكتشاف العديد من اختبارات CAPTCHA

بايثون مع السيلينيوم

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

driver = webdriver.Chrome()
driver.get("https://example.com/multi-captcha-page")

# Find all reCAPTCHA iframes
captcha_iframes = driver.find_elements(
    By.CSS_SELECTOR, 'iframe[src*="recaptcha/api2/anchor"]'
)

# Extract sitekeys from each iframe's src
import re
captchas = []
for i, iframe in enumerate(captcha_iframes):
    src = iframe.get_attribute("src")
    match = re.search(r"k=([A-Za-z0-9_-]+)", src)
    if match:
        captchas.append({
            "index": i,
            "sitekey": match.group(1),
            "iframe": iframe
        })

print(f"Found {len(captchas)} CAPTCHAs on page")
for c in captchas:
    print(f"  [{c['index']}] sitekey: {c['sitekey']}")

الناتج المتوقع:

Found 2 CAPTCHAs on page
  [0] sitekey: 6LcXyzABCDEF-login
  [1] sitekey: 6LcAbcDEFGHI-signup

JavaScript مع Puppeteer

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();
  await page.goto('https://example.com/multi-captcha-page', {
    waitUntil: 'networkidle2'
  });

  // Extract all reCAPTCHA widgets from the page
  const captchas = await page.evaluate(() => {
    const widgets = document.querySelectorAll('.g-recaptcha');
    return Array.from(widgets).map((el, i) => ({
      index: i,
      sitekey: el.getAttribute('data-sitekey'),
      elementId: el.id || `captcha-${i}`,
      callbackName: el.getAttribute('data-callback') || null
    }));
  });

  console.log(`Found ${captchas.length} CAPTCHAs`);
  captchas.forEach(c => console.log(`  [${c.index}] ${c.sitekey}`));
})();

حل جميع اختبارات CAPTCHA بالتوازي

أرسل جميع اختبارات CAPTCHA إلى CaptchaAI مرة واحدة، ثم قم بالاستطلاع حتى يتم حل كل منها.

بايثون

import requests
import time
from concurrent.futures import ThreadPoolExecutor, as_completed

API_KEY = "YOUR_API_KEY"
PAGE_URL = "https://example.com/multi-captcha-page"

def submit_captcha(sitekey):
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": API_KEY,
        "method": "userrecaptcha",
        "googlekey": sitekey,
        "pageurl": PAGE_URL,
        "json": "1"
    })
    result = resp.json()
    if result["status"] != 1:
        raise Exception(f"Submit error: {result['request']}")
    return result["request"]

def poll_result(task_id, timeout=120):
    deadline = time.time() + timeout
    while time.time() < deadline:
        time.sleep(5)
        resp = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": API_KEY,
            "action": "get",
            "id": task_id,
            "json": "1"
        })
        result = resp.json()
        if result["status"] == 1:
            return result["request"]
        if result["request"] != "CAPCHA_NOT_READY":
            raise Exception(f"Poll error: {result['request']}")
    raise TimeoutError(f"Task {task_id} timed out")

def solve_all(captchas):
    # Submit all in parallel
    task_ids = {}
    with ThreadPoolExecutor(max_workers=len(captchas)) as pool:
        futures = {
            pool.submit(submit_captcha, c["sitekey"]): c["index"]
            for c in captchas
        }
        for future in as_completed(futures):
            idx = futures[future]
            task_ids[idx] = future.result()
            print(f"[captcha-{idx}] Submitted → task {task_ids[idx]}")

    # Poll all in parallel
    tokens = {}
    with ThreadPoolExecutor(max_workers=len(task_ids)) as pool:
        futures = {
            pool.submit(poll_result, tid): idx
            for idx, tid in task_ids.items()
        }
        for future in as_completed(futures):
            idx = futures[future]
            tokens[idx] = future.result()
            print(f"[captcha-{idx}] Solved")

    return tokens

# Example usage
captchas = [
    {"index": 0, "sitekey": "6LcXyzABCDEF-login"},
    {"index": 1, "sitekey": "6LcAbcDEFGHI-signup"}
]

tokens = solve_all(captchas)

الناتج المتوقع:

[captcha-0] Submitted → task 71823456
[captcha-1] Submitted → task 71823457
[captcha-1] Solved
[captcha-0] Solved

حقن الرموز في القطعة الصحيحة

تحتوي كل أداة reCAPTCHA على منطقة نصية g-recaptcha-response خاصة بها. عند وجود عناصر واجهة مستخدم متعددة، يتم دمج كل منطقة نصية داخل حاوية عناصر واجهة المستخدم الخاصة بها.

بايثون (السيلينيوم)

def inject_tokens(driver, captchas, tokens):
    for c in captchas:
        idx = c["index"]
        token = tokens[idx]

        # Find the textarea within the widget's container
        container = driver.find_elements(By.CSS_SELECTOR, ".g-recaptcha")[idx]
        textarea = container.find_element(
            By.CSS_SELECTOR, 'textarea[name="g-recaptcha-response"]'
        )
        driver.execute_script(
            "arguments[0].value = arguments[1];", textarea, token
        )

        # Trigger the callback if defined
        callback = c.get("callback")
        if callback:
            driver.execute_script(f"{callback}('{token}');")

        print(f"[captcha-{idx}] Token injected")

inject_tokens(driver, captchas, tokens)

JavaScript (Puppeteer)

async function injectTokens(page, captchas, tokens) {
  for (const captcha of captchas) {
    const token = tokens[captcha.index];

    await page.evaluate((idx, tkn, callbackName) => {
      const widgets = document.querySelectorAll('.g-recaptcha');
      const textarea = widgets[idx].querySelector(
        'textarea[name="g-recaptcha-response"]'
      );
      textarea.value = tkn;

      if (callbackName && typeof window[callbackName] === 'function') {
        window[callbackName](tkn);
      }
    }, captcha.index, token, captcha.callbackName);

    console.log(`[captcha-${captcha.index}] Token injected`);
  }
}

await injectTokens(page, captchas, tokens);

أنواع CAPTCHA المختلطة

عندما تحتوي الصفحة على أنواع مختلفة من CAPTCHA (على سبيل المثال، reCAPTCHA + Turnstile)، اكتشف كل نوع على حدة:

def detect_all_captchas(driver):
    detected = []

    # reCAPTCHA
    recaptchas = driver.find_elements(By.CSS_SELECTOR, ".g-recaptcha")
    for i, el in enumerate(recaptchas):
        detected.append({
            "type": "userrecaptcha",
            "sitekey": el.get_attribute("data-sitekey"),
            "label": f"recaptcha-{i}"
        })

    # Turnstile
    turnstiles = driver.find_elements(By.CSS_SELECTOR, ".cf-turnstile")
    for i, el in enumerate(turnstiles):
        detected.append({
            "type": "turnstile",
            "sitekey": el.get_attribute("data-sitekey"),
            "label": f"turnstile-{i}"
        })

    return detected

أرسل كل منها مع معلمة method المطابقة لها - userrecaptcha لـ reCAPTCHA، وturnstile لـ Turnstile.


استكشاف الأخطاء وإصلاحها

مشكلة السبب إصلاح
تم إدخال الرمز ولكن النموذج لا يزال محظورًا لم يتم تشغيل رد الاتصال تحقق من data-callback واتصل به باستخدام الرمز المميز
تم اكتشاف اختبار CAPTCHA للمرة الأولى فقط يتم تحميل اختبار CAPTCHA الثاني بتكاسل انتظر حتى تظهر جميع إطارات iframe/widgets قبل إجراء المسح الضوئي
رمز خاطئ في القطعة الخاطئة عدم تطابق الفهرس تعيين الرموز المميزة لمفاتيح الموقع، وليس الفهرس الموضعي
ERROR_WRONG_GOOGLEKEY تم استخراج مفتاح الموقع بشكل غير صحيح تحقق من مفتاح الموقع من سمة iframe src أو data-sitekey

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

هل يمكن أن تحتوي الصفحة على مفاتيح مواقع مختلفة لكل اختبار CAPTCHA؟

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

هل يجب أن أقوم بحلها بالتتابع أم بالتوازي؟

بالتوازي. يستغرق كل حل 15-30 ثانية. يستغرق حل اثنين من اختبارات CAPTCHA بالتوازي نفس الوقت الذي يستغرقه حل أحدهما.

ماذا لو ظهر اختبار CAPTCHA الثاني فقط بعد إرسال النموذج الأول؟

أعد فحص الصفحة بعد كل إرسال نموذج لاكتشاف اختبارات CAPTCHA المقدمة حديثًا. استخدم WebDriverWait (السيلينيوم) أو page.waitForSelector (Puppeteer) لانتظار الأداة الجديدة.


قم بحل أي عدد من اختبارات CAPTCHA لكل صفحة باستخدام CaptchaAI

احصل على مفتاح API الخاص بك علىcaptchaai.com.


أدلة ذات صلة

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