دليل Selenium الشامل للمصادقة على البروكسي والتخفي: من التكوين إلى التوسع

تعلّم كيف تُعدّل Selenium مع بروكسي مُصادَق عليه باستخدام selenium-wire وFirefox profiles، وتقلّل البصمات بـ selenium-stealth، وتوسّع العمليات عبر Selenium Grid والحاويات.

دليل Selenium الشامل للمصادقة على البروكسي والتخفي: من التكوين إلى التوسع

المشكلة: لماذا لا يتوافق Selenium مع البروكسي المُصادَق بسهولة

إذا حاولت يوماً تمرير بروكسي سكني يتطلب مصادقة إلى Selenium عبر --proxy-server، فستواجه على الفور نافذة مصادقة منبثقة لا يستطيع WebDriver التعامل معها. السبب بسيط: Chromium وFirefox لا يدعمان تمرير اسم المستخدم وكلمة المرور في عنوان البروكسي عبر سطر الأوامر. هذه ثغرة معروفة تؤرق فرق ضمان الجودة ومهندسي الاستخراج على حد سواء.

تتفاقم المشكلة مع Selenium residential proxies لأن معظم مزوّدي البروكسي السكني يفرضون المصادقة كطبقة أمان أولى. بدون حل صحيح، ستجد نفسك عالقاً بين بروكسي لا يعمل أو اختبارات تفشل بصمت.

في هذا الدليل، نتعمق في كل نقطة اتصال بين Selenium والبروكسي: من المصادقة عبر selenium-wire، إلى إنشاء ملفات Firefox، مروراً بـ Selenium stealth لتقليل البصمات، وصولاً إلى أنماط التوسع عبر Selenium Grid والحاويات.

Chrome + selenium-wire: المصادقة على البروكسي بدون تعقيد

مكتبة selenium-wire توسّع WebDriver بحيث تمرّر جميع الطلبات عبر بروكسي HTTP/SOCKS مع مصادقة كاملة. المبدأ بسيط: بدلاً من حقن إعدادات البروكسي في المتصفح، تعترض selenium-wie الطلبات على مستوى بايثون وتُوجّهها عبر البروكسي مع بيانات الاعتماد.

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

pip install selenium-wire selenium

مثال كامل: Chrome مع بروكسي سكني مُصادَق من ProxyHat

from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options

proxy_opts = {
    'proxy': {
        'http': 'http://user-country-US:PASSWORD@gate.proxyhat.com:8080',
        'https': 'http://user-country-US:PASSWORD@gate.proxyhat.com:8080',
        'no_proxy': 'localhost,127.0.0.1'
    }
}

chrome_opts = Options()
chrome_opts.add_argument('--disable-blink-features=AutomationControlled')
chrome_opts.add_argument('--window-size=1920,1080')

# تعطيل علامة automation
chrome_opts.add_experimental_option('excludeSwitches', ['enable-automation'])
chrome_opts.add_experimental_option('useAutomationExtension', False)

driver = webdriver.Chrome(
    options=chrome_opts,
    seleniumwire_options=proxy_opts
)

driver.get('https://httpbin.org/ip')
print(driver.find_element('tag name', 'body').text)
driver.quit()

الميزة الكبرى هنا: لا حاجة لأي إضافة متصفح أو معالجة نافذة المصادقة. selenium-wire يتولى كل شيء على مستوى الشبكة. يمكنك أيضاً تحديد المدينة عبر علم اسم المستخدم:

# بروكسي سكني في برلين
'http': 'http://user-country-DE-city-berlin:PASSWORD@gate.proxyhat.com:8080'

نصيحة: استخدم علم session- في اسم المستخدم للحفاظ على جلسة لاصقة (sticky session) مدتها حتى 30 دقيقة، مما يقلل من تشغيل CAPTCHA أثناء التنقل بين الصفحات.

Firefox: إنشاء ملف تعريف مع بروكسي مدمج

