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

reCAPTCHA trong các ứng dụng trang đơn: Kiểu tải động

Các ứng dụng trang đơn tải reCAPTCHA một cách linh hoạt — tiện ích không tồn tại trong HTML ban đầu. Biểu mẫu đăng nhập React chỉ hiển thị CAPTCHA khi thành phần được gắn kết. Trang thanh toán Vue tải reCAPTCHA sau khi người dùng nhấp vào "Đặt hàng". Việc quét nguồn trang truyền thống hoàn toàn bỏ qua những điều này. Dưới đây là cách phát hiện và giải quyết các reCAPTCHA được tải động.

Tại sao các SPA lại khác nhau

Trang truyền thống SPA
tập lệnh reCAPTCHA trong HTML ban đầu Tập lệnh được chèn sau khi thay đổi tuyến đường
Widget hiển thị khi tải trang Widget hiển thị trên thành phần gắn kết
Khóa trang web trong nguồn trang Khóa trang web trong gói JavaScript
Biểu mẫu gửi qua POST Biểu mẫu gửi qua XHR/fetch

Trong SPA, tiện ích reCAPTCHA có thể không tồn tại cho đến khi một hành động cụ thể của người dùng kích hoạt tiện ích đó. Tự động hóa của bạn phải đợi tiện ích xuất hiện.

Phát hiện tiện ích reCAPTCHA

Chờ đợi phần tử

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(headless=False)
    page = browser.new_page()
    page.goto("https://staging.example.com/qa-login")

    # SPA may need a click or navigation to trigger reCAPTCHA
    page.click("#show-login-form")

    # Wait for reCAPTCHA iframe to appear
    recaptcha_frame = page.wait_for_selector(
        "iframe[src*='recaptcha']",
        timeout=15000
    )
    print("reCAPTCHA detected:", recaptcha_frame.get_attribute("src"))

Trích xuất khóa trang web

Khóa trang có thể ở nhiều vị trí trong SPA:

# Method 1: From the iframe src
iframe_src = recaptcha_frame.get_attribute("src")
# src contains: ...?k=6LcR_RsTAAAAADge...
import re
match = re.search(r'[?&]k=([^&]+)', iframe_src)
site_key = match.group(1) if match else None

# Method 2: From data-sitekey attribute
site_key = page.eval_on_selector(
    "[data-sitekey]",
    "el => el.getAttribute('data-sitekey')"
)

# Method 3: From JavaScript bundle (last resort)
site_key = page.evaluate("""
    () => {
        // Check for grecaptcha render calls
        const scripts = document.querySelectorAll('script');
        for (const s of scripts) {
            const match = s.textContent.match(/sitekey['":\s]+(['"])(6L[^'"]+)\\1/);
            if (match) return match[2];
        }
        return null;
    }
""")

Giải quyết reCAPTCHA

Khi bạn có khóa trang web, hãy gửi tới CaptchaAI:

import requests
import time

def solve_recaptcha(site_key, page_url):
    # Submit task
    resp = requests.post("https://ocr.captchaai.com/in.php", data={
        "key": "YOUR_API_KEY",
        "method": "userrecaptcha",
        "googlekey": site_key,
        "pageurl": page_url,
        "json": 1
    })
    task_id = resp.json()["request"]

    # Poll for result
    for _ in range(60):
        time.sleep(3)
        result = requests.get("https://ocr.captchaai.com/res.php", params={
            "key": "YOUR_API_KEY",
            "action": "get",
            "id": task_id,
            "json": 1
        })
        data = result.json()
        if data["status"] == 1:
            return data["request"]
    raise TimeoutError("Solve timed out")

Tiêm mã thông báo vào SPA

SPA không gửi các hình thức truyền thống. Bạn cần đưa mã thông báo vào nơi ứng dụng mong đợi.

Phương pháp 1: Đặt vùng văn bản ẩn

token = solve_recaptcha(site_key, "https://staging.example.com/qa-login")

# Inject into the g-recaptcha-response textarea
page.evaluate(f"""
    document.getElementById('g-recaptcha-response').value = '{token}';
""")

# Submit the form
page.click("#login-button")

Phương pháp 2: Kích hoạt gọi lại

Nhiều triển khai SPA reCAPTCHA sử dụng chức năng gọi lại:

# Find the callback function name
callback = page.evaluate("""
    () => {
        const widget = document.querySelector('.g-recaptcha');
        return widget?.getAttribute('data-callback') || null;
    }
""")

# Call it with the token
if callback:
    page.evaluate(f"window['{callback}']('{token}')")
else:
    # Try the default grecaptcha callback
    page.evaluate(f"""
        if (window.grecaptcha) {{
            // Set the response and trigger verification
            document.getElementById('g-recaptcha-response').value = '{token}';
            // Find and call any registered callbacks
            const form = document.querySelector('form');
            if (form) form.dispatchEvent(new Event('submit'));
        }}
    """)

