Hướng Dẫn Thực Hành

Nhà viết kịch Python + Hướng dẫn tích hợp hoàn chỉnh CaptchaAI

Playwright cung cấp khả năng thực thi nhanh hơn, mặc định có cấu hình QA chuẩn tốt hơn và hỗ trợ không đồng bộ gốc so với Selenium. Hướng dẫn này trình bày cách tích hợp đầy đủ với CaptchaAI để giải quyết reCAPTCHA, Turnstile và CAPTCHA hình ảnh trong tập lệnh tự động hóa Playwright.


Điều kiện tiên quyết

pip install playwright aiohttp
playwright install chromium

Bộ giải CaptchaAI không đồng bộ

import aiohttp
import asyncio

API_KEY = "YOUR_API_KEY"

async def solve_captcha(method, **params):
    """Async CaptchaAI solver for Playwright workflows."""
    async with aiohttp.ClientSession() as session:
        # Submit task
        submit_data = {
            "key": API_KEY,
            "method": method,
            "json": 1,
            **params,
        }
        async with session.post("https://ocr.captchaai.com/in.php", data=submit_data) as resp:
            data = await resp.json(content_type=None)
            if data.get("status") != 1:
                raise Exception(f"Submit error: {data.get('request')}")
            task_id = data["request"]

        # Poll for result
        for _ in range(30):
            await asyncio.sleep(5)
            async with session.get("https://ocr.captchaai.com/res.php", params={
                "key": API_KEY,
                "action": "get",
                "id": task_id,
                "json": 1,
            }) as resp:
                result = await resp.json(content_type=None)
                if result.get("status") == 1:
                    return result["request"]
                if result.get("request") == "ERROR_CAPTCHA_UNSOLVABLE":
                    raise Exception("CAPTCHA unsolvable")

        raise TimeoutError("Solve timed out")

Trình duyệt Playwright có cấu hình QA chuẩn

from playwright.async_api import async_playwright

async def create_browser():
    """Launch Playwright browser with stealth-configuredion settings."""
    pw = await async_playwright().start()
    browser = await pw.chromium.launch(
        headless=False,
        args=[
            "",
        ],
    )
    context = await browser.new_context(
        user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                   "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        viewport={"width": 1920, "height": 1080},
        locale="en-US",
    )

    # Remove Playwright detection signals
    await context.add_init_script("""
        Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
        delete navigator.__proto__.webdriver;
    """)

    page = await context.new_page()
    return pw, browser, context, page

reCAPTCHA v2 với Nhà viết kịch

import re

