Nếu pipeline scraping cứ dính CAPTCHA sau vài chục request liên tiếp, nguyên nhân gần như luôn là: quá nhiều request từ cùng một IP trong thời gian ngắn. Cách xử lý gồm hai lớp — đa dạng hoá nguồn request để giảm tần suất CAPTCHA xuất hiện, và dùng CaptchaAI để giải phần vẫn lọt qua. Kết hợp cả hai, bạn có luồng thu thập dữ liệu ổn định trước hầu hết hệ thống chống bot phổ biến.
Ví dụ thực tế: theo dõi giá trên sàn thương mại điện tử
Đội data tại một công ty outsourcing theo dõi giá Shopee, Lazada, Tiki thường dùng proxy trung tâm dữ liệu cho trang danh mục, rồi chuyển sang nguồn chất lượng cao hơn khi trang tìm kiếm bật reCAPTCHA hoặc Turnstile — CaptchaAI xử lý phần phát sinh.
Ghi log nguồn request giúp debug nhanh và đáp ứng yêu cầu lưu vết theo Nghị định 13/2023/NĐ-CP khi hệ thống xử lý dữ liệu cá nhân.
Vì sao một IP duy nhất dễ dính CAPTCHA
Các trang đích không chặn ngẫu nhiên — hệ thống chống bot của họ chấm điểm dựa trên mẫu request theo từng IP:
| Yếu tố | Một IP cố định | Đa dạng nguồn request |
|---|---|---|
| Request/phút | Trên 10 thường kích hoạt CAPTCHA | Phân tán trên nhiều IP |
| Uy tín IP | Giảm dần theo thời gian | Liên tục có IP mới |
| Mẫu phiên | Dễ lộ mẫu đáng ngờ | Trải đều, khó gộp nguồn |
| Địa lý | Một vị trí duy nhất | Tự nhiên, đa dạng hơn |
Chọn loại proxy theo mục tiêu quét
- Khu dân cư — mục tiêu khó (Google, Amazon); CAPTCHA thấp nhất; $$$
- Di động — độ tin cậy IP cao nhất; CAPTCHA thấp nhất; $$$$
- ISP/tĩnh — phiên cần ổn định lâu dài; CAPTCHA thấp; $$
- Trung tâm dữ liệu — trang dung lượng lớn, ít bảo vệ; CAPTCHA cao hơn; $
Gợi ý: trang chống bot chặt ưu tiên nguồn chất lượng cao; trang kiểm soát nhẹ thì trung tâm dữ liệu đã đủ dùng và rẻ hơn.
Thực tiễn triển khai nên áp dụng
| Thực tiễn | Lý do |
|---|---|
| Khớp địa lý với mục tiêu | Giảm nghi ngờ vị trí |
| Mỗi phiên một proxy | Không đổi giữa luồng nhiều bước |
| Giới hạn tần suất theo IP | Tối đa 5-10 request/phút |
| Ghi log tỷ lệ CAPTCHA theo nguồn | Phát hiện sớm proxy có vấn đề |
| Giữ phiên cố định cho luồng nhiều bước | Đăng nhập, checkout cùng một IP |
| Retry tự động khi proxy lỗi | Tránh dừng job giữa chừng |
Khắc phục sự cố thường gặp
- Toàn bộ proxy đều dính CAPTCHA → chuyển nguồn chất lượng cao hơn; giảm tần suất
- Proxy hết thời gian chờ liên tục → loại proxy chậm khỏi pool
- Nội dung khác nhau giữa các proxy → trang trả nội dung theo địa lý, cố định vùng
- Token không dùng được sau khi đổi proxy → dùng token đúng phiên/IP đã lấy
Câu hỏi thường gặp
Cloudflare Challenge có bắt buộc dùng cùng một proxy suốt phiên không?
Có. Cookie mà Cloudflare Challenge trả về bị ràng buộc IP, đổi proxy giữa chừng là mất hiệu lực. Các loại còn lại (reCAPTCHA, Turnstile, GeeTest v3) thì token hợp lệ bất kể IP nào submit.
Proxy trung tâm dữ liệu có dùng được cho Shopee, Lazada, Tiki không?
Được với trang danh mục/sản phẩm công khai. Trang tìm kiếm hoặc checkout chống bot chặt hơn nên tỷ lệ dính CAPTCHA cao hơn — chuyển sang nguồn chất lượng cao hơn và để CaptchaAI xử lý phần phát sinh.
Dùng nhiều proxy có làm tăng chi phí CaptchaAI không?
Không. CaptchaAI tính phí theo thread đang giải đồng thời (ví dụ BASIC $15/tháng, 5 thread), không theo IP hay số proxy. Đổi bao nhiêu proxy cũng không ảnh hưởng chi phí, miễn số CAPTCHA giải cùng lúc không vượt số thread của gói.
Cách đơn giản: đa dạng nguồn request bằng Python
import requests
import random
import time
PROXIES = [
"http://user:[email protected]:8080",
"http://user:[email protected]:8080",
"http://user:[email protected]:8080",
]
API_KEY = "YOUR_API_KEY"
def get_random_proxy():
proxy = random.choice(PROXIES)
return {"http": proxy, "https": proxy}
def scrape_with_rotation(url):
proxy = get_random_proxy()
session = requests.Session()
session.proxies = proxy
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
})
resp = session.get(url)
# If CAPTCHA appears, solve it
if "g-recaptcha" in resp.text or "captcha" in resp.text.lower():
from bs4 import BeautifulSoup
soup = BeautifulSoup(resp.text, "html.parser")
rc = soup.find("div", class_="g-recaptcha")
if rc:
site_key = rc["data-sitekey"]
token = solve_captcha(site_key, url)
resp = session.post(url, data={"g-recaptcha-response": token})
return resp.text
def solve_captcha(site_key, page_url):
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY, "method": "userrecaptcha",
"googlekey": site_key, "pageurl": page_url
})
task_id = resp.text.split("|")[1]
for _ in range(60):
time.sleep(5)
result = requests.get("https://ocr.captchaai.com/res.php", params={
"key": API_KEY, "action": "get", "id": task_id
})
if result.text == "CAPCHA_NOT_READY": continue
if result.text.startswith("OK|"): return result.text.split("|")[1]
raise Exception(result.text)
raise TimeoutError()
Ưu tiên nguồn request theo tỷ lệ giải thành công
Cách trên chọn proxy ngẫu nhiên, không phân biệt tốt xấu. Bản nâng cấp dưới đây theo dõi proxy nào hay kích hoạt CAPTCHA và tự động ưu tiên các proxy đang hoạt động tốt hơn:
from collections import defaultdict
import random
class SmartProxyRotator:
def __init__(self, proxies):
self.proxies = proxies
self.captcha_count = defaultdict(int)
self.success_count = defaultdict(int)
def get_proxy(self):
# Prefer proxies with lower CAPTCHA rates
scored = []
for proxy in self.proxies:
total = self.captcha_count[proxy] + self.success_count[proxy]
if total == 0:
score = 0.5 # Unknown proxy, neutral score
else:
score = self.success_count[proxy] / total
scored.append((proxy, score))
# Weight selection by score
scored.sort(key=lambda x: x[1], reverse=True)
top_proxies = scored[:max(len(scored) // 2, 1)]
proxy = random.choice(top_proxies)[0]
return proxy
def report_success(self, proxy):
self.success_count[proxy] += 1
def report_captcha(self, proxy):
self.captcha_count[proxy] += 1
# Usage
rotator = SmartProxyRotator(PROXIES)
def scrape(url):
proxy = rotator.get_proxy()
resp = requests.get(url, proxies={"http": proxy, "https": proxy})
if "captcha" in resp.text.lower():
rotator.report_captcha(proxy)
# Solve CAPTCHA...
else:
rotator.report_success(proxy)
return resp.text
Áp dụng trong Selenium
Khi automation chạy qua trình duyệt thật (Selenium, Playwright, Puppeteer), gán proxy ở cấp trình duyệt thay vì cấp request HTTP:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def create_driver_with_proxy(proxy_url):
options = Options()
options.add_argument(f"--proxy-server={proxy_url}")
options.add_argument("")
return webdriver.Chrome(options=options)
# Rotate proxy per session
proxy = random.choice(PROXIES)
driver = create_driver_with_proxy(proxy)
driver.get("https://example.com")
Trường hợp riêng: Cloudflare Challenge cần giữ nguyên một proxy
Cookie mà Cloudflare Challenge trả về bị ràng buộc IP, nên phải truyền đúng proxy đang dùng cho CaptchaAI:
proxy = "http://user:[email protected]:8080"
resp = requests.get("https://ocr.captchaai.com/in.php", params={
"key": API_KEY,
"method": "cloudflare_challenge",
"pageurl": "https://example.com",
"proxy": proxy,
"proxytype": "HTTP"
})
task_id = resp.text.split("|")[1]
# Poll for qa_session_cookie cookie
# Use the same proxy for subsequent requests