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
- Trích xuất CAPTCHA iframe: Giải CAPTCHA trong các khung lồng nhau
- Trích xuất tham số reCAPTCHA từ nguồn trang
- Giải quyết CAPTCHA song song