Trường Hợp Sử Dụng

Tự động so sánh báo giá bảo hiểm với xử lý CAPTCHA

Gửi xong biểu mẫu báo giá bảo hiểm ô tô hay y tế, bạn gần như chắc chắn gặp reCAPTCHA v2 ở bước cuối — đôi khi kèm CAPTCHA hình ảnh ở bước tra cứu địa chỉ. Đó là cách hãng bảo hiểm bảo vệ công cụ tính phí khỏi bị thu thập hàng loạt. Bài này chỉ CAPTCHA nào nằm ở đâu, vì sao phiên phải cố định xuyên suốt nhiều bước, và cách CaptchaAI xử lý phần giải cho đội QA kiểm thử tích hợp bảo hiểm.


CAPTCHA xuất hiện ở đâu trong quy trình báo giá bảo hiểm

Mỗi ngành bảo hiểm chọn một điểm chặn khác nhau, và độ phức tạp form quyết định loại CAPTCHA:

  • Form nhiều bước: CAPTCHA thường nằm ở bước cuối.
  • Form đơn giản: chỉ một lớp CAPTCHA duy nhất.
Loại bảo hiểm CAPTCHA gặp phải Điểm kích hoạt Độ phức tạp báo giá
Ô tô reCAPTCHA v2 Gửi biểu mẫu báo giá Nhiều bước (xe + tài xế)
Y tế reCAPTCHA v2 So sánh gói bảo hiểm Nhiều bước (nhân khẩu học)
Nhà ở CAPTCHA hình ảnh Tra cứu địa chỉ Trung bình
Nhân thọ reCAPTCHA v2 Máy tính phí bảo hiểm Biểu mẫu đơn giản
Du lịch reCAPTCHA v2 Invisible Yêu cầu báo giá Biểu mẫu đơn giản
Doanh nghiệp reCAPTCHA v3 Biểu mẫu liên hệ/báo giá Biểu mẫu dài

Vì sao luồng báo giá nhiều bước cần phiên cố định

Quy trình báo giá hiếm khi chỉ có một bước; server gắn mỗi bước với cùng session và IP, đổi IP giữa chừng gần như luôn làm mất session. Một đội QA outsourcing ở TP.HCM kiểm thử báo giá cho khách hàng bảo hiểm Bắc Mỹ thường gặp lỗi này đầu tiên: đổi IP giữa bước "thông tin xe" và bước "chọn phạm vi" khiến phiên bị reset dù chưa gửi báo giá.

Bước Dữ liệu gửi Yêu cầu IP
1. Thông tin cá nhân Họ tên, ngày sinh, mã zip Cùng IP
2. Xe/bất động sản Năm, hãng, mẫu xe Cùng IP
3. Chọn phạm vi bảo hiểm Hạn mức, mức khấu trừ Cùng IP
4. Giải CAPTCHA Token Cùng IP
5. Hiển thị báo giá Cùng IP

Dùng phiên cố định nội bộ với TTL 10-15 phút — đủ hoàn tất 5 bước, đủ ngắn để không giữ session thừa.


Thu thập báo giá bảo hiểm ô tô từ nhiều carrier

Gửi từng bước biểu mẫu, giải reCAPTCHA v2 qua CaptchaAI, rồi so sánh phí và chọn mức thấp nhất:

import requests
import time
import re
import base64

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"

def solve_recaptcha(sitekey, pageurl):
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "userrecaptcha",
        "googlekey": sitekey, "pageurl": pageurl, "json": 1,
    })
    task_id = resp.json()["request"]
    for _ in range(60):
        time.sleep(5)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")

def solve_image_captcha(image_bytes):
    img_b64 = base64.b64encode(image_bytes).decode()
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data={
        "key": CAPTCHAAI_KEY, "method": "base64",
        "body": img_b64, "json": 1,
    })
    task_id = resp.json()["request"]
    for _ in range(20):
        time.sleep(3)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        data = result.json()
        if data["request"] != "CAPCHA_NOT_READY":
            return data["request"]
    raise TimeoutError("Timeout")

class InsuranceQuoteCollector:
    def __init__(self, proxy=None):
        self.session = requests.Session()
        if proxy:
            self.session.proxies = {"http": proxy, "https": proxy}
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
        })

    def get_auto_quote(self, carrier_url, vehicle_data, driver_data, sitekey):
        """Get auto insurance quote from a single carrier."""
        # Step 1: Load quote page
        self.session.get(carrier_url)

        # Step 2: Submit vehicle info
        resp = self.session.post(f"{carrier_url}/vehicle", data=vehicle_data)

        # Step 3: Submit driver info
        resp = self.session.post(f"{carrier_url}/driver", data=driver_data)

        # Step 4: Solve CAPTCHA on quote page
        token = solve_recaptcha(sitekey, f"{carrier_url}/quote")

        # Step 5: Get quote
        resp = self.session.post(f"{carrier_url}/quote", data={
            "g-recaptcha-response": token,
        })

        if resp.status_code == 200:
            return self._parse_quote(resp.text)
        return None

    def compare_carriers(self, carriers, vehicle_data, driver_data):
        """Compare quotes across multiple carriers."""
        quotes = []

        for carrier in carriers:
            try:
                quote = self.get_auto_quote(
                    carrier_url=carrier["url"],
                    vehicle_data=vehicle_data,
                    driver_data=driver_data,
                    sitekey=carrier["sitekey"],
                )
                quotes.append({
                    "carrier": carrier["name"],
                    "status": "success",
                    "quote": quote,
                })
            except Exception as e:
                quotes.append({
                    "carrier": carrier["name"],
                    "status": "failed",
                    "error": str(e),
                })
            time.sleep(5)  # Delay between carriers

        # Sort by price
        successful = [q for q in quotes if q["status"] == "success" and q["quote"]]
        successful.sort(key=lambda x: x["quote"].get("monthly_premium", float("inf")))

        return {
            "quotes": quotes,
            "best_rate": successful[0] if successful else None,
            "total_compared": len(carriers),
            "successful": len(successful),
        }

    def _parse_quote(self, html):
        from bs4 import BeautifulSoup
        soup = BeautifulSoup(html, "html.parser")

        premium_el = soup.select_one(".premium, .monthly-rate, .quote-amount")
        coverage_el = soup.select_one(".coverage-summary, .plan-details")

        return {
            "monthly_premium": premium_el.get_text(strip=True) if premium_el else "",
            "coverage": coverage_el.get_text(strip=True) if coverage_el else "",
        }