عندما لا يكون selenium-wier خياراً مناسباً — مثلاً في بيئات لا تدعم تعديل الطلبات برمجياً — يبقى Firefox مع ملف تعريف مُعد مسبقاً حلاً موثوقاً. الفكرة: نُنشئ ملف تعريف Firefox، نضبط إعدادات البروكسي فيه، ثم نشغّل WebDriver مع هذا الملف.

from selenium import webdriver
from selenium.webdriver.firefox.service import Service
import tempfile, os

# إنشاء ملف تعريف مؤقت
profile_dir = tempfile.mkdtemp()

# كتابة إعدادات البروكسي في prefs.js
prefs_path = os.path.join(profile_dir, 'user.js')
with open(prefs_path, 'w') as f:
    f.write('''
user_pref("network.proxy.type", 1);
user_pref("network.proxy.http", "gate.proxyhat.com");
user_pref("network.proxy.http_port", 8080);
user_pref("network.proxy.ssl", "gate.proxyhat.com");
user_pref("network.proxy.ssl_port", 8080);
user_pref("network.proxy.no_proxies_on", "localhost, 127.0.0.1");
user_pref("network.http.proxy-chunked-size", 0);
''')

# تفعيل مصادقة البروكسي عبر ترويسة Authorization المُشفّرة
import base64
creds = base64.b64encode(b'user-country-US:PASSWORD').decode()

# إضافة امتداد صغير لحقن بيانات الاعتماد
ext_dir = os.path.join(profile_dir, 'proxy_auth_ext')
os.makedirs(ext_dir, exist_ok=True)

manifest = '''
{
  "manifest_version": 2,
  "name": "Proxy Auth Helper",
  "version": "1.0",
  "background": {
    "scripts": ["background.js"]
  },
  "permissions": ["webRequest", "webRequestBlocking", "<all_urls>"]
}
'''

bg_script = f'''
chrome.webRequest.onAuthRequired.addListener(
  function(details) {{
    return {{ authCredentials: {{ username: "user-country-US", password: "PASSWORD" }} }};
  }},
  {{ urls: ["<all_urls>"] }},
  ["blocking"]
);
'''

with open(os.path.join(ext_dir, 'manifest.json'), 'w') as f:
    f.write(manifest)
with open(os.path.join(ext_dir, 'background.js'), 'w') as f:
    f.write(bg_script)

options = webdriver.FirefoxOptions()
options.add_argument('-profile')
options.add_argument(profile_dir)

driver = webdriver.Firefox(options=options)
driver.get('https://httpbin.org/ip')
print(driver.find_element('tag name', 'body').text)
driver.quit()

هذا النهج أطول لكنه لا يعتمد على مكتبات خارجية تتعارض مع إصدارات Selenium. يُفضّل في بيئات الإنتاج المستقرة حيث لا يتغير إصدار Firefox بكثرة.

Selenium stealth: تقليل بصمات الأتمتة

حتى مع بروكسي سكني، يمكن للمواقع اكتشاف Selenium عبر مؤشرات متعددة: navigator.webdriver=true، خاصية window.chrome مفقودة، كائنات Permissions غير طبيعية، وغيرها. هنا يأتي دور Selenium stealth.

selenium-stealth لمتصفح Chrome

مكتبة undetected-chromedriver (المعروفة أيضاً بـ uc) هي الخيار الأكثر تطوراً. لكن لمن يفضّل التحكم اليدوي، توفر selenium-stealth واجهة أبسط:

from selenium import webdriver
from selenium_stealth import stealth

options = webdriver.ChromeOptions()
options.add_argument('--headless=new')
options.add_argument('--disable-blink-features=AutomationControlled')
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_experimental_option('useAutomationExtension', False)

driver = webdriver.Chrome(options=options)

# تطبيق التخفي بعد إنشاء المتصفح
stealth(driver,
    languages=["en-US", "en"],
    vendor="Google Inc.",
    platform="Win32",
    webgl_vendor="Intel Inc.",
    renderer="Intel Iris OpenGL Engine",
    fix_hairline=True,
)

