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

چگونه استفاده از Selenium و Puppeteer را پنهان کنیم

یاد بگیرید چگونه استفاده از Selenium و Puppeteer را از سیستم‌های ضد ربات پنهان کنید. روش‌های عملی، نمونه‌های کد و تکنیک‌های اثبات شده برای مخفی‌سازی خودکارسازی.

📅۵ دی ۱۴۰۴
```html

راهنمای کامل برای پنهان‌سازی Selenium و Puppeteer از تشخیص

سیستم‌های مدرن ضد ربات به راحتی مرورگرهای اتوماسیون را با استفاده از ده‌ها نشانه شناسایی می‌کنند: از متغیرهای JavaScript گرفته تا ویژگی‌های رفتار WebDriver. وب‌سایت‌ها از Cloudflare، DataDome، PerimeterX و راه‌حل‌های اختصاصی خود استفاده می‌کنند که تا 90% درخواست‌ها از Selenium و Puppeteer را در پیکربندی استاندارد مسدود می‌کنند.

در این راهنما، تمام روش‌های پنهان‌سازی اتوماسیون را بررسی خواهیم کرد: از تنظیمات پایه‌ای تا تکنیک‌های پیشرفته دور زدن تشخیص. شما راه‌حل‌های آماده با مثال‌های کد برای Python و Node.js دریافت خواهید کرد که در برابر اکثر سیستم‌های حفاظتی کار می‌کنند.

چگونه وب‌سایت‌ها اتوماسیون را شناسایی می‌کنند

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

نشانه‌های WebDriver

ساده‌ترین روش شناسایی، بررسی متغیرهای JavaScript است که فقط در مرورگرهای اتوماسیون وجود دارند:

// این متغیرها Selenium/Puppeteer را فاش می‌کنند
navigator.webdriver === true
window.navigator.webdriver === true
document.$cdc_ // متغیر خاص ChromeDriver
window.document.documentElement.getAttribute("webdriver")
navigator.plugins.length === 0 // مرورگرهای اتوماسیون هیچ افزونه‌ای ندارند
navigator.languages === "" // لیست زبان‌ها خالی است

Cloudflare و سیستم‌های مشابه این ویژگی‌ها را در اولویت بررسی می‌کنند. اگر حداقل یکی از آن‌ها نتیجه مثبت بدهد — درخواست مسدود می‌شود.

فینگرپرینتینگ مرورگر

سیستم‌های پیشرفته یک اثر انگشت منحصر به فرد برای مرورگر بر اساس ده‌ها پارامتر ایجاد می‌کنند:

  • فینگرپرینتینگ Canvas — رندر کردن تصاویر پنهان و تجزیه و تحلیل داده‌های پیکسل
  • فینگرپرینتینگ WebGL — پارامترهای رندرکننده گرافیک و کارت گرافیک
  • Audio Context — ویژگی‌های منحصر به فرد پردازش صدا
  • فینگرپرینتینگ فونت‌ها — لیست فونت‌های نصب شده در سیستم
  • رزولوشن صفحه نمایش — رزولوشن صفحه، عمق رنگ، ناحیه قابل دسترسی
  • منطقه زمانی و زبان — منطقه زمانی، زبان‌های مرورگر، محلی سیستم

مرورگرهای اتوماسیون اغلب ترکیب‌های غیرمعمولی از این پارامترها دارند. به عنوان مثال، Headless Chrome هیچ افزونه‌ای ندارد، اما WebGL را پشتیبانی می‌کند — چنین ترکیبی به ندرت در کاربران واقعی مشاهده می‌شود.

تحلیل رفتاری

سیستم‌های مدرن الگوهای رفتاری را ردیابی می‌کنند:

  • حرکات ماوس — ربات‌ها نشانگر را به صورت خطوط مستقیم حرکت می‌دهند یا اصلاً حرکت نمی‌دهند
  • سرعت عمل — پر کردن فرم‌ها به صورت آنی، سرعت کلیک غیرانسانی
  • الگوهای اسکرول — پرش‌های ناگهانی به جای اسکرول نرم
  • رویدادهای صفحه کلید — عدم وجود تأخیرهای طبیعی بین فشارها
  • فرکانس درخواست‌ها — فاصله‌های بسیار منظم بین اقدامات

مهم: DataDome و PerimeterX از یادگیری ماشین برای تحلیل رفتار استفاده می‌کنند. آن‌ها بر روی میلیون‌ها جلسه آموزش دیده‌اند و می‌توانند ربات را حتی با پنهان‌سازی صحیح پارامترهای فنی شناسایی کنند، اگر رفتار غیرطبیعی به نظر برسد.

پنهان‌سازی پایه‌ای Selenium

Selenium WebDriver در پیکربندی استاندارد نشانه‌های زیادی از خود به جا می‌گذارد. بیایید یک تنظیم مرحله به مرحله برای کاهش تشخیص را با استفاده از Python و ChromeDriver بررسی کنیم.

غیرفعال کردن پرچم webdriver

اولین قدم — پنهان کردن متغیر navigator.webdriver. این کار از طریق پروتکل Chrome DevTools انجام می‌شود:

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

# تنظیم گزینه‌های Chrome
chrome_options = Options()

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

# ایجاد درایور
driver = webdriver.Chrome(options=chrome_options)

# حذف webdriver از طریق CDP
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        })
    '''
})

driver.get('https://example.com')

تنظیم User-Agent و سایر هدرها

مرورگرهای Headless اغلب از رشته‌های User-Agent قدیمی یا خاص استفاده می‌کنند. لازم است یک User-Agent به‌روز از یک مرورگر واقعی تنظیم کنید:

# User-Agent به‌روز Chrome در ویندوز
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'
chrome_options.add_argument(f'user-agent={user_agent}')

# آرگومان‌های اضافی برای پنهان‌سازی
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-gpu')

# اندازه پنجره به اندازه یک کاربر واقعی
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--start-maximized')

افزودن افزونه‌ها و زبان‌ها

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

driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'languages', {
            get: () => ['en-US', 'en', 'ru']
        });
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [
                {
                    0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Plugin"
                },
                {
                    0: {type: "application/pdf", suffixes: "pdf", description: ""},
                    description: "",
                    filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai",
                    length: 1,
                    name: "Chrome PDF Viewer"
                }
            ]
        });
        
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
    '''
})

مثال کامل از تنظیم Selenium

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

def create_stealth_driver():
    chrome_options = Options()
    
    # تنظیمات پایه‌ای پنهان‌سازی
    chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
    chrome_options.add_experimental_option('useAutomationExtension', False)
    chrome_options.add_argument('--disable-blink-features=AutomationControlled')
    
    # User-Agent
    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'
    chrome_options.add_argument(f'user-agent={user_agent}')
    
    # اندازه پنجره
    chrome_options.add_argument('--window-size=1920,1080')
    chrome_options.add_argument('--start-maximized')
    
    driver = webdriver.Chrome(options=chrome_options)
    
    # اسکریپت پنهان‌سازی از طریق CDP
    stealth_script = '''
        Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
        Object.defineProperty(navigator, 'languages', {get: () => ['en-US', 'en']});
        Object.defineProperty(navigator, 'platform', {get: () => 'Win32'});
        
        window.chrome = {
            runtime: {}
        };
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [1, 2, 3, 4, 5]
        });
    '''
    
    driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
        'source': stealth_script
    })
    
    return driver

# استفاده
driver = create_stealth_driver()
driver.get('https://bot.sannysoft.com/')  # وب‌سایت برای بررسی تشخیص

تنظیم Puppeteer برای دور زدن تشخیص

Puppeteer همان مشکلات تشخیص را دارد که Selenium. با این حال، برای Node.js یک کتابخانه آماده به نام puppeteer-extra-plugin-stealth وجود دارد که اکثر تنظیمات پنهان‌سازی را خودکار می‌کند.

نصب puppeteer-extra

npm install puppeteer puppeteer-extra puppeteer-extra-plugin-stealth

پیکربندی پایه‌ای با پلاگین stealth

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

// اتصال پلاگین پنهان‌سازی
puppeteer.use(StealthPlugin());

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new', // حالت headless جدید Chrome
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-dev-shm-usage',
            '--disable-accelerated-2d-canvas',
            '--disable-gpu',
            '--window-size=1920,1080',
            '--disable-web-security',
            '--disable-features=IsolateOrigins,site-per-process'
        ]
    });
    
    const page = await browser.newPage();
    
    // تنظیم viewport
    await page.setViewport({
        width: 1920,
        height: 1080,
        deviceScaleFactor: 1
    });
    
    // تنظیم User-Agent
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
    
    // هدرهای اضافی
    await page.setExtraHTTPHeaders({
        'Accept-Language': 'en-US,en;q=0.9',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
    });
    
    await page.goto('https://bot.sannysoft.com/');
    
    // اسکرین‌شات برای بررسی
    await page.screenshot({ path: 'test.png' });
    
    await browser.close();
})();

تنظیم دستی بدون پلاگین‌ها

اگر می‌خواهید کنترل کامل داشته باشید یا نمی‌توانید از کتابخانه‌های شخص ثالث استفاده کنید، پنهان‌سازی را به صورت دستی تنظیم کنید:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    
    const page = await browser.newPage();
    
    // بازتعریف webdriver و سایر ویژگی‌ها
    await page.evaluateOnNewDocument(() => {
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        });
        
        Object.defineProperty(navigator, 'languages', {
            get: () => ['en-US', 'en']
        });
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [1, 2, 3, 4, 5]
        });
        
        // پنهان‌سازی Chrome headless
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
        
        window.chrome = {
            runtime: {}
        };
        
        // بازتعریف مجوزها
        const originalQuery = window.navigator.permissions.query;
        window.navigator.permissions.query = (parameters) => (
            parameters.name === 'notifications' ?
                Promise.resolve({ state: Notification.permission }) :
                originalQuery(parameters)
        );
    });
    
    await page.goto('https://example.com');
    await browser.close();
})();

تنظیم برای دور زدن Cloudflare

Cloudflare از روش‌های پیشرفته تشخیص استفاده می‌کند. برای دور زدن آن، لازم است تأخیرهای تصادفی و شبیه‌سازی اقدامات را اضافه کنید:

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

async function bypassCloudflare(url) {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: [
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-web-security'
        ]
    });
    
    const page = await browser.newPage();
    
    // User-Agent تصادفی
    const userAgents = [
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
    ];
    await page.setUserAgent(userAgents[Math.floor(Math.random() * userAgents.length)]);
    
    // رفتن به صفحه
    await page.goto(url, { waitUntil: 'networkidle2' });
    
    // انتظار برای بررسی Cloudflare (معمولاً 5-10 ثانیه)
    await page.waitForTimeout(8000);
    
    // حرکت تصادفی ماوس
    await page.mouse.move(100, 100);
    await page.mouse.move(200, 200);
    
    const content = await page.content();
    await browser.close();
    
    return content;
}

مقابله با فینگرپرینتینگ JavaScript

فینگرپرینتینگ JavaScript — ایجاد یک اثر انگشت منحصر به فرد برای مرورگر بر اساس چندین پارامتر است. حتی اگر شما webdriver را پنهان کرده باشید، سیستم‌ها صدها ویژگی دیگر را برای شناسایی اتوماسیون تحلیل می‌کنند.

وکتورهای اصلی فینگرپرینتینگ

سیستم‌های ضد ربات ویژگی‌های زیر را بررسی می‌کنند:

ویژگی چه چیزی بررسی می‌شود ریسک تشخیص
navigator.webdriver وجود پرچم اتوماسیون بحرانی
navigator.plugins تعداد و نوع افزونه‌ها بالا
window.chrome وجود API Chrome متوسط
navigator.permissions API مجوزهای مرورگر متوسط
screen.colorDepth عمق رنگ صفحه نمایش پایین
navigator.hardwareConcurrency تعداد هسته‌های پردازنده پایین

اسکریپت جامع پنهان‌سازی

اسکریپت زیر بیشتر ویژگی‌های مشکل‌ساز را بازتعریف می‌کند. آن را از طریق CDP (Selenium) یا evaluateOnNewDocument (Puppeteer) پیاده‌سازی کنید:

const stealthScript = `
    // حذف webdriver
    Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined
    });
    
    // افزودن شی chrome
    window.chrome = {
        runtime: {},
        loadTimes: function() {},
        csi: function() {},
        app: {}
    };
    
    // بازتعریف مجوزها
    const originalQuery = window.navigator.permissions.query;
    window.navigator.permissions.query = (parameters) => (
        parameters.name === 'notifications' ?
            Promise.resolve({ state: Notification.permission }) :
            originalQuery(parameters)
    );
    
    // پنهان‌سازی افزونه‌ها
    Object.defineProperty(navigator, 'plugins', {
        get: () => {
            return [
                {
                    0: {type: "application/x-google-chrome-pdf", suffixes: "pdf"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Plugin"
                },
                {
                    0: {type: "application/pdf", suffixes: "pdf"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Viewer"
                },
                {
                    0: {type: "application/x-nacl"},
                    description: "Native Client Executable",
                    filename: "internal-nacl-plugin",
                    length: 2,
                    name: "Native Client"
                }
            ];
        }
    });
    
    // زبان‌ها
    Object.defineProperty(navigator, 'languages', {
        get: () => ['en-US', 'en']
    });
    
    // پلتفرم
    Object.defineProperty(navigator, 'platform', {
        get: () => 'Win32'
    });
    
    // فروشنده
    Object.defineProperty(navigator, 'vendor', {
        get: () => 'Google Inc.'
    });
    
    // حذف ردپاهای Selenium
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
    
    // Battery API (غیاب در headless)
    if (!navigator.getBattery) {
        navigator.getBattery = () => Promise.resolve({
            charging: true,
            chargingTime: 0,
            dischargingTime: Infinity,
            level: 1
        });
    }
`;

حذف ویژگی‌های WebDriver

ChromeDriver و سایر پیاده‌سازی‌های WebDriver متغیرهای خاصی را به فضای نام جهانی اضافه می‌کنند. این متغیرها با پیشوند cdc_ شروع می‌شوند و به راحتی توسط سیستم‌های حفاظتی شناسایی می‌شوند.

شناسایی متغیرهای cdc

می‌توان با یک اسکریپت ساده وجود این متغیرها را بررسی کرد:

// جستجوی تمام متغیرهای cdc
for (let key in window) {
    if (key.includes('cdc_')) {
        console.log('متغیر WebDriver شناسایی شد:', key);
    }
}

// متغیرهای معمولی ChromeDriver:
// cdc_adoQpoasnfa76pfcZLmcfl_Array
// cdc_adoQpoasnfa76pfcZLmcfl_Promise
// cdc_adoQpoasnfa76pfcZLmcfl_Symbol
// $cdc_asdjflasutopfhvcZLmcfl_

روش 1: حذف از طریق CDP

مطمئن‌ترین روش — حذف متغیرها قبل از بارگذاری صفحه از طریق پروتکل Chrome DevTools:

from selenium import webdriver

driver = webdriver.Chrome()

# حذف تمام متغیرهای cdc
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        // حذف متغیرهای cdc شناخته شده
        const cdcProps = [
            'cdc_adoQpoasnfa76pfcZLmcfl_Array',
            'cdc_adoQpoasnfa76pfcZLmcfl_Promise',
            'cdc_adoQpoasnfa76pfcZLmcfl_Symbol',
            '$cdc_asdjflasutopfhvcZLmcfl_'
        ];
        
        cdcProps.forEach(prop => {
            delete window[prop];
        });
        
        // حذف تمام متغیرهای حاوی 'cdc_'
        Object.keys(window).forEach(key => {
            if (key.includes('cdc_') || key.includes('$cdc_')) {
                delete window[key];
            }
        });
    '''
})

روش 2: تغییر ChromeDriver

یک رویکرد رادیکال‌تر — تغییر فایل باینری ChromeDriver با جایگزینی رشته cdc_ با یک دنباله کاراکتری دیگر. این کار از ایجاد این متغیرها جلوگیری می‌کند:

import re

def patch_chromedriver(driver_path):
    """
    ChromeDriver را پچ می‌کند و 'cdc_' را با یک رشته تصادفی جایگزین می‌کند
    """
    with open(driver_path, 'rb') as f:
        content = f.read()
    
    # جایگزینی تمام موارد 'cdc_' با 'dog_' (یا هر رشته دیگری با همان طول)
    patched = content.replace(b'cdc_', b'dog_')
    
    with open(driver_path, 'wb') as f:
        f.write(patched)
    
    print(f'ChromeDriver پچ شد: {driver_path}')

# استفاده
patch_chromedriver('/path/to/chromedriver')

توجه: تغییر فایل باینری ChromeDriver می‌تواند عملکرد آن را مختل کند. همیشه قبل از پچ کردن یک نسخه پشتیبان تهیه کنید. این روش با همه نسخه‌های ChromeDriver کار نمی‌کند.

روش 3: استفاده از undetected-chromedriver

کتابخانه undetected-chromedriver به طور خودکار ChromeDriver را هنگام اجرا پچ می‌کند:

pip install undetected-chromedriver
import undetected_chromedriver as uc

# ایجاد درایور با پچ خودکار
driver = uc.Chrome()

driver.get('https://nowsecure.nl/')  # وب‌سایت برای بررسی تشخیص
input('برای بستن Enter را فشار دهید...')
driver.quit()

پنهان‌سازی Canvas، WebGL و Audio API

فینگرپرینتینگ Canvas، WebGL و Audio روش‌هایی برای ایجاد یک اثر انگشت منحصر به فرد بر اساس ویژگی‌های رندرینگ گرافیک و پردازش صدا هستند. هر ترکیب از مرورگر، سیستم‌عامل و سخت‌افزار یک نتیجه منحصر به فرد تولید می‌کند.

فینگرپرینتینگ Canvas

سیستم‌ها یک تصویر پنهان را بر روی Canvas رسم کرده و پیکسل‌های به‌دست‌آمده را تحلیل می‌کنند. مرورگرهای Headless اغلب نتایج غیرمعمولی به دلیل عدم وجود شتاب‌دهنده GPU ارائه می‌دهند.

// کد معمولی فینگرپرینتینگ Canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('اثر انگشت مرورگر', 2, 2);
const fingerprint = canvas.toDataURL();

برای محافظت می‌توانید نویز تصادفی به API Canvas اضافه کنید:

const canvasNoiseScript = `
    // افزودن نویز تصادفی به Canvas
    const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
    const originalToBlob = HTMLCanvasElement.prototype.toBlob;
    const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
    
    // تابع افزودن نویز
    const addNoise = (canvas, context) => {
        const imageData = originalGetImageData.call(context, 0, 0, canvas.width, canvas.height);
        for (let i = 0; i < imageData.data.length; i += 4) {
            // افزودن نویز حداقلی به RGB (غیر قابل مشاهده برای چشم)
            imageData.data[i] += Math.floor(Math.random() * 3) - 1;
            imageData.data[i + 1] += Math.floor(Math.random() * 3) - 1;
            imageData.data[i + 2] += Math.floor(Math.random() * 3) - 1;
        }
        context.putImageData(imageData, 0, 0);
    };
    
    // بازتعریف toDataURL
    HTMLCanvasElement.prototype.toDataURL = function() {
        if (this.width > 0 && this.height > 0) {
            const context = this.getContext('2d');
            addNoise(this, context);
        }
        return originalToDataURL.apply(this, arguments);
    };
`;

فینگرپرینتینگ WebGL

WebGL اطلاعاتی درباره کارت گرافیک و درایورها ارائه می‌دهد. مرورگرهای Headless اغلب SwiftShader (رندرکننده نرم‌افزاری) را به جای GPU واقعی نشان می‌دهند:

const webglMaskScript = `
    // پنهان‌سازی پارامترهای WebGL
    const getParameter = WebGLRenderingContext.prototype.getParameter;
    WebGLRenderingContext.prototype.getParameter = function(parameter) {
        // UNMASKED_VENDOR_WEBGL
        if (parameter === 37445) {
            return 'Intel Inc.';
        }
        // UNMASKED_RENDERER_WEBGL
        if (parameter === 37446) {
            return 'Intel Iris OpenGL Engine';
        }
        return getParameter.call(this, parameter);
    };
    
    // همچنین برای WebGL2
    if (typeof WebGL2RenderingContext !== 'undefined') {
        const getParameter2 = WebGL2RenderingContext.prototype.getParameter;
        WebGL2RenderingContext.prototype.getParameter = function(parameter) {
            if (parameter === 37445) {
                return 'Intel Inc.';
            }
            if (parameter === 37446) {
                return 'Intel Iris OpenGL Engine';
            }
            return getParameter2.call(this, parameter);
        };
    }
`;

فینگرپرینتینگ Audio Context

API Audio همچنین یک اثر انگشت منحصر به فرد ارائه می‌دهد. نویز را به پردازش صدا اضافه کنید:

const audioMaskScript = `
    // افزودن نویز به Audio Context
    const AudioContext = window.AudioContext || window.webkitAudioContext;
    if (AudioContext) {
        const originalCreateAnalyser = AudioContext.prototype.createAnalyser;
        AudioContext.prototype.createAnalyser = function() {
            const analyser = originalCreateAnalyser.call(this);
            const originalGetFloatFrequencyData = analyser.getFloatFrequencyData;
            analyser.getFloatFrequencyData = function(array) {
                originalGetFloatFrequencyData.call(this, array);
                // افزودن نویز حداقلی
                for (let i = 0; i < array.length; i++) {
                    array[i] += Math.random() * 0.0001;
                }
            };
            return analyser;
        };
    }
`;

شبیه‌سازی رفتار انسانی

حتی با پنهان‌سازی فنی ایده‌آل، ربات‌ها خود را با رفتارشان فاش می‌کنند. سیستم‌های یادگیری ماشین الگوهای حرکتی ماوس، سرعت عمل و توالی رویدادها را تحلیل می‌کنند.

تأخیرهای تصادفی بین اقدامات

هرگز از تأخیرهای ثابت استفاده نکنید. کاربران واقعی برای مدت‌های مختلفی توقف می‌کنند:

import random
import time

def human_delay(min_seconds=1, max_seconds=3):
    """تأخیر تصادفی شبیه‌سازی‌کننده انسان"""
    delay = random.uniform(min_seconds, max_seconds)
    time.sleep(delay)

# استفاده
driver.get('https://example.com')
human_delay(2, 4)  # توقف 2-4 ثانیه

element = driver.find_element(By.ID, 'search')
human_delay(0.5, 1.5)  # توقف کوتاه قبل از وارد کردن

element.send_keys('search query')
human_delay(1, 2)

حرکت نرم ماوس

ربات‌ها ماوس را به صورت خطوط مستقیم حرکت می‌دهند یا نشانگر را تلپورت می‌کنند. کاربران واقعی مسیرهای منحنی با شتاب و کاهش سرعت ایجاد می‌کنند:

// Puppeteer: حرکت نرم ماوس
async function humanMouseMove(page, targetX, targetY) {
    const steps = 25; // تعداد نقاط میانی
    const currentPos = await page.evaluate(() => ({
        x: window.mouseX || 0,
        y: window.mouseY || 0
    }));
    
    for (let i = 0; i <= steps; i++) {
        const t = i / steps;
        // استفاده از easing برای نرمی
        const ease = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
        
        const x = currentPos.x + (targetX - currentPos.x) * ease;
        const y = currentPos.y + (targetY - currentPos.y) * ease;
        
        await page.mouse.move(x, y);
        await page.waitForTimeout(Math.random() * 10 + 5);
    }
    
    // ذخیره موقعیت
    await page.evaluate((x, y) => {
        window.mouseX = x;
        window.mouseY = y;
    }, targetX, targetY);
}

// استفاده
await humanMouseMove(page, 500, 300);
await page.mouse.click(500, 300);

اسکرول طبیعی

کاربران واقعی به آرامی اسکرول می‌کنند و برای خواندن محتوا توقف می‌کنند:

async function humanScroll(page) {
    const scrollHeight = await page.evaluate(() => document.body.scrollHeight);
    const viewportHeight = await page.evaluate(() => window.innerHeight);
    
    let currentPosition = 0;
    
    while (currentPosition < scrollHeight - viewportHeight) {
        // قدم تصادفی اسکرول (200-500px)
        const scrollStep = Math.floor(Math.random() * 300) + 200;
        currentPosition += scrollStep;
        
        // اسکرول نرم
        await page.evaluate((pos) => {
            window.scrollTo({
                top: pos,
                behavior: 'smooth'
            });
        }, currentPosition);
        
        // توقف برای "خواندن" محتوا (1-3 ثانیه)
        await page.waitForTimeout(Math.random() * 2000 + 1000);
    }
}

// استفاده
await page.goto('https://example.com');
await humanScroll(page);

وارد کردن متن طبیعی

افراد با سرعت‌های مختلف تایپ می‌کنند، اشتباه تایپی می‌کنند و آن‌ها را اصلاح می‌کنند:

async function humanTypeText(page, selector, text) {
    await page.click(selector);
    
    for (let char of text) {
        // تأخیر تصادفی بین فشارها (50-200ms)
        const delay = Math.random() * 150 + 50;
        await page.waitForTimeout(delay);
        
        // 5% شانس اشتباه تایپی
        if (Math.random() < 0.05) {
            // تایپ یک کاراکتر تصادفی
            const wrongChar = String.fromCharCode(97 + Math.floor(Math.random() * 26));
            await page.keyboard.type(wrongChar);
            await page.waitForTimeout(100 + Math.random() * 100);
            // حذف (Backspace)
            await page.keyboard.press('Backspace');
            await page.waitForTimeout(50 + Math.random() * 50);
        }
        
        await page.keyboard.type(char);
    }
}

// استفاده
await humanTypeText(page, '#search-input', 'example search query');

ادغام پروکسی برای ناشناسی کامل

پنهان‌سازی مرورگر بی‌فایده است اگر تمام درخواست‌ها از یک آدرس IP واحد ارسال شوند. سیستم‌های ضد ربات تعداد درخواست‌ها را از هر IP ردیابی کرده و فعالیت مشکوک را مسدود می‌کنند. پروکسی یک جزء ضروری برای هر اتوماسیون جدی است.

انتخاب نوع پروکسی

وظایف مختلف به انواع مختلف پروکسی نیاز دارند:

نوع پروکسی مزایا کاربرد
پروکسی‌های HTTP ساده و سریع وب‌گردی و اتوماسیون ساده
پروکسی‌های SOCKS پشتیبانی از انواع پروتکل‌ها اتوماسیون پیچیده و بازی‌ها
پروکسی‌های روتین ناشناسی بالا اتوماسیون حساس و جمع‌آوری داده‌ها

ادغام پروکسی در Selenium

برای ادغام پروکسی در Selenium، می‌توانید از کد زیر استفاده کنید:

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

chrome_options = Options()
chrome_options.add_argument('--proxy-server=http://your-proxy-server:port')

driver = webdriver.Chrome(options=chrome_options)
driver.get('https://example.com')

کتابخانه‌ها و ابزارهای آماده

برای تسهیل کار، می‌توانید از کتابخانه‌ها و ابزارهای آماده زیر استفاده کنید:

  • selenium-stealth — کتابخانه‌ای برای پنهان‌سازی Selenium
  • puppeteer-extra — کتابخانه‌ای برای Puppeteer با پلاگین‌های اضافی
  • undetected-chromedriver — نسخه‌ای از ChromeDriver که به طور خودکار پنهان‌سازی می‌کند

آزمایش سطح تشخیص

برای ارزیابی اینکه آیا اتوماسیون شما شناسایی می‌شود یا خیر، می‌توانید از وب‌سایت‌های تست تشخیص استفاده کنید. این وب‌سایت‌ها می‌توانند به شما بگویند که آیا نشانه‌های اتوماسیون شما شناسایی شده‌اند یا خیر.

نتیجه‌گیری

پنهان‌سازی اتوماسیون مرورگر یک چالش پیچیده است که نیاز به درک عمیق از روش‌های تشخیص و تکنیک‌های پنهان‌سازی دارد. با استفاده از روش‌ها و ابزارهای مناسب، می‌توانید شانس خود را برای موفقیت افزایش دهید.

```