# Usage
collector = InsuranceQuoteCollector(
    proxy="http://user-session-abc:[email protected]:5000"
)

vehicle = {
    "year": "2022",
    "make": "Toyota",
    "model": "Camry",
    "vin": "",
    "mileage": "15000",
}

driver = {
    "age": "35",
    "gender": "M",
    "zip": "90210",
    "driving_record": "clean",
}

carriers = [
    {"name": "Carrier A", "url": "https://carrier-a.example.com/auto", "sitekey": "6Lc_xxx1"},
    {"name": "Carrier B", "url": "https://carrier-b.example.com/auto", "sitekey": "6Lc_xxx2"},
    {"name": "Carrier C", "url": "https://carrier-c.example.com/auto", "sitekey": "6Lc_xxx3"},
]

comparison = collector.compare_carriers(carriers, vehicle, driver)
print(f"Best rate: {comparison['best_rate']}")

So sánh gói bảo hiểm y tế

Cổng bảo hiểm y tế bắt nhập nhân khẩu học trước; CAPTCHA xuất hiện ngay trước khi hiển thị gói:

def compare_health_plans(marketplace_url, demographics, sitekey):
    """Compare health insurance plans on marketplace sites."""
    collector = InsuranceQuoteCollector(
        proxy="http://user-session-xyz:[email protected]:5000"
    )

    # Load marketplace
    collector.session.get(marketplace_url)

    # Submit demographics
    collector.session.post(f"{marketplace_url}/demographics", data=demographics)

    # Solve CAPTCHA for plan results
    token = solve_recaptcha(sitekey, f"{marketplace_url}/plans")

    resp = collector.session.post(f"{marketplace_url}/plans", data={
        "g-recaptcha-response": token,
    })

    if resp.status_code == 200:
        from bs4 import BeautifulSoup
        soup = BeautifulSoup(resp.text, "html.parser")
        plans = []
        for card in soup.select(".plan-card, .insurance-plan"):
            plans.append({
                "name": card.select_one(".plan-name").get_text(strip=True) if card.select_one(".plan-name") else "",
                "premium": card.select_one(".premium").get_text(strip=True) if card.select_one(".premium") else "",
                "deductible": card.select_one(".deductible").get_text(strip=True) if card.select_one(".deductible") else "",
            })
        return plans

    return []

Khắc phục sự cố thường gặp

Vấn đề Nguyên nhân Cách xử lý
Biểu mẫu báo giá bị reset giữa chừng IP đổi giữa các bước Dùng phiên cố định nội bộ
"Không thể cung cấp báo giá" Xác thực dữ liệu thất bại Kiểm tra lại các trường bắt buộc
CAPTCHA xuất hiện hai lần Token đầu tiên đã hết hạn Giải lại ngay lập tức
Phí hiển thị khác khi tra thủ công Khác biệt cookie/session Bắt đầu một phiên mới, sạch
Request bị chặn do rate limit Gửi quá nhiều báo giá từ một IP Giãn cách request, đổi IP giữa các carrier

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

Mỗi ngày thu thập được bao nhiêu báo giá bảo hiểm?

Thường 20-50 báo giá mỗi carrier mỗi ngày nếu giãn cách hợp lý; vượt ngưỡng này carrier siết rate limit và tăng tần suất CAPTCHA.

reCAPTCHA v3 trên biểu mẫu doanh nghiệp có khác reCAPTCHA v2 không?

Có phần khác. reCAPTCHA v3 chấm điểm hành vi, không hiện ô xác nhận — nhưng luồng gọi CaptchaAI giống hệt reCAPTCHA v2.

Nhiều carrier cùng lúc có cần gói CaptchaAI lớn không?

Tùy số carrier song song. Với 3-5 carrier như ví dụ trên, BASIC ($15/tháng, 5 thread) thường đủ; 20-30 carrier thì ADVANCE ($90/tháng, 50 thread) phù hợp hơn.

Có thể thử trên staging trước khi thu thập báo giá thật không?

Nên vậy — chạy collector trên URL staging của đội bạn trước khi trỏ sang trang thật.


Hướng dẫn liên quan


So sánh báo giá bảo hiểm ở quy mô lớn — lấy API key CaptchaAI và tự động hóa việc thu thập.

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