# التحقق من نجاح التخفي
driver.get('https://bot.sannysoft.com/')
print('WebDriver flag:', driver.execute_script('return navigator.webdriver'))
driver.quit()

selenium-driverless: الجيل التالي

مكتبة selenium-driverless تتجاوز CDP التقليدي وتستخدم DevTools Protocol مباشرة عبر WebSocket، مما يجعل الكشف عن الأتمتة أصعب بكثير. ميزتها الكبرى: لا تُنشئ أي ملف debug.log يكشف أن المتصفح يُدار آلياً.

from selenium_driverless import webdriver as dl_webdriver
from selenium_driverless.webdriver import ChromeOptions as DLOptions

proxy_url = 'http://user-country-GB:PASSWORD@gate.proxyhat.com:8080'

opts = DLOptions()
opts.add_argument(f'--proxy-server={proxy_url}')

async def main():
    driver = await dl_webdriver.Chrome(options=opts)
    await driver.get('https://nowsecure.nl/')
    content = await driver.page_source
    print('Page loaded successfully')
    await driver.quit()

import asyncio
asyncio.run(main())

ملاحظة مهمة: selenium-driverless يعمل بشكل غير متزامن (async). إذا كان كودك الحالي متزامناً، ستحتاج إلى تعديل البنية أو استخدام undetected-chromedriver كبديل أبسط.

نمط تجمع البروكسي الدوار: IP جديد لكل جلسة

عند استخراج البيانات بمعدل مرتفع، تحتاج إلى IP جديد لكل جلسة WebDriver. أفضل ممارسة: مصنع جلسات يُنشئ متصفحاً جديداً مع بروكسي جديد في كل مرة.

التصميم

المبدأ بسيط: بدلاً من إعادة استخدام المتصفح، نُنشئ واحدة جديدة لكل مهمة مع علم session- فريد في اسم مستخدم البروكسي. هذا يضمن IP جديداً مع كل جلسة.

import uuid
from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options

class ProxySessionFactory:
    """مصنع جلسات WebDriver مع بروكسي دوار"""

    def __init__(self, base_user: str, password: str, country: str = 'US'):
        self.base_user = base_user
        self.password = password
        self.country = country
        self._active_drivers = []

    def _build_proxy_opts(self, session_id: str) -> dict:
        username = f'{self.base_user}-country-{self.country}-session-{session_id}'
        proxy_url = f'http://{username}:{self.password}@gate.proxyhat.com:8080'
        return {
            'proxy': {
                'http': proxy_url,
                'https': proxy_url,
                'no_proxy': 'localhost,127.0.0.1'
            }
        }

    def create_session(self) -> webdriver.Chrome:
        session_id = uuid.uuid4().hex[:12]
        proxy_opts = self._build_proxy_opts(session_id)

        chrome_opts = Options()
        chrome_opts.add_argument('--disable-blink-features=AutomationControlled')
        chrome_opts.add_argument('--window-size=1920,1080')
        chrome_opts.add_experimental_option('excludeSwitches', ['enable-automation'])

        driver = webdriver.Chrome(
            options=chrome_opts,
            seleniumwire_options=proxy_opts
        )
        self._active_drivers.append(driver)
        return driver

    def cleanup_all(self):
        for driver in self._active_drivers:
            try:
                driver.quit()
            except Exception:
                pass
        self._active_drivers.clear()

# --- الاستخدام ---
factory = ProxySessionFactory(
    base_user='myuser',
    password='mypassword',
    country='DE'
)

# كل جلسة تحصل على IP مختلف
driver1 = factory.create_session()
driver1.get('https://httpbin.org/ip')  # IP ألماني #1

driver2 = factory.create_session()
driver2.get('https://httpbin.org/ip')  # IP ألماني #2

factory.cleanup_all()

هذا النمط مثالي لـ استخراج البيانات حيث تحتاج إلى طلبات من IPs متعددة دون ربطها ببعضها. مع بروكسي سكني من ProxyHat، كل IP سيكون عنوان IP منزلي حقيقي في الدولة المحددة.

Selenium Grid والتوسع بالحاويات

عندما تحتاج إلى تشغيل عشرات المتصفحات بالتوازي، يصبح التشغيل المحلي غير عملي. هنا يأتي دور Selenium Grid مع Docker.

بنية Docker Compose

الإعداد التالي يُنشئ شبكة Selenium مع 4 عُقد Chrome، كل منها يمكنه استقبال جلسات WebDriver مع بروكسي:

# docker-compose.yml
version: '3.8'
services:
  selenium-hub:
    image: selenium/hub:4.18
    ports:
      - '4442:4442'
      - '4443:4443'
      - '4444:4444'
    environment:
      - SE_SESSION_REQUEST_TIMEOUT=300
      - SE_NODE_SESSION_TIMEOUT=300

  chrome-node-1:
    image: selenium/node-chrome:4.18
    depends_on:
      - selenium-hub
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_MAX_SESSIONS=2
      - SE_NODE_OVERRIDE_MAX_SESSIONS=true
    deploy:
      replicas: 4

  # خدمة العميل التي تُشغّل المهام
  scraper:
    build: .
    depends_on:
      - selenium-hub
    environment:
      - HUB_URL=http://selenium-hub:4444/wd/hub
      - PROXY_USER=user-country-US
      - PROXY_PASS=PASSWORD

الاتصال بالشبكة من بايثون

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from seleniumwire import webdriver as sw_webdriver
import os

hub_url = os.getenv('HUB_URL', 'http://localhost:4444/wd/hub')
proxy_user = os.getenv('PROXY_USER', 'user-country-US')
proxy_pass = os.getenv('PROXY_PASS', 'PASSWORD')

proxy_opts = {
    'proxy': {
        'http': f'http://{proxy_user}:{proxy_pass}@gate.proxyhat.com:8080',
        'https': f'http://{proxy_user}:{proxy_pass}@gate.proxyhat.com:8080',
    }
}

chrome_opts = Options()
chrome_opts.add_argument('--disable-blink-features=AutomationControlled')

# الاتصال بالعُقدة عبر Grid
driver = sw_webdriver.Chrome(
    options=chrome_opts,
    seleniumwire_options=proxy_opts,
    command_executor=hub_url
)

driver.get('https://httpbin.org/ip')
print(driver.find_element('tag name', 'body').text)
driver.quit()

نصائح التوسع

  • التحكم بالتزامن: اضبط SE_NODE_MAX_SESSIONS حسب ذاكرة كل حاوية (2 جلسة لكل 2GB RAM تقريباً).
  • الإيقاف التدريجي: استخدم SE_DRAIN_AFTER_SESSION_COUNT لإيقاف العُقد بعد عدد معين من الجلسات، مما يمنع تسرب الذاكرة.
  • مراقبة الصحة: أضف حاوية Prometheus + Grafana لمراقبة معدل نجاح الجلسات وزمن الاستجابة.
  • تدوير البروكسي: كل حاوية يمكنها استخدام علم session- مختلف، مما يضمن تنوع IPs حتى مع إعادة استخدام الحاويات.

لمزيد من التفاصيل حول المواقع المتاحة، راجع صفحة مواقع البروكسي.

مقارنة: متى تختار Playwright بدلاً من Selenium

Playwright من Microsoft أصبح منافساً قوياً لـ Selenium. لكن القرار ليس دائماً واضحاً. إليك المقارنة التفصيلية:

المعيار Selenium Playwright
دعم المصادقة على البروكسي يحتاج selenium-wire أو إضافة متصفح مدعوم أصلاً عبر proxy.username و proxy.password
التخفي المدمج يحتاج selenium-stealth أو undetected-chromedriver أفضل بصمة أولية، لكن لا يزال قابلاً للاكتشاف
النضج البيئي 20+ سنة، دعم واسع في السحابة (BrowserStack, Sauce Labs) أحدث، دعم سحابي محدود
التوافق القديم ممتاز — يعمل مع كل إصدارات المتصفحات يتطلب إصدارات حديثة من المتصفحات
التوازي المدمج يحتاج Selenium Grid مدعوم أصلاً عبر BrowserContext
سرعة التنفيذ أبطأ بسبب JSON Wire Protocol أسرع بفضل CDP المباشر
لغات البرمجة Java, Python, JS, C#, Ruby, PHP, Perl Python, JS/TS, Java, C#
مكتبات التخفي المتقدمة undetected-chromedriver, selenium-driverless playwright-stealth (أقل تطوراً)