async def solve_recaptcha_v2_playwright(page, url):
    """Complete reCAPTCHA v2 solve in Playwright."""
    await page.goto(url, wait_until="networkidle")

    # Extract sitekey from the page
    content = await page.content()
    match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]{40})["\']', content)
    if not match:
        raise ValueError("reCAPTCHA sitekey not found")

    sitekey = match.group(1)
    print(f"Sitekey: {sitekey}")

    # Solve via CaptchaAI
    token = await solve_captcha(
        "userrecaptcha",
        googlekey=sitekey,
        pageurl=url,
    )
    print(f"Token: {token[:50]}...")

    # Inject token
    await page.evaluate(f"""() => {{
        document.getElementById('g-recaptcha-response').value = '{token}';
        document.getElementById('g-recaptcha-response').style.display = 'block';
    }}""")

    # Trigger callback if available
    await page.evaluate(f"""() => {{
        if (typeof ___grecaptcha_cfg !== 'undefined') {{
            var clients = ___grecaptcha_cfg.clients;
            for (var key in clients) {{
                var client = clients[key];
                try {{
                    Object.keys(client).forEach(function(k) {{
                        if (client[k] && client[k].callback) {{
                            client[k].callback('{token}');
                        }}
                    }});
                }} catch(e) {{}}
            }}
        }}
    }}""")

    # Submit form
    await page.click("button[type='submit'], input[type='submit']")
    await page.wait_for_load_state("networkidle")

    return token

Cloudflare Turnstile với Nhà viết kịch

async def solve_turnstile_playwright(page, url):
    """Complete Turnstile solve in Playwright."""
    await page.goto(url, wait_until="networkidle")

    content = await page.content()

    # Extract sitekey
    match = re.search(r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', content)
    if not match:
        match = re.search(r"sitekey\s*:\s*['\"]([0-9x][A-Za-z0-9_-]+)['\"]", content)
    if not match:
        raise ValueError("Turnstile sitekey not found")

    sitekey = match.group(1)
    print(f"Turnstile sitekey: {sitekey}")

    # Solve via CaptchaAI
    token = await solve_captcha(
        "turnstile",
        sitekey=sitekey,
        pageurl=url,
    )

    # Inject token into hidden inputs
    await page.evaluate(f"""() => {{
        document.querySelectorAll('[name="cf-turnstile-response"]')
            .forEach(el => el.value = '{token}');
    }}""")

    # Submit
    await page.click("button[type='submit'], input[type='submit']")
    await page.wait_for_load_state("networkidle")

    return token

Hình ảnh CAPTCHA với Nhà viết kịch

async def solve_image_captcha_playwright(page, captcha_selector):
    """Solve image CAPTCHA visible on the page."""
    captcha_element = page.locator(captcha_selector)

    # Screenshot the CAPTCHA image
    img_bytes = await captcha_element.screenshot()
    import base64
    img_base64 = base64.b64encode(img_bytes).decode()

    # Solve via CaptchaAI
    answer = await solve_captcha("base64", body=img_base64)
    print(f"Answer: {answer}")

    # Type the answer
    captcha_input = page.locator("input[name='captcha'], input[name='code'], input.captcha-input")
    await captcha_input.fill(answer)

    return answer

Chặn các yêu cầu mạng

Nhà viết kịch xuất sắc trong việc đánh chặn yêu cầu. Sử dụng nó để trích xuất các tham số CAPTCHA từ lệnh gọi API:

async def intercept_captcha_params(page, url):
    """Intercept network requests to find CAPTCHA parameters."""
    captcha_params = {}

    async def handle_request(route, request):
        if "recaptcha" in request.url or "turnstile" in request.url:
            from urllib.parse import urlparse, parse_qs
            parsed = urlparse(request.url)
            params = parse_qs(parsed.query)
            captcha_params.update(params)
            print(f"Intercepted: {request.url}")
        await route.continue_()

    await page.route("**/*", handle_request)
    await page.goto(url, wait_until="networkidle")
    await page.unroute("**/*")

    return captcha_params

Lớp tự động hóa hoàn chỉnh

import re
import asyncio
import aiohttp
import base64
from playwright.async_api import async_playwright

API_KEY = "YOUR_API_KEY"

class PlaywrightCaptchaSolver:
    """Complete Playwright + CaptchaAI automation class."""

    def __init__(self, api_key, headless=False):
        self.api_key = api_key
        self.headless = headless
        self.pw = None
        self.browser = None
        self.context = None
        self.page = None

    async def start(self):
        """Initialize the browser."""
        self.pw = await async_playwright().start()
        self.browser = await self.pw.chromium.launch(
            headless=self.headless,
            args=[""],
        )
        self.context = await self.browser.new_context(
            user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                       "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
            viewport={"width": 1920, "height": 1080},
        )
        await self.context.add_init_script(
            "Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
        )
        self.page = await self.context.new_page()

    async def stop(self):
        """Close the browser."""
        if self.browser:
            await self.browser.close()
        if self.pw:
            await self.pw.stop()

    async def navigate(self, url):
        """Navigate and wait for page to load."""
        await self.page.goto(url, wait_until="networkidle")

    async def detect_captcha(self):
        """Detect which CAPTCHA type is present."""
        content = await self.page.content()

        if re.search(r'data-sitekey=["\'][A-Za-z0-9_-]{40}["\']', content):
            if "recaptcha" in content.lower():
                return "recaptcha_v2"

        if "cf-turnstile" in content or "challenges.cloudflare.com/turnstile" in content:
            return "turnstile"

        if re.search(r"render=[A-Za-z0-9_-]{40}", content):
            return "recaptcha_v3"

        img_count = await self.page.locator(
            "img.captcha, img[alt*='captcha'], img[src*='captcha']"
        ).count()
        if img_count > 0:
            return "image"

        return None

    async def solve_and_submit(self, url, form_data=None):
        """Full workflow: navigate, detect, solve, fill, submit."""
        await self.navigate(url)
        captcha_type = await self.detect_captcha()

        if captcha_type:
            print(f"Detected: {captcha_type}")
            await self._solve(captcha_type)

        if form_data:
            for name, value in form_data.items():
                try:
                    await self.page.fill(f"[name='{name}']", value)
                except Exception:
                    pass

        await self.page.click("button[type='submit'], input[type='submit']")
        await self.page.wait_for_load_state("networkidle")
        return self.page.url

    async def _solve(self, captcha_type):
        content = await self.page.content()
        url = self.page.url

        if captcha_type == "recaptcha_v2":
            match = re.search(r'data-sitekey=["\']([A-Za-z0-9_-]{40})["\']', content)
            token = await self._api_solve("userrecaptcha", googlekey=match.group(1), pageurl=url)
            await self.page.evaluate(f"""() => {{
                document.getElementById('g-recaptcha-response').value = '{token}';
            }}""")

        elif captcha_type == "turnstile":
            match = re.search(r'data-sitekey=["\']([0-9x][A-Za-z0-9_-]+)["\']', content)
            token = await self._api_solve("turnstile", sitekey=match.group(1), pageurl=url)
            await self.page.evaluate(f"""() => {{
                document.querySelectorAll('[name="cf-turnstile-response"]')
                    .forEach(el => el.value = '{token}');
            }}""")

        elif captcha_type == "image":
            img = self.page.locator("img.captcha, img[alt*='captcha'], img[src*='captcha']").first
            img_bytes = await img.screenshot()
            answer = await self._api_solve("base64", body=base64.b64encode(img_bytes).decode())
            await self.page.fill("input[name='captcha'], input[name='code']", answer)

    async def _api_solve(self, method, **params):
        async with aiohttp.ClientSession() as session:
            async with session.post("https://ocr.captchaai.com/in.php", data={
                "key": self.api_key, "method": method, "json": 1, **params,
            }) as resp:
                data = await resp.json(content_type=None)
                if data.get("status") != 1:
                    raise Exception(f"Submit error: {data.get('request')}")
                task_id = data["request"]

            for _ in range(30):
                await asyncio.sleep(5)
                async with session.get("https://ocr.captchaai.com/res.php", params={
                    "key": self.api_key, "action": "get", "id": task_id, "json": 1,
                }) as resp:
                    result = await resp.json(content_type=None)
                    if result.get("status") == 1:
                        return result["request"]
            raise TimeoutError("Solve timed out")

# Usage
async def main():
    solver = PlaywrightCaptchaSolver(API_KEY)
    await solver.start()
    try:
        result = await solver.solve_and_submit(
            "https://staging.example.com/qa-login",
            form_data={"email": "user@example.com", "password": "pass123"},
        )
        print(f"Result: {result}")
    finally:
        await solver.stop()

asyncio.run(main())

Nhà viết kịch vs Selenium để giải CAPTCHA

tính năng Nhà viết kịch Selen
Gốc không đồng bộ Không (yêu cầu phân luồng)
cấu hình tàng hình Mặc định tốt hơn Yêu cầu cấu hình nhiều hơn
Tốc độ Nhanh hơn Tải trang chậm hơn
Yêu cầu chặn Tích hợp sẵn Yêu cầu proxy/extension
Đa trình duyệt Crom, Firefox, WebKit Chrome, Firefox, Edge, Safari
Kiểu API Dựa trên lời hứa, hiện đại Bắt buộc, truyền thống

Khắc phục sự cố

Triệu chứng nguyên nhân sửa chữa
page.evaluate không thành công Nội dung chưa được tải Sử dụng wait_until="networkidle"
Việc tiêm mã thông báo không hoạt động Bộ chọn phần tử sai Kiểm tra bằng page.content() để tìm phần tử thực tế
Phát hiện nhà viết kịch Thiếu tập lệnh init Thêm ghi đè webdriver trong add_init_script
Hết thời gian chờ trên networkidle Kịch bản bỏ phiếu vô hạn Thay vào đó hãy sử dụng wait_until="domcontentloaded"
Ảnh chụp màn hình trống Phần tử bị ẩn Cuộn vào chế độ xem: await element.scroll_into_view_if_needed()

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

Tôi nên sử dụng Playwright hay Selenium để giải CAPTCHA?

Sử dụng Playwright cho các dự án mới - nó có hiệu suất tốt hơn, hỗ trợ không đồng bộ gốc và các giá trị mặc định có cấu hình QA chuẩn tốt hơn. Hãy sử dụng Selenium nếu bạn có cơ sở mã Selenium hiện có.

Nhà viết kịch có thể chạy ở chế độ headless không?

Vâng. Đặt headless=True trong launch(). Một số trang web phát hiện chế độ không có giao diện người dùng, vì vậy hãy kiểm tra cả hai cấu hình. CaptchaAI giải quyết trên cơ sở hạ tầng của chính nó, do đó không có đầu so với có đầu không ảnh hưởng đến thành công của giải pháp.

Làm cách nào để xử lý các trang tải CAPTCHA động?

Sử dụng page.wait_for_selector để đợi phần tử CAPTCHA xuất hiện hoặc sử dụng page.wait_for_function để đợi JavaScript CAPTCHA sẵn sàng.


Tóm tắt

Nhà viết kịch Python +CaptchaAIcung cấp ngăn xếp tự động hóa CAPTCHA không đồng bộ hiện đại. Sử dụng PlaywrightCaptchaSolver để có quy trình phát hiện-giải quyết-gửi hoàn chỉnh với hỗ trợ không đồng bộ gốc, chặn yêu cầu và mặc định cấu hình QA chuẩn mạnh mẽ.

bài viết liên quan

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