Cách 3: Chặn XHR (JavaScript/Puppeteer)

const puppeteer = require('puppeteer');

async function solveRecaptchaInSPA() {
  const browser = await puppeteer.launch({ headless: false });
  const page = await browser.newPage();

  // Intercept the API call and inject the token
  await page.setRequestInterception(true);
  page.on('request', request => {
    if (request.url().includes('/api/login')) {
      const postData = JSON.parse(request.postData() || '{}');
      // Token already set via page.evaluate — let it pass
      request.continue();
    } else {
      request.continue();
    }
  });

  await page.goto('https://staging.example.com/qa-login');
  await page.waitForSelector('[data-sitekey]');

  const siteKey = await page.$eval(
    '[data-sitekey]',
    el => el.getAttribute('data-sitekey')
  );

  // Solve with CaptchaAI (implementation omitted — same as Python)
  const token = await solveCaptcha(siteKey, page.url());

  // Inject token and trigger callback
  await page.evaluate((t) => {
    document.getElementById('g-recaptcha-response').value = t;
    const callback = document.querySelector('.g-recaptcha')
      ?.getAttribute('data-callback');
    if (callback && window[callback]) {
      window[callback](t);
    }
  }, token);
}

Các mẫu dành riêng cho khung

Phản ứng (Reac-google-recaptcha)

Các ứng dụng React thường sử dụng gói react-google-recaptcha. Thành phần hiển thị không đồng bộ:

# Wait for React to mount the component
page.wait_for_selector(".g-recaptcha", state="attached")

# The sitekey is in the rendered div's data attribute
site_key = page.eval_on_selector(
    ".g-recaptcha", "el => el.dataset.sitekey"
)

Vue (vue-recaptcha)

# Vue may use v-if to conditionally render
# Navigate or interact to trigger the condition
page.click("#proceed-to-checkout")
page.wait_for_selector("iframe[src*='recaptcha']")

Góc cạnh

# Angular apps may lazy-load reCAPTCHA modules
# Wait for the specific Angular component
page.wait_for_selector("re-captcha, app-recaptcha, [data-sitekey]")

Xử lý thay đổi tuyến đường

SPA sử dụng lại trang - điều hướng diễn ra mà không cần tải lại đầy đủ:

# Listen for reCAPTCHA appearing after SPA navigation
page.goto("https://example.com")

# Navigate within the SPA
page.click("a[href='/login']")

# The URL changed but no page reload happened
# Wait for the CAPTCHA to render in the new "page"
page.wait_for_selector("iframe[src*='recaptcha']", timeout=10000)

Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
Không tìm thấy vùng văn bản g-recaptcha-response SPA chưa hiển thị tiện ích này Sử dụng wait_for_selector với thời gian chờ thích hợp
Mã thông báo đã được chèn nhưng biểu mẫu không gửi được Cuộc gọi lại không được kích hoạt Tìm và gọi hàm data-callback
Khóa trang web không có trong nguồn trang Được gói trong JS hoặc được tải động Đợi kết xuất widget, sau đó trích xuất từ iframe src
Mã thông báo hoạt động một lần rồi thất bại Thành phần hiển thị lại SPA, xóa mã thông báo Tiêm mã thông báo ngay trước khi gửi biểu mẫu
Tiện ích hiển thị lại sau khi chèn mã thông báo Phản ứng React/Vue xóa giá trị Sử dụng phương pháp data-callback thay vì đặt vùng văn bản

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

Tôi có thể bỏ qua trình duyệt và giải quyết SPA reCAPTCHA chỉ bằng yêu cầu HTTP không?

Nếu bạn có thể trích xuất khóa trang web và sao chép lệnh gọi API gửi biểu mẫu thì có. Nhiều biểu mẫu SPA gửi qua điểm cuối API REST - bạn có thể gọi nó trực tiếp bằng mã thông báo. Nhưng trước tiên bạn cần có trình duyệt để khám phá khóa trang web và điểm cuối API.

Làm cách nào để xử lý reCAPTCHA chỉ xuất hiện trên một số hành động nhất định của người dùng?

Tự động hóa hành động kích hoạt (nhấp vào nút, điền vào biểu mẫu, điều hướng đến một tuyến đường), sau đó đợi phần tử reCAPTCHA xuất hiện. Sử dụng wait_for_selector với thời gian chờ hợp lý.

CaptchaAI có quan tâm liệu reCAPTCHA có trong SPA không?

Không. CaptchaAI chỉ cần khóa trang và URL trang. Cách tải tiện ích trên trang không ảnh hưởng đến việc giải quyết.

bài viết liên quan

Các bước tiếp theo

Giải quyết các reCAPTCHA được tải động trong bất kỳ SPA nào —lấy khóa API CaptchaAI của bạn.

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