Khắc Phục Sự Cố

Xử lý reCAPTCHA v2 và Cloudflare Turnstile trên cùng một trang web

Một số trang web sử dụng reCAPTCHA trên trang đăng nhập và Turnstile trên trang thanh toán. Những người khác kiểm tra A/B giữa các nhà cung cấp - cùng một URL hiển thị reCAPTCHA cho một khách truy cập và Turnstile cho một khách truy cập khác. Mã hóa cứng một phương pháp giải duy nhất có nghĩa là quá trình tự động hóa của bạn bị gián đoạn bất cứ khi nào nó gặp loại khác.

Tại sao các trang web sử dụng nhiều nhà cung cấp CAPTCHA

Kịch bản Nó xuất hiện như thế nào
Các trang khác nhau, nhà cung cấp khác nhau Đăng nhập = reCAPTCHA, thanh toán = Turnstile
Nhà cung cấp thử nghiệm A/B Cùng một trang hiển thị ngẫu nhiên một trong hai loại
Đang di chuyển Trang cũ có reCAPTCHA, trang mới có Turnstile
Dự phòng khi thất bại Nhà cung cấp chính không thành công → quay trở lại nhà cung cấp phụ
Sự thay đổi khu vực reCAPTCHA cho khách truy cập Hoa Kỳ, Turnstile cho EU (GDPR)

Python: Tự động phát hiện và giải quyết

import requests
import time
import re
from dataclasses import dataclass

API_KEY = "YOUR_API_KEY"
SUBMIT_URL = "https://ocr.captchaai.com/in.php"
RESULT_URL = "https://ocr.captchaai.com/res.php"

@dataclass
class CaptchaInfo:
    provider: str     # "recaptcha" or "turnstile"
    method: str       # API method name
    sitekey: str
    pageurl: str
    response_field: str  # Form field name for the token

def detect_captcha_type(html, pageurl):
    """
    Detect which CAPTCHA provider is on the page.
    Returns CaptchaInfo or None.
    """
    # Check for Turnstile
    turnstile_match = re.search(
        r'class=["\'][^"\']*cf-turnstile[^"\']*["\'][^>]*data-sitekey=["\']([^"\']+)["\']',
        html,
    )
    if not turnstile_match:
        turnstile_match = re.search(
            r'data-sitekey=["\']([^"\']+)["\'][^>]*class=["\'][^"\']*cf-turnstile',
            html,
        )

    if turnstile_match:
        return CaptchaInfo(
            provider="turnstile",
            method="turnstile",
            sitekey=turnstile_match.group(1),
            pageurl=pageurl,
            response_field="cf-turnstile-response",
        )

    # Check for reCAPTCHA
    recaptcha_match = re.search(
        r'class=["\'][^"\']*g-recaptcha[^"\']*["\'][^>]*data-sitekey=["\']([^"\']+)["\']',
        html,
    )
    if not recaptcha_match:
        recaptcha_match = re.search(
            r'data-sitekey=["\']([^"\']+)["\'][^>]*class=["\'][^"\']*g-recaptcha',
            html,
        )

    # Also check for script-rendered reCAPTCHA
    if not recaptcha_match:
        recaptcha_match = re.search(
            r'grecaptcha\.render\([^,]+,\s*\{[^}]*["\']sitekey["\']\s*:\s*["\']([^"\']+)["\']',
            html,
        )

    if recaptcha_match:
        return CaptchaInfo(
            provider="recaptcha",
            method="userrecaptcha",
            sitekey=recaptcha_match.group(1),
            pageurl=pageurl,
            response_field="g-recaptcha-response",
        )

    return None

