بازگشت به وبلاگ

تنظیم پروکسی در Selenium WebDriver: راهنمای کامل با مثال‌های کد برای Python و Java

راهنمای جامع برای ادغام پروکسی در Selenium WebDriver با مثال‌های کد به زبان‌های Python و Java برای Chrome و Firefox.

📅۲۴ بهمن ۱۴۰۴
```html

Selenium WebDriver یکی از محبوب‌ترین ابزارها برای اتوماسیون مرورگر و استخراج داده‌ها است. هنگام کار با حجم بالای درخواست‌ها یا در صورت نیاز به دور زدن محدودیت‌های جغرافیایی، تنظیم صحیح پروکسی به شدت اهمیت دارد. در این راهنما، تمام روش‌های ادغام پروکسی در Selenium برای مرورگرهای مختلف و زبان‌های برنامه‌نویسی را بررسی خواهیم کرد و همچنین مشکلات رایجی که توسعه‌دهندگان با آن مواجه می‌شوند را حل خواهیم کرد.

چرا پروکسی در Selenium نیاز است

هنگام اتوماسیون وب‌اسکرپینگ یا تست از طریق Selenium، چندین وظیفه وجود دارد که بدون پروکسی نمی‌توان آن‌ها را حل کرد:

  • دور زدن محدودیت نرخ — بسیاری از وب‌سایت‌ها تعداد درخواست‌ها از یک آدرس IP را محدود می‌کنند. بدون پروکسی، اسکریپت شما به سرعت پس از 50-100 درخواست مسدود خواهد شد.
  • محدودیت‌های جغرافیایی — اگر نیاز به استخراج محتوایی دارید که فقط از یک کشور خاص در دسترس است، پروکسی با IP جغرافیای مورد نظر این مشکل را حل می‌کند.
  • توزیع بار — در استخراج داده‌های انبوه، چرخش آدرس‌های IP از طریق پروکسی به توزیع درخواست‌ها کمک می‌کند و از شناسایی ربات‌ها جلوگیری می‌کند.
  • تست محلی‌سازی — برای بررسی اینکه چگونه وب‌سایت برای کاربران از کشورهای مختلف نمایش داده می‌شود، پروکسی‌های مربوط به مناطق خاص لازم است.
  • دور زدن سیستم‌های ضد ربات — محافظت‌های مدرن (Cloudflare، DataDome) به تجزیه و تحلیل شهرت IP می‌پردازند. پروکسی‌های با کیفیت به شما کمک می‌کنند تا مانند یک کاربر عادی به نظر برسید.

بدون تنظیم صحیح پروکسی، اسکریپت Selenium شما به طور ناپایدار عمل خواهد کرد: CAPTCHA دریافت می‌کند، مسدودیت‌های موقتی یا مسدودیت کامل دسترسی را تجربه می‌کند. این موضوع به ویژه در استخراج از پلتفرم‌های تجارت الکترونیک، شبکه‌های اجتماعی یا وب‌سایت‌هایی با محافظت‌های شدید از ربات‌ها بسیار بحرانی است.

کدام نوع پروکسی باید استفاده شود

انتخاب نوع پروکسی بستگی به وظیفه دارد. برای اتوماسیون Selenium، سه نوع اصلی پروکسی وجود دارد که هر کدام مزایای خاص خود را دارند:

نوع پروکسی سرعت ناشناس بودن بهترین سناریوها
پروکسی دیتاسنتر بسیار بالا (100+ مگابیت/ثانیه) متوسط استخراج داده‌های عمومی، تست عملکرد، بررسی‌های انبوه
پروکسی‌های مسکونی متوسط (10-50 مگابیت/ثانیه) بسیار بالا دور زدن سیستم‌های ضد ربات، استخراج از شبکه‌های اجتماعی، تجارت الکترونیک، وب‌سایت‌های با محافظت شدید
پروکسی‌های موبایل متوسط (5-30 مگابیت/ثانیه) حداکثری کار با نسخه‌های موبایل وب‌سایت‌ها، شبکه‌های اجتماعی، برنامه‌هایی که IPهای موبایل را بررسی می‌کنند

توصیه‌ها برای انتخاب:

  • برای استخراج از وب‌سایت‌های خبری، APIهای باز، دایرکتوری‌های ساده — پروکسی دیتاسنتر مناسب است. این‌ها ارزان‌تر و سریع‌تر هستند.
  • برای کار با Amazon، eBay، Google، شبکه‌های اجتماعی — فقط پروکسی‌های مسکونی. این پلتفرم‌ها به شدت IPهای دیتاسنتر را مسدود می‌کنند.
  • برای شبیه‌سازی کاربران موبایل یا کار با Instagram، TikTok — پروکسی‌های موبایل ضروری هستند.
  • برای تست جغرافیایی — پروکسی‌هایی را انتخاب کنید که امکان انتخاب کشور و شهر خاص را داشته باشند.

تنظیم پروکسی برای Chrome در Selenium

Chrome WebDriver — محبوب‌ترین انتخاب برای اتوماسیون Selenium است. تنظیم پروکسی از طریق شیء ChromeOptions انجام می‌شود. چندین روش را بررسی می‌کنیم.

روش 1: پروکسی HTTP/HTTPS بدون احراز هویت (Python)

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

# تنظیم پروکسی
PROXY = "123.45.67.89:8080"  # آن را با پروکسی سرور خود جایگزین کنید

chrome_options = Options()
chrome_options.add_argument(f'--proxy-server=http://{PROXY}')

# گزینه‌های اضافی برای پایداری
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')

# راه‌اندازی درایور
driver = webdriver.Chrome(options=chrome_options)

# بررسی IP
driver.get('https://httpbin.org/ip')
print(driver.page_source)

driver.quit()

روش 2: پروکسی SOCKS5 (Python)

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

PROXY = "123.45.67.89:1080"

chrome_options = Options()
# برای SOCKS5 پروتکل را به وضوح مشخص کنید
chrome_options.add_argument(f'--proxy-server=socks5://{PROXY}')

driver = webdriver.Chrome(options=chrome_options)
driver.get('https://httpbin.org/ip')
print(driver.page_source)
driver.quit()

مهم: Chrome از پروکسی‌های HTTP، HTTPS و SOCKS5 پشتیبانی می‌کند. برای SOCKS4 به تنظیمات اضافی یا استفاده از افزونه‌ها نیاز است.

تنظیم پروکسی برای Chrome در Java

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.Proxy;

public class ChromeProxyExample {
    public static void main(String[] args) {
        // تنظیم پروکسی
        Proxy proxy = new Proxy();
        proxy.setHttpProxy("123.45.67.89:8080");
        proxy.setSslProxy("123.45.67.89:8080");
        
        ChromeOptions options = new ChromeOptions();
        options.setProxy(proxy);
        options.addArguments("--no-sandbox");
        
        WebDriver driver = new ChromeDriver(options);
        driver.get("https://httpbin.org/ip");
        
        System.out.println(driver.getPageSource());
        driver.quit();
    }
}

تنظیم پروکسی برای Firefox در Selenium

Firefox WebDriver از رویکرد دیگری برای تنظیم پروکسی از طریق پروفایل مرورگر استفاده می‌کند. این امر انعطاف‌پذیری بیشتری را فراهم می‌کند، اما نیاز به درک تنظیمات پیکربندی دارد.

پروکسی HTTP/HTTPS برای Firefox (Python)

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

PROXY_HOST = "123.45.67.89"
PROXY_PORT = 8080

firefox_options = Options()

# تنظیم پروکسی از طریق preferences
firefox_options.set_preference("network.proxy.type", 1)
firefox_options.set_preference("network.proxy.http", PROXY_HOST)
firefox_options.set_preference("network.proxy.http_port", PROXY_PORT)
firefox_options.set_preference("network.proxy.ssl", PROXY_HOST)
firefox_options.set_preference("network.proxy.ssl_port", PROXY_PORT)

# غیرفعال کردن پروکسی برای آدرس‌های محلی
firefox_options.set_preference("network.proxy.no_proxies_on", "localhost,127.0.0.1")

driver = webdriver.Firefox(options=firefox_options)
driver.get('https://httpbin.org/ip')
print(driver.page_source)
driver.quit()

پروکسی SOCKS5 برای Firefox (Python)

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

PROXY_HOST = "123.45.67.89"
PROXY_PORT = 1080

firefox_options = Options()

firefox_options.set_preference("network.proxy.type", 1)
firefox_options.set_preference("network.proxy.socks", PROXY_HOST)
firefox_options.set_preference("network.proxy.socks_port", PROXY_PORT)
firefox_options.set_preference("network.proxy.socks_version", 5)

# برای SOCKS5 با DNS از طریق پروکسی
firefox_options.set_preference("network.proxy.socks_remote_dns", True)

driver = webdriver.Firefox(options=firefox_options)
driver.get('https://httpbin.org/ip')
print(driver.page_source)
driver.quit()

مزیت Firefox: پارامتر network.proxy.socks_remote_dns اجازه می‌دهد تا درخواست‌های DNS از طریق پروکسی انجام شود، که ناشناس بودن را افزایش می‌دهد و به دور زدن مسدودیت‌ها در سطح DNS کمک می‌کند.

کار با پروکسی‌هایی که نیاز به احراز هویت دارند

بیشتر سرویس‌های پروکسی با کیفیت از احراز هویت با نام کاربری و رمز عبور استفاده می‌کنند. Selenium از ارسال اطلاعات احراز هویت به طور مستقیم در URL پروکسی برای Chrome پشتیبانی نمی‌کند، بنابراین نیاز به راه‌حل‌های دور زدن است.

روش 1: افزونه Chrome برای احراز هویت (توصیه شده)

یک افزونه موقت Chrome ایجاد می‌کنیم که به طور خودکار نام کاربری و رمز عبور را هنگام اتصال به پروکسی وارد می‌کند:

import os
import zipfile
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

PROXY_HOST = "123.45.67.89"
PROXY_PORT = 8080
PROXY_USER = "username"
PROXY_PASS = "password"

# ایجاد مانیفست افزونه
manifest_json = """
{
    "version": "1.0.0",
    "manifest_version": 2,
    "name": "Chrome Proxy",
    "permissions": [
        "proxy",
        "tabs",
        "unlimitedStorage",
        "storage",
        "webRequest",
        "webRequestBlocking"
    ],
    "background": {
        "scripts": ["background.js"]
    }
}
"""

# اسکریپت برای احراز هویت
background_js = """
var config = {
    mode: "fixed_servers",
    rules: {
        singleProxy: {
            scheme: "http",
            host: "%s",
            port: parseInt(%s)
        },
        bypassList: ["localhost"]
    }
};

chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});

function callbackFn(details) {
    return {
        authCredentials: {
            username: "%s",
            password: "%s"
        }
    };
}

chrome.webRequest.onAuthRequired.addListener(
    callbackFn,
    {urls: [""]},
    ['blocking']
);
""" % (PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS)

# ایجاد افزونه
plugin_path = 'proxy_auth_plugin.zip'
with zipfile.ZipFile(plugin_path, 'w') as zp:
    zp.writestr("manifest.json", manifest_json)
    zp.writestr("background.js", background_js)

# راه‌اندازی Chrome با افزونه
chrome_options = Options()
chrome_options.add_extension(plugin_path)

driver = webdriver.Chrome(options=chrome_options)
driver.get('https://httpbin.org/ip')
print(driver.page_source)

driver.quit()
os.remove(plugin_path)  # حذف فایل موقت

روش 2: Firefox با احراز هویت (ساده‌تر)

Firefox اجازه می‌دهد تا اطلاعات احراز هویت از طریق تنظیمات پروفایل ارسال شود:

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

PROXY_HOST = "123.45.67.89"
PROXY_PORT = 8080
PROXY_USER = "username"
PROXY_PASS = "password"

firefox_options = Options()

firefox_options.set_preference("network.proxy.type", 1)
firefox_options.set_preference("network.proxy.http", PROXY_HOST)
firefox_options.set_preference("network.proxy.http_port", PROXY_PORT)
firefox_options.set_preference("network.proxy.ssl", PROXY_HOST)
firefox_options.set_preference("network.proxy.ssl_port", PROXY_PORT)

# احراز هویت (همیشه کار نمی‌کند، بستگی به نسخه Firefox دارد)
firefox_options.set_preference("network.proxy.username", PROXY_USER)
firefox_options.set_preference("network.proxy.password", PROXY_PASS)

# غیرفعال کردن درخواست احراز هویت
firefox_options.set_preference("network.automatic-ntlm-auth.trusted-uris", PROXY_HOST)

driver = webdriver.Firefox(options=firefox_options)
driver.get('https://httpbin.org/ip')
print(driver.page_source)
driver.quit()

یادداشت: اگر ارائه‌دهنده پروکسی شما از whitelist IP پشتیبانی می‌کند، ساده‌تر است که IP سرور خود را در لیست سفید قرار دهید و از پروکسی بدون احراز هویت استفاده کنید.

چرخش پروکسی در Selenium

هنگام استخراج حجم بالای داده‌ها، تغییر پروکسی برای جلوگیری از مسدودیت‌ها به شدت اهمیت دارد. دو رویکرد وجود دارد: چرخش در سطح کد و استفاده از پروکسی‌های چرخشی.

چرخش در سطح کد (ایجاد درایور جدید)

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

# لیست پروکسی
PROXY_LIST = [
    "123.45.67.89:8080",
    "98.76.54.32:8080",
    "11.22.33.44:8080",
]

def create_driver_with_proxy(proxy):
    """ایجاد درایور با پروکسی مشخص شده"""
    chrome_options = Options()
    chrome_options.add_argument(f'--proxy-server=http://{proxy}')
    chrome_options.add_argument('--no-sandbox')
    return webdriver.Chrome(options=chrome_options)

# استخراج با چرخش
urls_to_parse = [
    'https://example.com/page1',
    'https://example.com/page2',
    'https://example.com/page3',
]

for url in urls_to_parse:
    # انتخاب یک پروکسی تصادفی
    current_proxy = random.choice(PROXY_LIST)
    
    # ایجاد یک درایور جدید با پروکسی
    driver = create_driver_with_proxy(current_proxy)
    
    try:
        driver.get(url)
        # منطق استخراج شما
        print(f"استخراج {url} از طریق {current_proxy}")
        print(driver.title)
    except Exception as e:
        print(f"خطا با {current_proxy}: {e}")
    finally:
        driver.quit()  # مهم است که درایور را ببندید

استفاده از پروکسی‌های چرخشی (ساده‌تر)

بسیاری از ارائه‌دهندگان پروکسی، endpoint چرخشی ارائه می‌دهند — یک URL که به طور خودکار IP را در هر درخواست یا در فواصل مشخص تغییر می‌دهد. این کار کد را ساده‌تر می‌کند:

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

# endpoint پروکسی چرخشی (IP به طور خودکار تغییر می‌کند)
ROTATING_PROXY = "rotating.proxycove.com:8080"

chrome_options = Options()
chrome_options.add_argument(f'--proxy-server=http://{ROTATING_PROXY}')

driver = webdriver.Chrome(options=chrome_options)

# هر درخواست با IP جدید خواهد بود
urls = ['https://httpbin.org/ip'] * 5

for url in urls:
    driver.get(url)
    print(driver.find_element("tag name", "body").text)
    # هر خروجی IP متفاوتی را نشان می‌دهد

driver.quit()

توصیه: برای پروژه‌های بزرگ از پروکسی‌های چرخشی استفاده کنید — این کار منابع را صرفه‌جویی می‌کند (نیازی به ایجاد مجدد درایور نیست) و کد را ساده‌تر می‌کند. پروکسی‌های مسکونی معمولاً از چرخش به طور پیش‌فرض پشتیبانی می‌کنند.

خطاهای رایج و راه‌حل‌های آن‌ها

خطا: "ERR_PROXY_CONNECTION_FAILED"

علت: Selenium نمی‌تواند به سرور پروکسی متصل شود.

راه‌حل:

  • درستی IP و پورت پروکسی را بررسی کنید
  • اطمینان حاصل کنید که پروکسی فعال است (از طریق curl بررسی کنید: curl -x http://123.45.67.89:8080 https://httpbin.org/ip)
  • فایروال را بررسی کنید — ممکن است اتصالات خروجی به پروکسی مسدود شده باشد
  • اگر از احراز هویت استفاده می‌کنید، صحت نام کاربری/رمز عبور را بررسی کنید

خطا: "ERR_TUNNEL_CONNECTION_FAILED"

علت: مشکل با اتصال HTTPS از طریق پروکسی.

راه‌حل:

  • اطمینان حاصل کنید که پروکسی از HTTPS (روش CONNECT) پشتیبانی می‌کند
  • برای وب‌سایت‌های HTTPS از پروکسی HTTPS یا SOCKS5 استفاده کنید
  • گزینه نادیده‌گیری خطاهای SSL را اضافه کنید: chrome_options.add_argument('--ignore-certificate-errors')

خطا: پروکسی کار می‌کند، اما وب‌سایت ربات را شناسایی می‌کند

علت: وب‌سایت از روش‌های پیشرفته شناسایی (fingerprinting، تجزیه و تحلیل رفتار) استفاده می‌کند.

راه‌حل:

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

chrome_options = Options()
chrome_options.add_argument(f'--proxy-server=http://{PROXY}')

# غیرفعال کردن پرچم webdriver (نشانه اصلی اتوماسیون)
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)

driver = webdriver.Chrome(options=chrome_options)

# حذف navigator.webdriver
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        })
    '''
})

driver.get('https://bot.sannysoft.com/')  # وب‌سایت برای بررسی شناسایی

علاوه بر این، توصیه می‌شود از کتابخانه undetected-chromedriver استفاده کنید که به طور خودکار بسیاری از تکنیک‌های ضد شناسایی را اعمال می‌کند.

مشکل: بارگذاری کند صفحات از طریق پروکسی

علت: پروکسی بیش از حد بارگذاری شده یا جغرافیایی دور است.

راه‌حل:

  • پروکسی را نزدیک‌تر به سرور هدف انتخاب کنید (برای استخراج از وب‌سایت‌های US، از پروکسی‌های US استفاده کنید)
  • برای کارهایی که سرعت مهم‌تر از ناشناس بودن است، از پروکسی‌های دیتاسنتر استفاده کنید
  • تایم‌اوت‌ها را در Selenium تنظیم کنید تا از قفل شدن جلوگیری کنید:
from selenium.webdriver.support.ui import WebDriverWait

driver.set_page_load_timeout(30)  # حداکثر 30 ثانیه برای بارگذاری
driver.implicitly_wait(10)  # انتظار غیرمستقیم برای عناصر

بهترین شیوه‌ها در کار با پروکسی

1. از مجموعه‌های پروکسی استفاده کنید
به یک سرور پروکسی تکی تکیه نکنید. یک مجموعه از 10-50 پروکسی ایجاد کنید و آن‌ها را بچرخانید. اگر یک پروکسی مسدود شود، استخراج از پروکسی دیگر ادامه خواهد یافت.

2. تأخیرهای تصادفی اضافه کنید
حتی با پروکسی، درخواست‌های بسیار سریع مشکوک به نظر می‌رسند. تأخیرهای تصادفی 2-5 ثانیه بین درخواست‌ها اضافه کنید:

import time
import random

for url in urls:
    driver.get(url)
    # استخراج...
    time.sleep(random.uniform(2, 5))  # تأخیر تصادفی 2-5 ثانیه

3. کیفیت پروکسی را نظارت کنید
پروکسی‌ها را قبل از استفاده بررسی کنید. آن‌هایی را که پاسخ نمی‌دهند یا خطا برمی‌گردانند از مجموعه حذف کنید:

import requests

def check_proxy(proxy):
    """بررسی کارایی پروکسی"""
    try:
        response = requests.get(
            'https://httpbin.org/ip',
            proxies={'http': f'http://{proxy}', 'https': f'http://{proxy}'},
            timeout=10
        )
        return response.status_code == 200
    except:
        return False

# فیلتر کردن پروکسی‌های کاری
working_proxies = [p for p in PROXY_LIST if check_proxy(p)]
print(f"پروکسی‌های کاری: {len(working_proxies)}/{len(PROXY_LIST)}")

4. از حالت headless با احتیاط استفاده کنید
مرورگرهای headless راحت‌تر شناسایی می‌شوند. برای وب‌سایت‌های پیچیده، مرورگر را در حالت عادی راه‌اندازی کنید یا از --window-size به جای --headless استفاده کنید.

5. تمام درخواست‌ها را ثبت کنید
اطلاعات مربوط به اینکه کدام پروکسی برای هر درخواست استفاده شده است را ذخیره کنید. این کار به شناسایی پروکسی‌های مشکل‌دار و اشکال‌زدایی خطاها کمک می‌کند.

6. به robots.txt و محدودیت‌های نرخ احترام بگذارید
حتی با پروکسی، به قوانین وب‌سایت احترام بگذارید. استخراج تهاجمی می‌تواند منجر به مسدود شدن زیرشبکه‌های پروکسی شود که به سایر کاربران آسیب می‌زند.

نتیجه‌گیری

تنظیم صحیح پروکسی در Selenium WebDriver، پایه‌ای برای استخراج و اتوماسیون پایدار است. ما تمام روش‌های اصلی ادغام پروکسی برای Chrome و Firefox، کار با احراز هویت، چرخش آدرس‌های IP و حل مشکلات رایج را بررسی کردیم. نکته اصلی این است که نوع مناسب پروکسی را برای وظیفه خود انتخاب کنید: برای استخراج ساده، پروکسی‌های دیتاسنتر کافی هستند، در حالی که برای کار با پلتفرم‌های محافظت‌شده، پروکسی‌های مسکونی یا موبایل ضروری هستند.

به یاد داشته باشید که بهترین شیوه‌ها را رعایت کنید: از مجموعه‌های پروکسی استفاده کنید، تأخیرهای تصادفی اضافه کنید، کیفیت اتصالات را نظارت کنید و تکنیک‌های ضد شناسایی را اعمال کنید. این کار پایداری اسکریپت‌های شما را افزایش می‌دهد و خطر مسدودیت‌ها را به شدت کاهش می‌دهد.

اگر قصد دارید استخراج را با نیازهای بالای ناشناس بودن و دور زدن سیستم‌های ضد ربات اتوماسیون کنید، توصیه می‌کنیم پروکسی‌های مسکونی را امتحان کنید — آن‌ها حداکثر پایداری را در کار با هر وب‌سایتی، از جمله شبکه‌های اجتماعی، پلتفرم‌های تجارت الکترونیک و خدمات با حفاظت پیشرفته فراهم می‌کنند. برای کارهایی که سرعت پردازش حجم بالای داده‌ها اهمیت دارد، پروکسی‌های دیتاسنتر انتخاب بهینه‌ای از نظر قیمت و عملکرد خواهند بود.

```