التكاملات

سلك السيلينيوم + CaptchaAI: طلب اعتراض لحل اختبار CAPTCHA

يعمل Selenium Wire على توسيع السيلينيوم مع القدرة على اعتراض طلبات HTTP وتعديلها - وهو أمر لا يستطيع السيلينيوم القياسي القيام به. يؤدي هذا إلى فتح مسارات عمل قوية لحل اختبار CAPTCHA: استخراج مفاتيح الموقع من مكالمات API، وحقن الرموز المميزة في الاستجابات التي تم اعتراضها، وتوجيه الطلبات من خلال الوكلاء.

يغطي هذا الدليل اعتراض الطلبات، واكتشاف اختبار CAPTCHA من حركة مرور الشبكة، وتكامل الوكيل، والحل الآلي باستخدام CaptchaAI.


ما يضيفه سلك السيلينيوم

ميزة السيلينيوم القياسي سلك السيلينيوم
قراءة الطلبات لا نعم
تعديل الرؤوس محدودة السيطرة الكاملة
اعتراض الردود لا نعم
دعم الوكيل الأساسية دعم الوكيل المصادقة
تسجيل الشبكة أدوات التطوير فقط كائنات بايثون
تصدير هار لا نعم

الإعداد

pip install seleniumwire selenium webdriver-manager requests

التكامل الأساسي

from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import requests
import time
import json

class SeleniumWireCaptchaSolver:
    BASE_URL = "https://ocr.captchaai.com"

    def __init__(self, api_key, proxy=None):
        self.api_key = api_key
        self.proxy = proxy
        self.driver = None

    def create_driver(self, headless=True):
        options = webdriver.ChromeOptions()
        if headless:
            options.add_argument("--headless=new")
        options.add_argument("--no-sandbox")
        options.add_argument("--disable-blink-features=AutomationControlled")
        options.add_argument("--window-size=1920,1080")

        wire_options = {}
        if self.proxy:
            wire_options["proxy"] = {
                "http": self.proxy,
                "https": self.proxy,
            }

        self.driver = webdriver.Chrome(
            service=Service(ChromeDriverManager().install()),
            options=options,
            seleniumwire_options=wire_options,
        )
        return self.driver

    def detect_captcha_from_requests(self):
        """Detect CAPTCHA type from intercepted network requests."""
        for request in self.driver.requests:
            url = request.url

            if "recaptcha/api2/anchor" in url or "recaptcha/enterprise/anchor" in url:
                # Extract sitekey from reCAPTCHA iframe URL
                import re
                match = re.search(r"k=([A-Za-z0-9_-]+)", url)
                if match:
                    return {
                        "type": "recaptcha_v2",
                        "sitekey": match.group(1),
                        "page_url": self.driver.current_url,
                    }

            if "recaptcha/api2/reload" in url or "recaptcha/enterprise/reload" in url:
                return {
                    "type": "recaptcha_v3",
                    "sitekey": self._extract_v3_sitekey(),
                    "page_url": self.driver.current_url,
                }

            if "challenges.cloudflare.com" in url:
                sitekey = self._extract_turnstile_sitekey()
                if sitekey:
                    return {
                        "type": "turnstile",
                        "sitekey": sitekey,
                        "page_url": self.driver.current_url,
                    }

        return None

    def _extract_v3_sitekey(self):
        for request in self.driver.requests:
            if "recaptcha" in request.url and "render=" in request.url:
                import re
                match = re.search(r"render=([A-Za-z0-9_-]+)", request.url)
                if match:
                    return match.group(1)
        return self.driver.execute_script(
            "return document.querySelector('[data-sitekey]')?.getAttribute('data-sitekey')"
        )

    def _extract_turnstile_sitekey(self):
        return self.driver.execute_script(
            "return document.querySelector('.cf-turnstile[data-sitekey]')?.getAttribute('data-sitekey')"
        )

    def solve_captcha(self, captcha_info):
        """Solve detected CAPTCHA via CaptchaAI API."""
        params = {"key": self.api_key, "json": 1}

        if captcha_info["type"] == "recaptcha_v2":
            params.update({
                "method": "userrecaptcha",
                "googlekey": captcha_info["sitekey"],
                "pageurl": captcha_info["page_url"],
            })
        elif captcha_info["type"] == "recaptcha_v3":
            params.update({
                "method": "userrecaptcha",
                "googlekey": captcha_info["sitekey"],
                "pageurl": captcha_info["page_url"],
                "version": "v3",
                "action": "verify",
            })
        elif captcha_info["type"] == "turnstile":
            params.update({
                "method": "turnstile",
                "key": captcha_info["sitekey"],
                "pageurl": captcha_info["page_url"],
            })

        # Submit
        resp = requests.post(f"{self.BASE_URL}/in.php", data=params)
        data = resp.json()
        if data["status"] != 1:
            raise Exception(f"Submit: {data['request']}")

        task_id = data["request"]

        # Poll
        for _ in range(60):
            time.sleep(5)
            resp = requests.get(f"{self.BASE_URL}/res.php", params={
                "key": self.api_key,
                "action": "get",
                "id": task_id,
                "json": 1,
            })
            data = resp.json()
            if data["request"] == "CAPCHA_NOT_READY":
                continue
            if data["status"] != 1:
                raise Exception(f"Solve: {data['request']}")
            return data["request"]

        raise Exception("Timeout")

    def inject_token(self, captcha_type, token):
        """Inject solved token into the page."""
        if captcha_type in ("recaptcha_v2", "recaptcha_v3"):
            self.driver.execute_script(f"""
                document.querySelector('#g-recaptcha-response').value = '{token}';
                // Try hidden textareas in iframes
                document.querySelectorAll('[name="g-recaptcha-response"]').forEach(
                    el => el.value = '{token}'
                );
            """)
        elif captcha_type == "turnstile":
            self.driver.execute_script(f"""
                const input = document.querySelector('[name="cf-turnstile-response"]');
                if (input) input.value = '{token}';
            """)

    def close(self):
        if self.driver:
            self.driver.quit()

