تعرض بعض الصفحات اثنين أو أكثر من اختبارات 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.