Phạm vi an toàn: bài này chỉ áp dụng cho môi trường QA hoặc staging mà bạn sở hữu, hoặc được uỷ quyền kiểm thử.
Muốn biết vì sao bước CAPTCHA trong bộ test hỏng, bạn phải nhìn tầng network chứ không phải DOM. Selenium Wire đưa mọi request trình duyệt gửi đi vào driver.requests dưới dạng object Python có URL và status code, nên ba dữ kiện quyết định phần lớn ca "captcha failed" đều hiện ra:
- Widget đã load chưa — status code của
recaptcha/api2/anchor. - Trang dùng sitekey nào — tham số
k=trong URL iframe. - Thứ tự thời gian — request nào chạy trước lúc test treo.
Ba bước dưới đây là toàn bộ luồng cho một job CI: cài Selenium Wire, đọc log trên staging, gửi sitekey sang CaptchaAI lấy token cho backend QA xác thực.
Bước 1: cài Selenium Wire vào đúng virtualenv của bộ test
Cài vào đúng môi trường chạy test, không cài ở Python hệ thống:
pip install selenium-wire
Selenium Wire thay thế trực tiếp webdriver: test case giữ nguyên, chỉ dòng import đổi.
Bước 2: đọc log request CAPTCHA trên staging của bạn
Đoạn dưới mở trang QA rồi in mọi request reCAPTCHA kèm mã trạng thái:
from seleniumwire import webdriver
driver = webdriver.Chrome()
driver.get('https://staging.example.com/qa-form')
for req in driver.requests:
if 'recaptcha' in req.url:
print(req.url, req.response.status_code if req.response else None)
driver.requests xếp theo thời gian, nên bạn thấy cả trình tự load lẫn request 4xx/5xx. Danh sách rỗng thường do script kết thúc trước khi iframe load xong.
Bước 3: gửi sitekey sang CaptchaAI và xác thực token
Có sitekey và pageurl rồi thì còn ba nhịp: gửi task, polling, đặt token vào biểu mẫu QA. Lần đầu gọi API thì xem hướng dẫn bắt đầu nhanh.
import os
import requests
API_KEY = os.environ['CAPTCHAAI_KEY']
QA_PAGE_URL = os.environ['QA_PAGE_URL'] # ví dụ https://staging.example.com/qa-login
QA_SITE_KEY = os.environ['QA_SITE_KEY']
def submit_qa_recaptcha() -> str:
payload = {
'clientKey': API_KEY,
'task': {
'type': 'NoCaptchaTaskProxyless',
'websiteURL': QA_PAGE_URL,
'websiteKey': QA_SITE_KEY,
},
}
response = requests.post(
'https://api.captchaai.com/createTask',
json=payload,
timeout=30,
)
response.raise_for_status()
return response.json()['taskId']
def fetch_qa_result(task_id: str) -> dict:
payload = {'clientKey': API_KEY, 'taskId': task_id}
response = requests.post(
'https://api.captchaai.com/getTaskResult',
json=payload,
timeout=30,
)
response.raise_for_status()
return response.json()
Hàm đầu trả về ID task, hàm sau polling tới khi có token. CaptchaAI tính tiền theo thread, nên cần cân số test song song chứ không phải tổng lượt giải.
Từ log request suy ra loại CAPTCHA cần gửi
Dấu hiệu trong driver.requests |
Loại CAPTCHA và hướng dẫn |
|---|---|
recaptcha/api2/anchor kèm k= |
reCAPTCHA v2 qua API |
challenges.cloudflare.com |
Turnstile qua API |
Host geetest kèm gt= |
GeeTest v3 qua API |
Thấy hCaptcha hoặc FunCaptcha thì dừng ở mức chẩn đoán: CaptchaAI chưa hỗ trợ.
Ví dụ: đội QA thuê ngoài chạy regression ban đêm
Một agency ở TP.HCM maintain bộ test cho khách nước ngoài, mỗi đêm chạy 12 kịch bản đăng nhập song song trên staging được uỷ quyền. Trước đây báo cáo sáng hôm sau chỉ có dòng "captcha failed"; có Selenium Wire thì mỗi lần hỏng đều kèm URL và status code, đủ để tách lỗi sitekey khỏi lỗi mạng. Gói STANDARD ($30/tháng, 15 thread) vừa đủ cho 12 luồng đó.
Ghi log để lần chẩn đoán sau nhanh hơn
Mỗi lần chạy nên ghi thời điểm lấy token, mã trạng thái HTTP và ID task, kèm correlation id tới lúc backend trả kết quả. Đừng ghi nguyên token hay dữ liệu cá nhân: nguyên tắc tối thiểu hoá dữ liệu trong Nghị định 13/2023/NĐ-CP là lý do đủ để mask từ tầng thu thập.
Bảng lỗi thường gặp
| Vấn đề | Nguyên nhân thường gặp | Cách xử lý |
|---|---|---|
| Không thấy widget | Iframe load muộn | Chờ selector rồi mới đọc log |
| Log phình to | Request tích luỹ trong bộ nhớ | Dọn driver.requests giữa các kịch bản |
ERROR_NO_SLOT_AVAILABLE |
Thread bận hết tạm thời | Thử lại có backoff hoặc nâng thread |
Checklist trước khi bật trên CI
- Chỉ kiểm thử ứng dụng của bạn hoặc tài nguyên đã được uỷ quyền.
- API key nằm trong CI secret, không nằm trong repo.
Câu hỏi thường gặp
Selenium Wire chạy trong Docker trên CI được không?
Được. Image cần sẵn Chrome và chromedriver chạy headless, phần bắt request y như máy local.
Bộ test chạy 15 luồng song song thì nên chọn gói nào?
Gói STANDARD ($30/tháng, 15 thread) khớp mức đó, vì mỗi luồng chờ token chiếm một thread. Dưới 5 luồng thì BASIC ($15/tháng, 5 thread) là đủ.
CaptchaAI có giải hCaptcha hoặc GeeTest v4 không?
Không; GeeTest v4 mới ở trạng thái sắp ra mắt. Bộ test dùng được reCAPTCHA v2/v3, Turnstile, GeeTest v3, CAPTCHA ảnh/OCR và BLS.
Bật Selenium Wire có làm test chậm đi không?
Có chậm hơn chút ít vì traffic đi qua proxy nội bộ; thu hẹp phạm vi bắt request là đủ bù lại.
Bài liên quan
Lấy API key tại CaptchaAI và thêm bước giải CAPTCHA vào job regression đêm nay.