سير العمل الكامل

def automate_login():
    solver = SeleniumWireCaptchaSolver(
        api_key="YOUR_API_KEY",
        proxy="http://user:pass@proxy.example.com:8080"
    )

    try:
        driver = solver.create_driver(headless=True)

        # Navigate and wait for CAPTCHA resources to load
        driver.get("https://example.com/login")
        time.sleep(3)

        # Fill form
        driver.find_element("id", "email").send_keys("user@example.com")
        driver.find_element("id", "password").send_keys("password123")

        # Detect CAPTCHA from network requests
        captcha = solver.detect_captcha_from_requests()

        if captcha:
            print(f"Found {captcha['type']} (sitekey: {captcha['sitekey'][:20]}...)")
            token = solver.solve_captcha(captcha)
            solver.inject_token(captcha["type"], token)
            print(f"Token injected: {token[:50]}...")

        # Submit
        driver.find_element("id", "submit").click()
        time.sleep(3)

        print(f"Current URL: {driver.current_url}")

    finally:
        solver.close()

automate_login()

اعتراض الطلبات وتعديلها

إضافة رؤوس مخصصة

def add_headers_interceptor(request):
    request.headers["X-Custom-Header"] = "value"
    request.headers["Accept-Language"] = "en-US,en;q=0.9"

driver = solver.create_driver()
driver.request_interceptor = add_headers_interceptor

حظر البرامج النصية للتتبع

def block_trackers(request):
    blocked = ["analytics", "tracking", "ads", "facebook.net", "doubleclick"]
    if any(b in request.url for b in blocked):
        request.abort()

driver.request_interceptor = block_trackers

تعديل محتوى الاستجابة

def modify_response(request, response):
    if "captcha-config" in request.url:
        # Modify CAPTCHA configuration response
        import json
        body = json.loads(response.body.decode("utf-8"))
        body["difficulty"] = "easy"
        response.body = json.dumps(body).encode("utf-8")

driver.response_interceptor = modify_response

استخراج معلمات CAPTCHA من استدعاءات API

تقوم بعض المواقع بتحميل معلمات CAPTCHA عبر AJAX. يلتقط سلك السيلينيوم ما يلي:

def extract_captcha_from_api(driver, timeout=10):
    """Watch network for CAPTCHA configuration API calls."""
    start = time.time()

    while time.time() - start < timeout:
        for request in driver.requests:
            if request.response and "captcha" in request.url.lower():
                try:
                    data = json.loads(request.response.body.decode())
                    if "sitekey" in str(data) or "siteKey" in str(data):
                        return data
                except (json.JSONDecodeError, UnicodeDecodeError):
                    pass
        time.sleep(0.5)

    return None

تناوب الوكيل لكل طلب

from seleniumwire import webdriver

proxies = [
    "http://user:pass@proxy1.example.com:8080",
    "http://user:pass@proxy2.example.com:8080",
    "http://user:pass@proxy3.example.com:8080",
]

current_proxy = [0]

def rotate_proxy(request):
    proxy = proxies[current_proxy[0] % len(proxies)]
    request.headers["Proxy-Authorization"] = None  # Reset
    current_proxy[0] += 1

