Hướng Dẫn Thực Hành

Tải CAPTCHA động: Phát hiện CAPTCHA được tải chậm

Không phải tất cả CAPTCHA đều xuất hiện khi trang tải lần đầu tiên. Nhiều trang web hiển thị CAPTCHA một cách lười biếng — sau một lần nhấp nút, tiêu điểm biểu mẫu, cuộn hoặc hẹn giờ. Nếu tính năng tự động hóa của bạn lấy nguồn trang ngay lập tức thì CAPTCHA vẫn chưa có ở đó. Hướng dẫn này bao gồm cách phát hiện và chờ đợi CAPTCHA được tải động.


Trình kích hoạt tải chậm phổ biến

Trình kích hoạt Ví dụ Cách kích hoạt
Bấm vào nút "Gửi" thêm reCAPTCHA vào biểu mẫu Bấm vào nút đầu tiên
Tiêu điểm của biểu mẫu CAPTCHA xuất hiện khi tập trung vào dữ liệu nhập Tập trung vào trường email/password
Vị trí cuộn CAPTCHA tải khi phần này hiển thị Di chuyển đến biểu mẫu
hẹn giờ CAPTCHA tải sau 3 giây Chờ sự chậm trễ
Điều kiện JavaScript Tải CAPTCHA sau phản hồi AJAX Kích hoạt yêu cầu tiên quyết

Cách 1: MutationObserver

Xem DOM để biết các phần tử CAPTCHA đang được thêm vào:

Puppeteer

const puppeteer = require('puppeteer');

const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('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);

Kích hoạt tải

// 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();
});

Phương pháp 2: Chờ chèn tập lệnh

CAPTCHA yêu cầu thư viện JavaScript của chúng. Hãy chú ý điều đó:

// 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');
});

cho cửa quay

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');
});

Phương pháp 3: Chặn lệnh gọi kết xuất

Truy cập thư viện CAPTCHA trước khi nó hiển thị:

// 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): Đang chờ CAPTCHA lười biếng

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://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")

Đang chờ 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")

Phát hiện hoàn chỉnh + giải quyết luồng

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

Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
CAPTCHA không bao giờ xuất hiện Hành động kích hoạt sai Kiểm tra trang để tìm yếu tố kích hoạt CAPTCHA
Khóa trang web không có giá trị Phần tử tồn tại nhưng tập lệnh chưa chạy Đợi iframe CAPTCHA, không chỉ div
Người quan sát bỏ lỡ nó CAPTCHA đã có sẵn ở đó Kiểm tra các phần tử hiện có trước khi thiết lập trình quan sát
Hết giờ CAPTCHA chỉ tải cho người dùng thực Sử dụng trình duyệt hoàn chỉnh với dấu vân tay thực tế

Câu hỏi thường gặp

Làm cách nào để biết CAPTCHA có được tải từng phần hay không?

Xem nguồn trang (Ctrl+U). Nếu div hoặc tập lệnh CAPTCHA không có ở đó nhưng xuất hiện khi bạn tương tác với trang thì trang đó được tải từng phần.

Tính năng này có hoạt động với các trình duyệt không có giao diện người dùng không?

Vâng, hãy cẩn thận. Một số trang web chỉ tải CAPTCHA cho các trình duyệt không có giao diện người dùng. Sử dụng headless: 'new' trong Puppeteer hoặc plugin tàng hình.


Giải bất kỳ CAPTCHA nào bằng CaptchaAI

Nhận khóa API của bạn tạicaptchaai.com.


Hướng dẫn liên quan

Os comentários estão desativados para este artigo.