اگر شما به پارسینگ مارکتپلیسها، نظارت بر قیمت رقبا یا جمعآوری داده از وبسایتها مشغول هستید، با این مشکل آشنا هستید: وبسایتها آدرسهای IP را مسدود میکنند، کپچا درخواست میکنند یا صفحات خالی برمیگردانند. نرخ مسدودسازی (درصد درخواستهای مسدودشده) میتواند به 70-90% برسد که پارسینگ را غیرممکن میکند. در این مقاله روشهای مشخصی را بررسی میکنیم که به کاهش نرخ مسدودسازی تا 5-10% و جمعآوری پایدار دادهها کمک میکند.
ما هم راهحلهای فنی (چرخش پروکسی، هدرهای HTTP، fingerprinting) و هم الگوهای رفتاری (تاخیرها، تقلید اقدامات کاربر) را بررسی خواهیم کرد. تمام روشها در عمل هنگام پارسینگ Wildberries، Ozon، Avito و پلتفرمهای خارجی آزمایش شدهاند.
چرا وبسایتها پارسرها را مسدود میکنند: محرکهای اصلی
قبل از بررسی روشهای حفاظتی، مهم است بفهمیم که وبسایتها چگونه ترافیک خودکار را تشخیص میدهند. سیستمهای مدرن ضد ربات (Cloudflare، Akamai، DataDome، Imperva) دهها پارامتر از هر درخواست را تحلیل میکنند. در اینجا محرکهای اصلی مسدودسازی آمده است:
محرکها در سطح شبکه:
- درخواستهای بیش از حد از یک آدرس IP (مثلاً بیش از 100 درخواست در دقیقه)
- IP از محدودههای شناختهشده دیتاسنترها (AWS، Google Cloud، Hetzner)
- عدم تطابق جغرافیایی: IP از روسیه نسخه انگلیسی سایت را درخواست میکند
- نبود رکورد DNS معکوس برای آدرس IP
محرکها در سطح HTTP:
- نبود یا نادرستی هدرهای HTTP (User-Agent، Accept-Language، Referer)
- ترتیب هدرها با استاندارد مرورگر متفاوت است
- نسخه TLS/SSL با مرورگر اعلامشده مطابقت ندارد
- نبود کوکیها یا استفاده نادرست از آنها
محرکها در سطح مرورگر (JavaScript):
- نبود اجرای JavaScript (اگر از کلاینت HTTP ساده استفاده میکنید)
- Browser fingerprinting: Canvas، WebGL، AudioContext، فونتهای نصبشده
- نبود حرکت موس، اسکرول، کلیک
- اندازه پنجره مرورگر (مرورگرهای headless اغلب اندازههای غیراستاندارد دارند)
- وجود اتوماسیون: ویژگیهای navigator.webdriver، window.chrome
محرکهای رفتاری:
- ناوبری بیش از حد سریع بین صفحات (کمتر از 1 ثانیه)
- فواصل یکسان بین درخواستها (مثلاً دقیقاً هر 2 ثانیه)
- طی کردن متوالی صفحات (1، 2، 3، 4...) بدون پرش
- نبود اقدامات معمول کاربر: جستجو، فیلترها، مشاهده تصاویر
به عنوان مثال، هنگام پارسینگ Wildberries، اشتباه معمول ارسال درخواستها هر 0.5 ثانیه از یک IP است. سیستم ضد ربات Cloudflare فوراً الگو را تشخیص داده و IP را برای 24 ساعت مسدود میکند. کاربر واقعی 5-15 ثانیه برای مشاهده کارت محصول صرف میکند، صفحه را اسکرول میکند، روی تصاویر کلیک میکند.
چرخش پروکسی: چگونه آدرسهای IP را به درستی تغییر دهیم
استفاده از پروکسی روش پایهای برای کاهش نرخ مسدودسازی است. اما مهم است که فقط پروکسی نخریم، بلکه چرخش را به درستی تنظیم کنیم. در اینجا استراتژیهای اثباتشده آمده است:
انتخاب نوع پروکسی برای پارسینگ
| نوع پروکسی | نرخ مسدودسازی | سرعت | چه زمانی استفاده کنیم |
|---|---|---|---|
| پروکسی دیتاسنتر | بالا (40-60%) | بسیار بالا | سایتهای ساده بدون حفاظت، پارسینگ انبوه با استخر بزرگ IP |
| پروکسی مسکونی | پایین (5-15%) | متوسط | مارکتپلیسها (Wildberries، Ozon)، سایتها با Cloudflare، شبکههای اجتماعی |
| پروکسی موبایل | بسیار پایین (2-8%) | پایین | سایتها با حفاظت تهاجمی، نسخههای موبایل اپلیکیشنها |
برای پارسینگ مارکتپلیسها (Wildberries، Ozon، Avito) پروکسیهای مسکونی توصیه میشود — آنها IP کاربران واقعی خانگی دارند که تشخیص آنها از ترافیک عادی دشوار است. پروکسیهای دیتاسنتر برای سایتهای کمتر محافظتشده یا زمانی که سرعت بیشینه با حجم زیاد داده مورد نیاز است، مناسب هستند.
استراتژیهای چرخش آدرسهای IP
استراتژی 1: چرخش بر اساس زمان
IP را هر 5-10 دقیقه تغییر دهید. این تعادل بهینه است: به اندازه کافی طولانی که تغییر مکرر سوء ظن ایجاد نکند، اما به اندازه کافی مکرر که تاریخچه درخواستها روی یک IP انباشته نشود.
مثال: هنگام پارسینگ کاتالوگ 1000 محصولی با فاصله 3 ثانیه بین درخواستها، یک IP تقریباً 100 درخواست فعال خواهد بود، سپس تغییر رخ میدهد.
استراتژی 2: چرخش بر اساس تعداد درخواستها
IP را بعد از 50-150 درخواست تغییر دهید. این به جلوگیری از انباشت فعالیت مشکوک روی یک آدرس کمک میکند. تصادفیسازی اضافه کنید: نه دقیقاً 100 درخواست، بلکه از 80 تا 120.
مثال: اسکریپت را طوری تنظیم کنید که بعد از تعداد تصادفی درخواستها (80-120) چرخش پروکسی از استخر رخ دهد.
استراتژی 3: Sticky sessions (پروکسیهای نشستی)
برای سایتهایی که نیاز به احراز هویت دارند یا با سبد خرید کار میکنند، از sticky sessions استفاده کنید — تثبیت IP برای مدت نشست (10-30 دقیقه). این اجازه میدهد کوکیها حفظ شوند و هنگام تغییر IP در یک نشست سوء ظن ایجاد نشود.
مثال: هنگام پارسینگ پنل کاربری در Ozon، از یک IP برای ورود و تمام درخواستهای بعدی در طول نشست 15 دقیقهای استفاده کنید.
مهم: از یک IP برای وظایف مختلف استفاده نکنید. اگر IP هنگام پارسینگ یک سایت مسدود شد، بلافاصله برای سایت دیگر استفاده نکنید — 24-48 ساعت صبر کنید.
اندازه استخر پروکسی
حداقل اندازه استخر به شدت پارسینگ بستگی دارد:
- شدت پایین (تا 10,000 درخواست در روز): 10-20 پروکسی
- شدت متوسط (10,000 - 100,000 درخواست در روز): 50-100 پروکسی
- شدت بالا (بیش از 100,000 درخواست در روز): 200+ پروکسی یا مسکونی با چرخش خودکار
برای پروکسیهای مسکونی با چرخش در هر درخواست (rotating proxies)، اندازه استخر میتواند کمتر باشد، زیرا ارائهدهنده به طور خودکار IP جدید از استخر میلیونی خود جایگزین میکند.
User-Agent و هدرهای HTTP: تقلید مرورگر واقعی
حتی با پروکسیهای خوب، اگر هدرهای HTTP مشکوک به نظر برسند، ممکن است مسدود شوید. سایتها نه تنها User-Agent، بلکه ترتیب هدرها، مقادیر آنها و تطابق با یکدیگر را تحلیل میکنند.
User-Agent صحیح
از یک User-Agent یکسان برای همه درخواستها استفاده نکنید. لیستی از مرورگرهای محبوب ایجاد کنید و به صورت تصادفی از آن انتخاب کنید:
user_agents = [
# Chrome on Windows
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
# Chrome on macOS
"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",
# Firefox on Windows
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
# Safari on macOS
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15",
# Edge on Windows
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0"
]
اشتباه: استفاده از نسخههای قدیمی مرورگرها (مثلاً Chrome 80) — این فوراً سوء ظن ایجاد میکند. لیست User-Agent را هر 2-3 ماه یکبار بهروز کنید و نسخههای فعلی را در سایت whatismybrowser.com دنبال کنید.
مجموعه کامل هدرهای HTTP
مرورگرهای مدرن 15-20 هدر ارسال میکنند. در اینجا مجموعه حداقل لازم برای تقلید Chrome آمده است:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Language": "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7",
"Accept-Encoding": "gzip, deflate, br",
"DNT": "1",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Cache-Control": "max-age=0",
"sec-ch-ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": '"Windows"'
}
به هدرهای Sec-Fetch-* و sec-ch-ua-* توجه کنید — آنها در نسخههای جدید Chrome ظاهر شدهاند و نبود آنها میتواند اتوماسیون را فاش کند.
ترتیب هدرها اهمیت دارد
مرورگرها هدرها را به ترتیب مشخصی ارسال میکنند. به عنوان مثال، Chrome همیشه Host را اول، سپس Connection، User-Agent و غیره قرار میدهد. اگر از کتابخانه Python requests استفاده کنید، ترتیب ممکن است الفبایی باشد که اتوماسیون را فاش میکند.
راهحل: از کتابخانههایی استفاده کنید که هدرها را به درستی شکل میدهند (curl_cffi برای Python، got برای Node.js) یا مرورگرهای headless (Puppeteer، Playwright، Selenium) که هدرها را مانند مرورگر واقعی تولید میکنند.
تاخیر بین درخواستها: فواصل بهینه
یکی از سادهترین اما مؤثرترین روشهای کاهش نرخ مسدودسازی، تاخیرهای صحیح بین درخواستها است. کاربر واقعی نمیتواند 10 صفحه در ثانیه باز کند، بنابراین درخواستهای بیش از حد سریع فوراً باعث مسدودسازی میشوند.
تاخیرهای تصادفی به جای ثابت
از تاخیر ثابت استفاده نکنید (مثلاً دقیقاً 2 ثانیه بین درخواستها). سیستمهای ضد ربات به راحتی چنین الگویی را تشخیص میدهند. از فاصله تصادفی استفاده کنید:
import random
import time
# به جای تاخیر ثابت
time.sleep(2) # ❌ بد
# از فاصله تصادفی استفاده کنید
delay = random.uniform(2.5, 5.5) # ✅ خوب
time.sleep(delay)
فواصل توصیهشده برای سایتهای مختلف
| نوع سایت | حداقل تاخیر | تاخیر توصیهشده | مثالها |
|---|---|---|---|
| مارکتپلیسها با حفاظت | 3-5 ثانیه | 5-10 ثانیه | Wildberries، Ozon، Lamoda |
| تابلوهای اعلانات | 2-4 ثانیه | 4-8 ثانیه | Avito، Yula، CIAN |
| سایتهای خبری | 1-2 ثانیه | 2-4 ثانیه | RBC، Kommersant، Vedomosti |
| API بدون محدودیت | 0.5-1 ثانیه | 1-2 ثانیه | APIهای باز، فیدهای RSS |
تاخیرهای تطبیقی بر اساس پاسخهای سرور
رویکرد پیشرفته — تغییر پویای تاخیرها بسته به پاسخهای سرور:
base_delay = 3.0 # تاخیر پایه
delay_multiplier = 1.0
response = requests.get(url, headers=headers, proxies=proxies)
# اگر کپچا یا 429 دریافت کردیم — تاخیر را افزایش میدهیم
if response.status_code == 429 or 'captcha' in response.text.lower():
delay_multiplier *= 1.5
print(f"حفاظت شناسایی شد، تاخیر را به {base_delay * delay_multiplier}ث افزایش میدهیم")
# اگر همه چیز خوب است — میتوانیم کمی سرعت بگیریم
elif response.status_code == 200:
delay_multiplier = max(1.0, delay_multiplier * 0.95)
time.sleep(random.uniform(base_delay * delay_multiplier, base_delay * delay_multiplier * 1.5))
این رویکرد اجازه میدهد هنگام شناسایی حفاظت به طور خودکار کند شوید و زمانی که سایت تهاجمی نشان نمیدهد، سرعت بگیرید.
حفاظت در برابر fingerprinting: Canvas، WebGL، فونتها
اگر سایت از JavaScript برای بررسی استفاده میکند، هدرهای ساده HTTP کافی نیستند. سیستمهای مدرن ضد ربات "اثر انگشت" مرورگر (fingerprint) را بر اساس دهها پارامتر ایجاد میکنند: Canvas، WebGL، فونتهای نصبشده، منطقه زمانی، وضوح صفحه و سایر موارد.
پارامترهای اصلی fingerprinting
Canvas fingerprinting
سایت یک تصویر نامرئی در Canvas رسم میکند و آن را میخواند. مرورگرها و سیستمعاملهای مختلف تصویر را متفاوت رندر میکنند و اثر انگشت منحصر به فرد ایجاد میکنند. مرورگرهای Headless اغلب Canvas یکسانی تولید میکنند که اتوماسیون را فاش میکند.
WebGL fingerprinting
مشابه Canvas، اما از رندرینگ 3D استفاده میکند. اطلاعات کارت گرافیک، درایورها، افزونههای پشتیبانیشده خوانده میشود. مرورگرهای Headless اغلب رندرینگ نرمافزاری (SwiftShader) را به جای GPU واقعی نشان میدهند.
فونتهای نصبشده
JavaScript میتواند لیست فونتهای نصبشده را تعیین کند. مرورگرهای headless معمولاً مجموعه حداقلی از فونتهای سیستمی دارند که با کاربر واقعی با Microsoft Office، Adobe و سایر برنامههای نصبشده متفاوت است.
ویژگیهای Navigator
ویژگیهای navigator.webdriver، navigator.plugins، navigator.languages اتوماسیون را فاش میکنند. به عنوان مثال، در Selenium navigator.webdriver === true است که فوراً توسط سیستمهای ضد ربات شناسایی میشود.
ابزارهای دور زدن fingerprinting
برای دور زدن fingerprinting از ابزارهای تخصصی استفاده کنید:
- Undetected ChromeDriver (Python) — نسخه اصلاحشده Selenium که نشانههای اتوماسیون را پنهان میکند
- Puppeteer Stealth (Node.js) — پلاگین برای Puppeteer که پارامترهای fingerprint را جایگزین میکند
- Playwright با stealth — مشابه Puppeteer، اما با پشتیبانی بهتر از مرورگرهای مختلف
- مرورگرهای ضد شناسایی (Dolphin Anty، AdsPower، Multilogin) — برای کسانی که نمیخواهند کد بنویسند، این مرورگرها به طور خودکار fingerprint را جایگزین میکنند
مثال استفاده از undetected-chromedriver در Python:
import undetected_chromedriver as uc
# مرورگر با حفاظت در برابر شناسایی ایجاد میکنیم
options = uc.ChromeOptions()
options.add_argument('--disable-blink-features=AutomationControlled')
driver = uc.Chrome(options=options)
driver.get('https://example.com')
# بررسی میکنیم که navigator.webdriver === undefined
webdriver_status = driver.execute_script("return navigator.webdriver")
print(f"navigator.webdriver: {webdriver_status}") # باید None/undefined باشد
مدیریت کوکیها و سشنها
بسیاری از سایتها از کوکیها برای ردیابی رفتار کاربران استفاده میکنند. مدیریت صحیح کوکیها به جلوگیری از مسدودسازی و به نظر رسیدن مانند کاربر واقعی کمک میکند.
ذخیره و استفاده مجدد از کوکیها
به جای ایجاد سشن جدید در هر درخواست، کوکیها را ذخیره کنید و دوباره استفاده کنید. این رفتار کاربر واقعی را که به سایت برمیگردد، تقلید میکند:
import requests
import pickle
session = requests.Session()
# اولین بازدید — کوکیها را دریافت میکنیم
response = session.get('https://example.com')
# کوکیها را در فایل ذخیره میکنیم
with open('cookies.pkl', 'wb') as f:
pickle.dump(session.cookies, f)
# بعداً کوکیها را بارگذاری میکنیم
with open('cookies.pkl', 'rb') as f:
session.cookies.update(pickle.load(f))
# حالا درخواستها مانند کاربر بازگشته به نظر میرسند
response = session.get('https://example.com/catalog')
گرم کردن سشن قبل از پارسینگ
پارسینگ را بلافاصله از صفحات هدف شروع نکنید. رفتار کاربر واقعی را تقلید کنید:
- صفحه اصلی سایت را باز کنید
- 2-5 ثانیه صبر کنید
- صفحه دستهبندی یا بخش را باز کنید
- 3-7 ثانیه صبر کنید
- فقط بعد از آن شروع به پارس کردن صفحات هدف کنید
این تاریخچه فعالیت را در کوکیها ایجاد میکند و احتمال مسدودسازی را کاهش میدهد.
پردازش کوکیهای سشن و توکنها
برخی سایتها در اولین بازدید توکنهای منحصر به فرد تولید میکنند و آنها را در درخواستهای بعدی بررسی میکنند. به عنوان مثال، Wildberries از توکن در هدر x-requested-with استفاده میکند. همیشه چنین توکنهایی را از اولین پاسخ ذخیره کنید و در درخواستهای بعدی ارسال کنید.
رندر کردن JavaScript: چه زمانی ضروری است
بسیاری از سایتهای مدرن محتوا را از طریق JavaScript بارگذاری میکنند. اگر از کلاینت HTTP ساده استفاده کنید (requests در Python، axios در Node.js)، صفحه خالی یا جایگزین دریافت خواهید کرد. در چنین مواردی رندر کردن JavaScript ضروری است.
چه زمانی رندر کردن JavaScript لازم است
- سایت از React، Vue، Angular استفاده میکند — محتوا بعد از بارگذاری اولیه صفحه بارگذاری میشود
- دادهها از طریق درخواستهای AJAX/Fetch بارگذاری میشوند
- سایت برای تولید توکنها یا کوکیها نیاز به اجرای JavaScript دارد
- حفاظت در برابر رباتها وجود دارد که نیاز به اجرای کد JS دارد (مثلاً Cloudflare Challenge)
ابزارهای رندر کردن JavaScript
| ابزار | زبان | سرعت | دور زدن حفاظت |
|---|---|---|---|
| Selenium | Python، Java، C# | کند | متوسط (با undetected-chromedriver) |
| Puppeteer | Node.js | متوسط | خوب (با puppeteer-extra-plugin-stealth) |
| Playwright | Python، Node.js، Java | سریع | عالی |
| Splash | HTTP API | متوسط | ضعیف |
برای اکثر وظایف Playwright توصیه میشود — سریعتر از Selenium است، بهتر حفاظت را دور میزند و API راحتتری دارد.
جایگزین: رهگیری درخواستهای API
اغلب میتوان از رندر کردن JavaScript اجتناب کرد، اگر درخواستهای API که سایت برای بارگذاری دادهها استفاده میکند را پیدا کنید. DevTools (F12) → تب Network → فیلتر XHR/Fetch را باز کنید و ببینید سایت چه درخواستهایی ارسال میکند. سپس این درخواستها را مستقیماً از طریق کلاینت HTTP تکرار کنید.
مثال: Wildberries دادههای محصولات را از طریق API https://catalog.wb.ru/catalog/... بارگذاری میکند. به جای رندر کردن کل صفحه میتوانید مستقیماً این API را درخواست کنید که 10-20 برابر سریعتر است.
دور زدن کپچا: راهحلهای خودکار
حتی با پروکسی و هدرهای صحیح ممکن است با کپچا مواجه شوید. چندین رویکرد برای حل آن وجود دارد:
انواع کپچا و روشهای حل
reCAPTCHA v2 (تیک "من ربات نیستم")
از طریق سرویسهای تشخیص حل میشود: 2Captcha، Anti-Captcha، CapMonster. هزینه: 1-3 دلار برای 1000 حل. زمان حل: 10-30 ثانیه.
reCAPTCHA v3 (نامرئی، مبتنی بر امتیاز)
پیچیدهتر است. رفتار کاربر را تحلیل میکند و امتیازی از 0 تا 1 میدهد. دور زدن: استفاده از مرورگرهای headless با fingerprint صحیح + تقلید اقدامات کاربر (حرکت موس، کلیک).
hCaptcha
مشابه reCAPTCHA، در بسیاری از سایتها استفاده میشود. از طریق همان سرویسهای تشخیص حل میشود. هزینه: 0.5-2 دلار برای 1000 حل.
Cloudflare Challenge
چالش JavaScript که مرورگر را بررسی میکند. دور زدن: استفاده از کتابخانههای تخصصی (cloudscraper برای Python، cloudflare-scraper برای Node.js) یا سرویسها (FlareSolverr).
یکپارچهسازی سرویس تشخیص کپچا
مثال یکپارچهسازی 2Captcha در Python:
from twocaptcha import TwoCaptcha
solver = TwoCaptcha('YOUR_API_KEY')
try:
# reCAPTCHA v2 را حل میکنیم
result = solver.recaptcha(
sitekey='6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-',
url='https://example.com'
)
# توکن حل را دریافت میکنیم
captcha_token = result['code']
# فرم را با توکن ارسال میکنیم
response = requests.post('https://example.com/submit', data={
'g-recaptcha-response': captcha_token
})
except Exception as e:
print(f"خطای حل کپچا: {e}")
مهم: حل کپچا پارسینگ را 10-30 برابر کند میکند و هزینه را افزایش میدهد. فقط زمانی از آن استفاده کنید که روشهای دیگر کار نمیکنند. ابتدا سعی کنید پروکسی، fingerprint و تاخیرها را بهبود دهید.
محدودیت نرخ: چگونه از محدودیتهای سایت فراتر نرویم
بسیاری از سایتها محدودیتهای آشکار یا پنهان در تعداد درخواستها دارند. فراتر رفتن از این محدودیتها منجر به مسدودسازی موقت یا دائمی IP میشود.
تعیین محدودیتهای سایت
به هدرهای HTTP در پاسخهای سرور توجه کنید:
X-RateLimit-Limit— حداکثر تعداد درخواستها در دورهX-RateLimit-Remaining— چند درخواست باقی ماندهX-RateLimit-Reset— چه زمانی محدودیت ریست میشود (Unix timestamp)Retry-After— بعد از چند ثانیه میتوان درخواست را تکرار کرد
اگر کد وضعیت 429 (Too Many Requests) دریافت کردید، این به معنای فراتر رفتن از محدودیت است. هدر Retry-After را بخوانید و زمان مشخصشده را قبل از درخواست بعدی صبر کنید.
پیادهسازی محدودکننده نرخ
مکانیزم کنترل سرعت درخواستها ایجاد کنید: