Не все CAPTCHA присутствуют при первой загрузке страницы. Многие сайты обрабатывают CAPTCHA лениво — после нажатия кнопки, фокуса формы, прокрутки или таймера. Если ваша автоматизация немедленно захватывает исходный код страницы, CAPTCHA еще не существует. В этом руководстве рассказывается, как обнаружить и дождаться динамически загружаемых CAPTCHA.
Распространенные триггеры отложенной загрузки
| Курок | Пример | Как активировать |
|---|---|---|
| Нажатие кнопки | «Отправить» добавляет reCAPTCHA в форму | Сначала нажмите кнопку |
| Форма фокуса | CAPTCHA появляется, когда ввод сфокусирован | Фокус на поле электронной почты/password |
| Позиция прокрутки | CAPTCHA загружается, когда раздел виден. | Прокрутите до формы |
| Таймер | Капча загружается через 3 секунды. | Подождите задержки |
| Условие JavaScript | CAPTCHA загружается после ответа AJAX | Запустить запрос предварительных условий |
Метод 1: MutationObserver
Посмотрите, как добавляются элементы CAPTCHA в DOM:
Puppeteer
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://https://staging.example.com/qa-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();
});
Способ 2. Подождите внедрения сценария.
Для 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');
});
Для Cloudflare Turnstile
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');
});
Способ 3: перехват вызовов рендеринга
Подключитесь к библиотеке 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' }
Python (Selenium): ожидание ленивых 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://https://staging.example.com/qa-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. |
| Sitekey имеет значение null | Элемент существует, но скрипт не запустился | Подождите, пока появится iframe CAPTCHA, а не только div. |
| Наблюдатель упускает это из виду | Капча уже была там | Проверьте наличие существующих элементов перед настройкой наблюдателя. |
| Тайм-аут | CAPTCHA загружается только для реальных пользователей | Используйте полноценный браузер с реалистичным сигналы браузера |
Часто задаваемые вопросы
Как узнать, что CAPTCHA загружается отложенно?
Просмотрите исходный код страницы (Ctrl+U). Если div или скрипт CAPTCHA отсутствует, но появляется при взаимодействии со страницей, значит, он загружается отложенно.
Работает ли это с headless браузерами?
Да, с оговорками. Некоторые сайты загружают CAPTCHA только для браузеров без headless. Используйте headless: 'new' в Puppeteer или стандартная конфигурация браузера-плагинах.
Решите любую капчу с помощью CaptchaAI
Получите ключ API по адресуcaptchaai.com.
Связанные руководства
- Обнаружение CAPTCHA в консоли браузера
- Обработка нескольких CAPTCHA на одной странице
- Извлечение параметров reCAPTCHA