لا تكون جميع اختبارات CAPTCHA موجودة عند تحميل الصفحة لأول مرة. تعرض العديد من المواقع اختبارات CAPTCHA بتكاسل - بعد نقرة زر أو التركيز على النموذج أو التمرير أو المؤقت. إذا استحوذت الأتمتة على مصدر الصفحة على الفور، فلن يكون اختبار CAPTCHA موجودًا بعد. يغطي هذا الدليل كيفية اكتشاف اختبارات CAPTCHA المحملة ديناميكيًا وانتظارها.
مشغلات التحميل البطيء الشائعة
| المحفّز | مثال | كيفية التنشيط |
|---|---|---|
| انقر فوق الزر | يؤدي "إرسال" إلى إضافة reCAPTCHA إلى النموذج | انقر فوق الزر أولاً |
| تركيز النموذج | يظهر اختبار CAPTCHA عندما يتم التركيز على الإدخال | ركز على حقل البريد الإلكتروني/password |
| موقف التمرير | يتم تحميل اختبار CAPTCHA عندما يكون القسم مرئيًا | قم بالتمرير إلى النموذج |
| الموقت | يتم تحميل اختبار CAPTCHA بعد 3 ثوانٍ | انتظر التأخير |
| شرط JavaScript | يتم تحميل اختبار CAPTCHA بعد استجابة AJAX | تشغيل الطلب المسبق |
الطريقة الأولى: مراقب الطفرة
شاهد DOM لعناصر CAPTCHA التي تتم إضافتها:
Puppeteer
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://example.com/login');
// Set up MutationObserver before triggering the CAPTCHA
const captchaInfo = await page.evaluate(() => {
return new Promise((resolve) => {
// Check if already present
const existing = document.querySelector('.g-recaptcha, .cf-turnstile, .h-captcha');
if (existing) {
resolve({
type: existing.className,
sitekey: existing.getAttribute('data-sitekey'),
});
return;
}
// Watch for new elements
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node.nodeType !== 1) continue;
const captcha = node.matches?.('.g-recaptcha, .cf-turnstile, .h-captcha')
? node
: node.querySelector?.('.g-recaptcha, .cf-turnstile, .h-captcha');
if (captcha) {
observer.disconnect();
resolve({
type: captcha.className,
sitekey: captcha.getAttribute('data-sitekey'),
});
return;
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
// Timeout after 30 seconds
setTimeout(() => {
observer.disconnect();
resolve(null);
}, 30000);
});
});
console.log('Detected CAPTCHA:', captchaInfo);
اثارة الحمل
// Click the submit button to trigger CAPTCHA
await page.click('#submit-btn');
// Or focus the input
await page.focus('#email');
// Or scroll to the form
await page.evaluate(() => {
document.querySelector('#signup-form').scrollIntoView();
});
الطريقة الثانية: انتظر إدخال البرنامج النصي
تتطلب اختبارات CAPTCHA مكتبة JavaScript الخاصة بها. انتبه لذلك:
// Wait for reCAPTCHA script to load
await page.waitForFunction(() => {
return typeof window.grecaptcha !== 'undefined'
&& typeof window.grecaptcha.render === 'function';
}, { timeout: 30000 });
// Now extract parameters
const sitekey = await page.evaluate(() => {
const el = document.querySelector('.g-recaptcha');
return el?.getAttribute('data-sitekey');
});
للباب الدوار
await page.waitForFunction(() => {
return typeof window.turnstile !== 'undefined';
}, { timeout: 30000 });
const sitekey = await page.evaluate(() => {
const el = document.querySelector('.cf-turnstile');
return el?.getAttribute('data-sitekey');
});
الطريقة الثالثة: اعتراض مكالمات العرض
قم بالربط بمكتبة CAPTCHA قبل أن يتم عرضها:
// Inject before page scripts run
await page.evaluateOnNewDocument(() => {
window.__captchaDetected = null;
// Hook grecaptcha.render
let _grecaptcha;
Object.defineProperty(window, 'grecaptcha', {
set(val) {
_grecaptcha = val;
const origRender = val.render;
val.render = function(container, params) {
window.__captchaDetected = {
type: 'recaptcha',
sitekey: params.sitekey,
callback: params.callback?.name,
container: typeof container === 'string' ? container : container.id,
};
return origRender.apply(this, arguments);
};
},
get() { return _grecaptcha; },
});
});
await page.goto('https://example.com/signup');
// Trigger the CAPTCHA (click, scroll, etc.)
await page.click('#show-form');
// Wait for detection
await page.waitForFunction(() => window.__captchaDetected !== null, {
timeout: 30000,
});
const detected = await page.evaluate(() => window.__captchaDetected);
console.log('Detected:', detected);
// { type: 'recaptcha', sitekey: '6Le-wvkS...', callback: 'onCaptcha', container: 'recaptcha-box' }
بايثون (السيلينيوم): في انتظار اختبارات CAPTCHA البطيئة
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://example.com/login")
# Trigger the CAPTCHA loading
submit = driver.find_element(By.ID, "submit-btn")
submit.click()
# Wait for CAPTCHA to appear
try:
captcha_el = WebDriverWait(driver, 30).until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
".g-recaptcha, .cf-turnstile, .h-captcha"
))
)
sitekey = captcha_el.get_attribute("data-sitekey")
captcha_class = captcha_el.get_attribute("class")
if "g-recaptcha" in captcha_class:
captcha_type = "recaptcha"
elif "cf-turnstile" in captcha_class:
captcha_type = "turnstile"
else:
captcha_type = "hcaptcha"
print(f"Type: {captcha_type}, Sitekey: {sitekey}")
except Exception:
print("No CAPTCHA appeared within 30 seconds")
في انتظار iframe (reCAPTCHA)
# reCAPTCHA loads an iframe even when the div exists but the script is still loading
WebDriverWait(driver, 30).until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
"iframe[src*='recaptcha'], iframe[src*='challenges.cloudflare.com']"
))
)
print("CAPTCHA iframe loaded")
الكشف الكامل + حل التدفق
import requests
import time
def detect_and_solve(driver, api_key, trigger_action=None):
"""Detect a lazy-loaded CAPTCHA, solve it, and inject the token."""
# 1. Trigger the CAPTCHA
if trigger_action:
trigger_action(driver)
# 2. Wait for it to appear
captcha_el = WebDriverWait(driver, 30).until(
EC.presence_of_element_located((
By.CSS_SELECTOR,
".g-recaptcha, .cf-turnstile, .h-captcha"
))
)
sitekey = captcha_el.get_attribute("data-sitekey")
page_url = driver.current_url
captcha_class = captcha_el.get_attribute("class")
# 3. Determine type and method
if "g-recaptcha" in captcha_class:
method, key_param, token_field = "userrecaptcha", "googlekey", "g-recaptcha-response"
elif "cf-turnstile" in captcha_class:
method, key_param, token_field = "turnstile", "sitekey", "cf-turnstile-response"
else:
method, key_param, token_field = "hcaptcha", "sitekey", "h-captcha-response"
# 4. Solve with CaptchaAI
resp = requests.post("https://ocr.captchaai.com/in.php", data={
"key": api_key, "method": method,
key_param: sitekey, "pageurl": page_url, "json": "1",
}).json()
task_id = resp["request"]
for _ in range(24):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": api_key, "action": "get", "id": task_id, "json": "1"
}).json()
if result["status"] == 1:
token = result["request"]
break
# 5. Inject
driver.execute_script(f"""
const el = document.querySelector('textarea[name="{token_field}"], input[name="{token_field}"]');
if (el) el.value = arguments[0];
""", token)
return token
استكشاف الأخطاء وإصلاحها
| مشكلة | السبب | إصلاح |
|---|---|---|
| لا يظهر اختبار CAPTCHA أبدًا | المحفّز الخاطئ | قم بفحص الصفحة للعثور على ما يؤدي إلى تشغيل اختبار CAPTCHA |
| مفتاح الموقع فارغ | العنصر موجود ولكن لم يتم تشغيل البرنامج النصي | انتظر CAPTCHA iframe، وليس div فقط |
| المراقب يفتقدها | كان اختبار CAPTCHA موجودًا بالفعل | تحقق من وجود العناصر الموجودة قبل إعداد المراقب |
| المهلة | يتم تحميل اختبار CAPTCHA للمستخدمين الحقيقيين فقط | استخدم متصفحًا كاملاً ببصمة واقعية |
الأسئلة الشائعة
كيف أعرف ما إذا كان اختبار CAPTCHA محملاً بشكل بطيء؟
عرض مصدر الصفحة (Ctrl+U). إذا لم يكن قسم CAPTCHA أو البرنامج النصي موجودًا ولكنه يظهر عندما تتفاعل مع الصفحة، فهذا يعني أنه تم تحميله ببطء.
هل يعمل هذا مع المتصفحات مقطوعة الرأس؟
نعم، مع التحذيرات. تقوم بعض المواقع بتحميل اختبارات CAPTCHA للمتصفحات غير مقطوعة الرأس فقط. استخدم headless: 'new' في Puppeteer أو المكونات الإضافية الخفية.
حل أي اختبار CAPTCHA باستخدام CaptchaAI
احصل على مفتاح API الخاص بك علىcaptchaai.com.