wire_options = {
    "proxy": {
        "http": proxies[0],
        "https": proxies[0],
    }
}

driver = webdriver.Chrome(seleniumwire_options=wire_options)

تحليل حركة مرور الشبكة

def analyze_captcha_traffic(driver):
    """Analyze all CAPTCHA-related network traffic."""
    captcha_requests = []

    for request in driver.requests:
        if any(k in request.url for k in ["recaptcha", "turnstile", "hcaptcha", "geetest"]):
            captcha_requests.append({
                "url": request.url,
                "method": request.method,
                "status": request.response.status_code if request.response else None,
                "content_type": request.response.headers.get("Content-Type") if request.response else None,
                "size": len(request.response.body) if request.response and request.response.body else 0,
            })

    print(f"\nCAPTCHA Network Traffic ({len(captcha_requests)} requests):")
    for req in captcha_requests:
        print(f"  [{req['status']}] {req['method']} {req['url'][:80]}...")

    return captcha_requests

تصدير HAR لتصحيح الأخطاء

from seleniumwire.utils import decode

def export_har(driver, filename="captcha_traffic.har"):
    """Export HAR file for debugging CAPTCHA issues."""
    import json

    har = {
        "log": {
            "version": "1.2",
            "entries": []
        }
    }

    for request in driver.requests:
        if not request.response:
            continue

        entry = {
            "request": {
                "method": request.method,
                "url": request.url,
                "headers": [{"name": k, "value": v} for k, v in request.headers.items()],
            },
            "response": {
                "status": request.response.status_code,
                "headers": [{"name": k, "value": v} for k, v in request.response.headers.items()],
            },
        }
        har["log"]["entries"].append(entry)

    with open(filename, "w") as f:
        json.dump(har, f, indent=2)

    print(f"HAR exported: {filename} ({len(har['log']['entries'])} entries)")

استكشاف الأخطاء وإصلاحها

المشكلة السبب الإجراء
خطأ في استيراد seleniumwire غير مثبت pip install seleniumwire
لم يتم التقاط أي طلبات تم تحميل الصفحة بسرعة كبيرة جدًا أضف time.sleep(3) بعد التنقل
أخطاء SSL مع الوكيل قضايا الشهادات قم بتعيين seleniumwire_options['verify_ssl'] = False
تسرب الذاكرة طلب التخزين ينمو اتصل بـ del driver.requests بشكل دوري
تحميل الصفحات البطيء كل حركة المرور بالوكالة استخدم exclude_hosts في خيارات الأسلاك
لم يتم اكتشاف اختبار CAPTCHA تم التحميل عبر iframe تحقق من driver.requests لعناوين URL الخاصة بـ iframe

الأسئلة الشائعة

ما الفرق بين سلك السيلينيوم والسيلينيوم القياسي؟

يقوم سلك السيلينيوم بتغليف برنامج Selenium WebDriver لإضافة اعتراض HTTP request/response. إنه بديل سهل الاستخدام - نفس واجهة برمجة التطبيقات (API) مع إمكانات شبكة إضافية.

متى يجب علي استخدام سلك السيلينيوم مقابل Puppeteer؟

استخدم Selenium Wire لمشاريع Python التي تحتاج إلى اعتراض الطلب. استخدم Puppeteer (Node.js) إذا كنت موجودًا بالفعل في نظام JavaScript البيئي.

هل يعمل سلك السيلينيوم مع محرك الكروم الذي لم يتم اكتشافه؟

نعم. استبدل webdriver.Chrome بـ uc.Chrome من برنامج التشغيل الكرومي الذي لم يتم اكتشافه مع الاحتفاظ بميزات اعتراض سلك السيلينيوم.

كيف يساعد اعتراض الطلب في اختبارات CAPTCHA؟

فهو يتيح لك اكتشاف أنواع اختبار CAPTCHA من حركة مرور الشبكة (أكثر موثوقية من تحليل DOM)، واستخراج المعلمات من استجابات واجهة برمجة التطبيقات، وإدخال الرموز المميزة في الطلبات التي تم اعتراضها.


أدلة ذات صلة

  • بايثون السيلينيوم + CaptchaAI دليل التكامل الكامل
  • بروتوكول Chrome DevTools + CaptchaAI: أتمتة اختبار CAPTCHA منخفض المستوى

اعتراض الطلب الرئيسي لأتمتة اختبار CAPTCHA –احصل على مفتاح CaptchaAI الخاص بكوقم بالبناء باستخدام سلك السيلينيوم.

التعليقات غير مفعّلة لهذا المقال.