def solve_captcha(info):
    """Solve any detected CAPTCHA type via CaptchaAI."""
    params = {
        "key": API_KEY,
        "method": info.method,
        "json": 1,
    }

    if info.method == "userrecaptcha":
        params["googlekey"] = info.sitekey
        params["pageurl"] = info.pageurl
    elif info.method == "turnstile":
        params["sitekey"] = info.sitekey
        params["pageurl"] = info.pageurl

    resp = requests.post(SUBMIT_URL, data=params, timeout=30).json()
    if resp.get("status") != 1:
        raise RuntimeError(f"Submit failed: {resp.get('request')}")

    task_id = resp["request"]
    for _ in range(60):
        time.sleep(5)
        poll = requests.get(RESULT_URL, params={
            "key": API_KEY, "action": "get",
            "id": task_id, "json": 1,
        }, timeout=15).json()

        if poll.get("request") == "CAPCHA_NOT_READY":
            continue
        if poll.get("status") == 1:
            return poll["request"]
        raise RuntimeError(f"Solve failed: {poll.get('request')}")

    raise RuntimeError("Timeout")

def process_page(session, url):
    """Fetch page, detect CAPTCHA type, solve, and return form-ready data."""
    response = session.get(url)
    captcha_info = detect_captcha_type(response.text, url)

    if not captcha_info:
        print(f"No CAPTCHA detected on {url}")
        return None

    print(f"Detected {captcha_info.provider} on {url}")
    print(f"  Sitekey: {captcha_info.sitekey[:30]}...")

    token = solve_captcha(captcha_info)
    print(f"  Solved: {token[:30]}...")

    return {
        "provider": captcha_info.provider,
        "response_field": captcha_info.response_field,
        "token": token,
    }

# Usage: Handle multiple pages with different providers
session = requests.Session()

pages = [
    "https://staging.example.com/qa-login",      # Might have reCAPTCHA
    "https://example.com/checkout",   # Might have Turnstile
]

for url in pages:
    result = process_page(session, url)
    if result:
        form_data = {result["response_field"]: result["token"]}
        # Add other form fields...
        # session.post(url, data=form_data)

JavaScript: Phát hiện CAPTCHA động

const API_KEY = "YOUR_API_KEY";
const SUBMIT_URL = "https://ocr.captchaai.com/in.php";
const RESULT_URL = "https://ocr.captchaai.com/res.php";