متى تختار Playwright

  • مشروع جديد بدون كود Selenium قائم — ابدأ بـ Playwright للحصول على دعم أصلي للبروكسي وأداء أفضل.
  • تحتاج مصادقة بروكسي بسيطة — لا حاجة لمكتبات إضافية.
  • التوازي العالي بدون Grid — BrowserContext يُغنيك عن بنية تحتية معقدة.

متى تختار Selenium

  • كود قائم — الترحيل مكلف، خاصة مع آلاف الاختبارات.
  • بيئات اختبار سحابية — BrowserStack وSauce Labs متكاملان بشكل أفضل مع Selenium.
  • الحاجة لأقصى تخفي — undetected-chromedriver وselenium-driverless أكثر تطوراً من أي بديل لـ Playwright.
  • متطلبات متصفحات غريبة — Selenium يدعم متصفحات أكثر عبر WebDriver البعيد.

الخلاصة: إذا كان مشروعك جديداً تماماً ولا تحتاج لمكتبات تخفي متقدمة، فـ Playwright خيار أفضل. أما إذا كنت تدير بنية Selenium قائمة أو تحتاج أقصى حماية من الاكتشاف، فابقَ على Selenium مع الأدوات المذكورة في هذا الدليل.

أفضل الممارسات لاستخدام البروكسي السكني مع Selenium

  • استخدم بروكسي سكني بدلاً من بروكسي مركز بيانات عند التعامل مع مواقع لديها حماية متقدمة — IPs المنزلية أقل عرضة للحظر. راجع خطط الأسعار للمقارنة.
  • غيّر الجلسة دورياً — حتى مع بروكسي سكني، لا تستخدم نفس IP لأكثر من 200 طلب على نفس الموقع.
  • فعّل التخفي — البروكسي السكني وحده لا يكفي إذا كان navigator.webdriver=true يكشفك.
  • احترم robots.txt و شروط الخدمة — الاستخراج غير المصرح به قد ينتهك شروط الموقع أو القوانين المحلية مثل GDPR وCCPA.
  • راقب معدل النجاح — إذا انخفض عن 90%، غيّر IP أو أضف تأخيراً بين الطلبات.
  • استخدم SOCKS5 عند الحاجة — للمواقع التي تحظر بروكسي HTTP، جرب socks5://user-country-US:PASSWORD@gate.proxyhat.com:1080.

النقاط الرئيسية

النقاط الرئيسية:

  • Selenium القياسي لا يدعم مصادقة البروكسي — استخدم selenium-wire لـ Chrome أو ملف تعريف Firefox مع إضافة مصادقة.
  • تقليل بصمة الأتمتة ضروري — selenium-stealth وundetected-chromedriver وselenium-driverless هي أدواتك الأساسية.
  • نمط مصنع الجلسات مع علم session- يضمن IP جديداً لكل مهمة.
  • Selenium Grid + Docker يُمكّنك من التوسع إلى عشرات الجلسات المتوازية.
  • Playwright أفضل للمشاريع الجديدة؛ Selenium أفضل للكود القائم والتخفي المتقدم.
  • البروكسي السكني مع التخفي = أقوى مزيج لتجاوز أنظمة مكافحة البوتات.

جاهز لتجربة بروكسي سكني مع Selenium؟ ابدأ بتجربة مجانية على ProxyHat وطبّق أنماط هذا الدليل مباشرة.

¿Listo para empezar?

Accede a más de 50M de IPs residenciales en más de 148 países con filtrado impulsado por IA.

Ver preciosProxies residenciales
← Volver al Blog