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

Xử lý nhiều CAPTCHA trên một trang

Một số trang hiển thị hai hoặc nhiều CAPTCHA — biểu mẫu đăng nhập bằng reCAPTCHA và đăng ký bản tin bằng reCAPTCHA thứ hai hoặc biểu mẫu nhiều bước trong đó mỗi bước kích hoạt thử thách riêng. Mỗi CAPTCHA có một khóa trang web và phần tử mục tiêu duy nhất, vì vậy bạn cần phát hiện tất cả chúng, giải quyết chúng song song và đưa từng mã thông báo vào lệnh gọi lại chính xác.


Phát hiện nhiều CAPTCHA

Python với Selenium

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']}")

Sản lượng dự kiến:

Found 2 CAPTCHAs on page
  [0] sitekey: 6LcXyzABCDEF-login
  [1] sitekey: 6LcAbcDEFGHI-signup

JavaScript với 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}`));
})();

Giải quyết song song tất cả CAPTCHA

Gửi tất cả CAPTCHA tới CaptchaAI cùng một lúc, sau đó thăm dò cho đến khi mỗi CAPTCHA được giải quyết.

Python

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)

Sản lượng dự kiến:

[captcha-0] Submitted → task 71823456
[captcha-1] Submitted → task 71823457
[captcha-1] Solved
[captcha-0] Solved

Đưa mã thông báo vào đúng tiện ích

Mỗi tiện ích reCAPTCHA có vùng văn bản g-recaptcha-response riêng. Khi có nhiều tiện ích tồn tại, mỗi vùng văn bản sẽ được lồng bên trong vùng chứa tiện ích của nó.

Python (Selen)

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

Các loại CAPTCHA hỗn hợp

Khi một trang có các loại CAPTCHA khác nhau (ví dụ: reCAPTCHA + Turnstile), hãy phát hiện từng loại riêng biệt:

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

Gửi từng tham số method phù hợp — userrecaptcha cho reCAPTCHA, turnstile cho Turnstile.


Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
Mã thông báo đã được chèn nhưng biểu mẫu vẫn bị chặn Cuộc gọi lại không được kích hoạt Kiểm tra data-callback và gọi nó bằng mã thông báo
Chỉ phát hiện CAPTCHA đầu tiên CAPTCHA thứ hai tải chậm Đợi tất cả iframe/widgets xuất hiện trước khi quét
Mã thông báo sai trong tiện ích sai Chỉ số không khớp Ánh xạ mã thông báo tới khóa trang web, không phải chỉ mục vị trí
ERROR_WRONG_GOOGLEKEY Sitekey được trích xuất không chính xác Xác minh khóa trang web từ thuộc tính iframe src hoặc data-sitekey

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

Một trang có thể có các khóa trang web khác nhau cho mỗi CAPTCHA không?

Vâng. Mỗi tiện ích có thể sử dụng một khóa trang web riêng biệt. Luôn trích xuất khóa trang web cho mỗi tiện ích thay vì cho rằng chúng chia sẻ một tiện ích.

Tôi nên giải quyết chúng tuần tự hay song song?

Song song. Mỗi lần giải mất 15-30 giây. Việc giải hai CAPTCHA song song cũng mất thời gian tương đương với việc giải một CAPTCHA.

Điều gì sẽ xảy ra nếu CAPTCHA thứ hai chỉ xuất hiện sau khi gửi biểu mẫu đầu tiên?

Quét lại trang sau mỗi lần gửi biểu mẫu để phát hiện CAPTCHA mới được hiển thị. Sử dụng WebDriverWait (Selenium) hoặc page.waitForSelector (Puppeteer) để chờ widget mới.


Giải bất kỳ số lượng CAPTCHA nào trên mỗi trang 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.