function detectCaptchaType(html, pageurl) {
  // Turnstile
  const turnstileMatch = html.match(/cf-turnstile[^>]*data-sitekey=["']([^"']+)["']/);
  if (turnstileMatch) {
    return { provider: "turnstile", method: "turnstile", sitekey: turnstileMatch[1], pageurl, field: "cf-turnstile-response" };
  }

  // reCAPTCHA
  const recaptchaMatch = html.match(/g-recaptcha[^>]*data-sitekey=["']([^"']+)["']/);
  if (recaptchaMatch) {
    return { provider: "recaptcha", method: "userrecaptcha", sitekey: recaptchaMatch[1], pageurl, field: "g-recaptcha-response" };
  }

  // Script-rendered reCAPTCHA
  const scriptMatch = html.match(/sitekey["']\s*:\s*["']([^"']+)["']/);
  if (scriptMatch) {
    return { provider: "recaptcha", method: "userrecaptcha", sitekey: scriptMatch[1], pageurl, field: "g-recaptcha-response" };
  }

  return null;
}

async function solveCaptcha(info) {
  const body = new URLSearchParams({ key: API_KEY, method: info.method, json: "1" });
  if (info.method === "userrecaptcha") { body.set("googlekey", info.sitekey); body.set("pageurl", info.pageurl); }
  else if (info.method === "turnstile") { body.set("sitekey", info.sitekey); body.set("pageurl", info.pageurl); }

  const resp = await (await fetch(SUBMIT_URL, { method: "POST", body })).json();
  if (resp.status !== 1) throw new Error(`Submit: ${resp.request}`);

  const taskId = resp.request;
  for (let i = 0; i < 60; i++) {
    await new Promise((r) => setTimeout(r, 5000));
    const url = `${RESULT_URL}?key=${API_KEY}&action=get&id=${taskId}&json=1`;
    const poll = await (await fetch(url)).json();
    if (poll.request === "CAPCHA_NOT_READY") continue;
    if (poll.status === 1) return poll.request;
    throw new Error(`Solve: ${poll.request}`);
  }
  throw new Error("Timeout");
}

async function processPage(url) {
  const response = await fetch(url);
  const html = await response.text();
  const info = detectCaptchaType(html, url);

  if (!info) { console.log(`No CAPTCHA on ${url}`); return null; }
  console.log(`${info.provider} detected on ${url}`);

  const token = await solveCaptcha(info);
  return { provider: info.provider, field: info.field, token };
}

// Usage
const pages = ["https://staging.example.com/qa-login", "https://example.com/checkout"];
for (const url of pages) {
  const result = await processPage(url);
  if (result) {
    console.log(`Solved ${result.provider}: ${result.token.substring(0, 30)}...`);
  }
}

Tài liệu tham khảo phát hiện nhà cung cấp

nhà cung cấp Điểm đánh dấu HTML URL tập lệnh Trường phản hồi
reCAPTCHA v2 class="g-recaptcha" google.com/recaptcha/api.js g-recaptcha-response
Cloudflare Turnstile class="cf-turnstile" challenges.cloudflare.com/turnstile cf-turnstile-response
hCaptcha class="h-captcha" js.hcaptcha.com/1/api.js h-captcha-response

Khắc phục sự cố

Vấn đề Nguyên nhân Cách xử lý
Đã phát hiện loại CAPTCHA sai Regex khớp sai phần tử Trước tiên, hãy kiểm tra tên lớp dành riêng cho nhà cung cấp, không chỉ data-sitekey
Mã thông báo bị từ chối sau khi giải quyết đúng Đã sử dụng tên trường phản hồi sai Khớp tên trường với nhà cung cấp: g-recaptcha-response vs cf-turnstile-response
Loại CAPTCHA thay đổi giữa các lần truy cập Thử nghiệm A/B hoặc lựa chọn dựa trên địa lý Luôn phát hiện động; không bao giờ mã hóa nhà cung cấp
Cả hai nhà cung cấp được phát hiện trên một trang Một người có thể bị ẩn/inactive Kiểm tra mức độ hiển thị của phần tử - chỉ giải quyết CAPTCHA hiển thị
Không phát hiện được CAPTCHA do tập lệnh hiển thị Không có điểm đánh dấu HTML trong nguồn Kiểm tra các lệnh gọi grecaptcha.render() hoặc turnstile.render() trong tập lệnh

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

Một trang có thể sử dụng đồng thời cả reCAPTCHA và Turnstile không?

Hiếm khi ở cùng một hình thức nhưng nó xảy ra trên các phần khác nhau của trang web. Nếu cả hai đều xuất hiện trên một trang, thường chỉ có một trang đang hoạt động — hãy kiểm tra xem tiện ích nào hiển thị và có data-sitekey không trống.

CaptchaAI có sử dụng cùng một API cho cả hai nhà cung cấp không?

Các điểm cuối giống nhau (in.php / res.php) nhưng có giá trị method khác nhau. reCAPTCHA sử dụng method=userrecaptcha với googlekey, trong khi Turnstile sử dụng method=turnstile với sitekey. Mẫu tự động phát hiện xử lý ánh xạ này.

Làm cách nào để xử lý chuyển đổi dự phòng của nhà cung cấp?

Nếu một trang web chuyển từ reCAPTCHA sang Turnstile giữa phiên (ví dụ: sau khi reCAPTCHA không tải được), hãy phát hiện lại loại CAPTCHA trên mỗi yêu cầu trang thay vì lưu vào bộ nhớ đệm nhà cung cấp từ lần truy cập đầu tiên.

bài viết liên quan

Các bước tiếp theo

Xử lý các trang web có nhiều nhà cung cấp CAPTCHA —lấy khóa API CaptchaAI của bạnvà thực hiện tự động phát hiện.

Hướng dẫn liên quan:

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