خانه/مقالات/اسکریپ با NodeJS: ترفندهای عبور از Anti‑Bot
پروکسی و چرخش IP
ضد بلاک (Anti-bot)
Headless Chrome
برگشت به صفحه مقاله ها
اسکریپ با NodeJS: ترفندهای عبور از Anti‑Bot

اسکریپ با NodeJS: ترفندهای عبور از Anti‑Bot

این مقاله یک راهنمای عملی برای عبور از مکانیسم‌های ضدبات با NodeJS ارائه می‌دهد؛ از بهینه‌سازی هدرها و پروکسی‌های چرخان تا مرورگرهای headless، حل CAPTCHA و سرویس‌های مدیریت‌شده. همراه با مثال‌های کد، نکات عملکردی و هشدارهای حقوقی، گزینه‌های مناسب برای سناریوهای مختلف شرح داده شده‌اند.
امیر حسین حسینیان
امیر حسین حسینیان
1404-09-23

مقدمه

این مقاله یک راهنمای فنی و عملی برای توسعه‌دهنده‌های سطح متوسط پایتون/Node.js است که می‌خواهند وب اسکریپینگ را مقابل سیستم‌های ضدبات (anti-bot) قابل اتکا کنند. در پایان این مطلب شما با انواع مکانیسم‌های تشخیص بات، مجموعه‌ای از روش‌های کاربردی (از بهینه‌سازی هدرها تا مرورگرهای headless مستحکم و سرویس‌های مدیریت‌شده) آشنا می‌شوید و مثال‌های کد NodeJS برای هر روش را خواهید دید.

هدف این راهنما ارائهٔ توضیحات خط‌به‌خط برای کدها، ذکر ورودی‌ها و خروجی‌ها، و نکات عملی در مورد امنیت، عملکرد و نگهداری است — نه فقط فهرست‌وار مرور روش‌ها.

خلاصهٔ سریع (TL;DR)

اگر دنبال راه‌حل سریع هستید: ترکیب Playwright یا Puppeteer (برای رندر جاوااسکریپت) با یک پول پروکسیِ چرخان، به همراه بهینه‌سازی هدرها و مدیریت کوکی/سشن، برای بسیاری از سایت‌ها کافی است. در موارد سخت‌تر از سرویس‌های مدیریت‌شده یا حل‌کنندهٔ CAPTCHA استفاده کنید.

فهم مکانیسم‌های Anti-Bot

قبل از هر چیز باید بدانید چه چیزی را باید دور زد. روش‌های معمول تشخیص بات شامل موارد زیر هستند:

  • IP Blocking و Rate Limiting
  • شناسایی User-Agent و هدرهای غیرمعمول
  • چالش‌های جاوااسکریپت (برای بررسی اجرای کد در مرورگر)
  • CAPTCHA
  • تحلیل رفتاری (حرکات ماوس، اسکرول، ترتیب کلیک)

معمولاً ترکیبی از این مکانیسم‌ها به کار می‌رود؛ بنابراین راه‌حل هم باید ترکیبی و لایه‌ای باشد.

روش 1 — بهینه‌سازی Request Fingerprints (هدرها و UA)

ایدهٔ کلی: درخواست‌های شما باید از نظر هدرها و fingerprintهای مبتنی بر HTTP نزدیک به مرورگر واقعی به نظر برسند.

چه کار می‌کنیم و چرا: هدرهای رایج مثل User-Agent، Accept-Language، Accept-Encoding و Referer را می‌سازیم و آنها را به‌صورت چرخان (rotate) یا با مجموعهٔ از مقادیر واقعی تنظیم می‌کنیم تا الگوهای ثابت ایجاد نشود.

مثال کد با axios:

const axios = require('axios');

async function fetchPage() {
  // ورودی: آدرس URL
  // خروجی: HTML صفحه یا خطا
  try {
    const response = await axios.get('https://example.com', {
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117 Safari/537.36',
        'Accept-Language': 'en-US,en;q=0.9',
        'Accept-Encoding': 'gzip, deflate, br',
        'Connection': 'keep-alive',
        'Referer': 'https://google.com/'
      },
      timeout: 15000
    });
    return response.data; // HTML صفحه
  } catch (err) {
    throw err; // فراخوان باید خطا را هندل کند (retry، backoff، logging)
  }
}

fetchPage().then(html => console.log('got', html.length)).catch(e => console.error(e));

توضیحات بخش‌به‌بخش:

  • axios.get: ارسال GET با هدرهای سفارشی. ورودی: URL و گزینه‌ها. خروجی: شیٔ پاسخ حاوی data.
  • هدرها باید از منابع واقعی استخراج یا از لیست‌های معتبر چرخان انتخاب شوند؛ هدرهای کاملاً ساختگی سریع تشخیص داده می‌شوند.
  • Best practice: همیشه timeout و retry با backoff داشته باشید تا جلوی صف‌های معیوب و رفتار تهاجمی گرفته شود.

روش 2 — استفاده از پول پروکسی چرخان

ایدهٔ کلی: با تغییر IP برای هر درخواست یا هر جلسه، ریسک بلوکه‌شدن بر اساس IP را کاهش می‌دهیم.

نکات مهم:

  • از پروکسی‌های پرداختی (residential یا ISP) در صورت امکان استفاده کنید؛ پروکسی‌های رایگان اغلب کند و بلاک‌شده‌اند.
  • برای هر پروکسی نرخ و کانفیگِ زمان انتظار و تست سلامت (healthcheck) تعریف کنید.

مثال با Playwright و استفاده از پراکسی (الگوریتمی مشابه):

const playwright = require('playwright');

(async () => {
  // ورودی: تنظیمات پروکسی (host، port، username، password)
  // خروجی: HTML رندرشده یا خطا
  const proxy = {
    server: 'http://proxy-host:8000',
    username: 'PROXY_USER',
    password: 'PROXY_PASS'
  };

  const browser = await playwright.chromium.launch({ headless: true, proxy });
  const context = await browser.newContext({ ignoreHTTPSErrors: true });
  const page = await context.newPage();

  try {
    await page.goto('https://example.com', { timeout: 180000 });
    const html = await page.content();
    console.log('len', html.length);
  } catch (err) {
    console.error('goto error', err);
  } finally {
    await browser.close();
  }
})();

نکات عملی:

  • پروکسی‌ها را قبل از استفاده تست کنید (latency، status codes).
  • استفاده از پروکسی‌های residential برای سایت‌های حساس بهتر است.
  • پالایش مانیتورینگ: ثبت میزان خطا به ازای هر IP برای حذف IPهای بد.

روش 3 — مرورگرهای Headless تقویت‌شده

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

چند گزینه رایج: Puppeteer، Playwright و نسخه‌های «undetected» برای کروم که برخی fingerprintها را پنهان می‌کنند.

مثال با puppeteer:

const puppeteer = require('puppeteer');

async function fetchWithPuppeteer(url) {
  // ورودی: url
  // خروجی: HTML رندرشده
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();

  // شبیه‌سازی اندازه صفحه و timezone برای طبیعی‌تر شدن
  await page.setViewport({ width: 1366, height: 768 });
  await page.setExtraHTTPHeaders({ 'Accept-Language': 'en-US,en;q=0.9' });

  await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 });
  const content = await page.content();
  await browser.close();
  return content;
}

fetchWithPuppeteer('https://example.com').then(c => console.log('len', c.length));

نکات عملکردی و هزینه‌ای:

  • Headless browserها منابع بیشتری مصرف می‌کنند (CPU، حافظه). برای مقیاس‌پذیری از کانتینریزه‌کردن و افقی‌شدن نمونه‌ها استفاده کنید.
  • برای سایت‌های دارای چالش‌های پیچیده باید تعاملات (mouse.move، scroll، تایپ) را شبیه‌سازی کنید تا رفتار واقعی‌تر شود.

روش 4 — سرویس‌های Managed Anti-Bot Bypass

ایدهٔ کلی: وقتی زمان یا توان فنی محدود است، از سرویس‌هایی استفاده کنید که لایه‌های عبور را به‌صورت سرویس ارائه می‌دهند؛ این سرویس‌ها معمولاً ترکیبی از رندر سروری، پروکسی‌های residential و حل‌کنندهٔ چالش هستند.

چه چیزهای مهم است:

  • مدل قیمت: per-request، per-GB یا اشتراک. مقیاس را قبل از انتخاب محاسبه کنید.
  • پایداری و SLA: بررسی کنید سرویس در طول زمان پایدار باشد و نرخ موفقیت را اندازه‌گیری کنید.

نکات امنیتی و حفظ حریم خصوصی: اطلاعات حساس (مثل کوکی‌های لاگین) را در سرویس‌های ثالث ذخیره نکنید مگر سیاست‌های آنها را بررسی کرده باشید.

روش 5 — حل CAPTCHA

ایدهٔ کلی: CAPTCHAها با هدف تشخیص انسان از ربات طراحی شده‌اند؛ برای اتوماسیون می‌توان از سرویس‌های حل‌کنندهٔ انسانی یا الگوریتمی استفاده کرد.

مثال خلاصه با یک کتابخانهٔ Node که به سرویس‌هایی مثل 2Captcha وصل می‌شود:

const TwoCaptcha = require('2captcha');

const solver = new TwoCaptcha('YOUR_API_KEY');

// ورودی: sitekey و آدرس صفحه‌ای که reCAPTCHA دارد
// خروجی: توکن پاسخ (token) که باید به فرم ارسال شود
solver.recaptcha('SITE_KEY', 'https://target.example.com')
  .then(res => console.log('captcha token', res))
  .catch(err => console.error('captcha error', err));

نکات عملی:

  • همیشه توکن را بلافاصله پس از دریافت استفاده کنید (توکن‌ها معمولاً زمان کوتاهی اعتبار دارند).
  • هزینه و نرخ خطا را در نظر بگیرید؛ استفادهٔ وسیع از حل‌کنندهٔ CAPTCHA سریعاً هزینه‌بر می‌شود.

روش 6 — استفاده از نسخهٔ کشِ موتورهای جستجو

ایدهٔ کلی: در مواردی که نیاز به دادهٔ بلافاصله به‌روز ندارید، می‌توان از نسخه‌های cached که توسط موتورهای جستجو ذخیره شده‌اند استفاده کرد و از بسیاری از محدودیت‌های زمان واقعی عبور کرد.

نمونهٔ ساده با axios:

const axios = require('axios');

async function fetchGoogleCache(targetUrl) {
  // ورودی: URL هدف
  // خروجی: HTML کش‌شده یا خطا
  const cacheUrl = `https://webcache.googleusercontent.com/search?q=cache:${encodeURIComponent(targetUrl)}`;
  const res = await axios.get(cacheUrl, { timeout: 15000 });
  return res.data;
}

fetchGoogleCache('http://example.com').then(html => console.log('cache len', html.length)).catch(e => console.error(e));

مزایا و معایب:

  • مزیت: ساده، سریع و معمولاً از محدودیت‌های هدف در امان است.
  • عیب: ممکن است محتوای قدیمی باشد یا برای سایت‌هایی که اجازهٔ کش شدن نمی‌دهند کار نکند.

روش 7 — Reverse Engineering سیستم‌های Anti-Bot (چکیده)

ایدهٔ کلی: بررسی دقیق ترافیک، کدهای جاوااسکریپت و مکانیزم‌های سمت سرور برای ساخت یک راه‌حل اختصاصیِ سبک و کم‌هزینه. این روش پیچیده، زمان‌بر و نیازمند مهارت است.

مراحل عملیاتی:

  1. جمع‌آوری ترافیک شبکه (DevTools یا ابزارهای پروکسی)
  2. تحلیل اسکریپت‌های جاوااسکریپت و شناسایی محاسبات/توکن‌های مورد نیاز
  3. شبیه‌سازی امضاها و رفتارهای لازم (مثلاً fingerprintها یا event sequence)

موارد احتیاطی و اخلاقی: این مسیر می‌تواند مفاد شرایط استفادهٔ سایت را نقض کند و ریسک‌های قانونی داشته باشد؛ قبل از اقدام، جنبه‌های قانونی را بررسی کنید.

مطالعهٔ موردی: Petsathome.com

خلاصهٔ اجرای تکنیک‌ها روی Petsathome.com:

  • با axios + cheerio صفحهٔ اصلی بارگذاری شد — یعنی بعضی صفحات برای اسکریپ ساده باز هستند.
  • بهینه‌سازی هدرها — بهبود ملحوظی در پایداری اتصال ایجاد کرد (موفق).
  • استفاده از پروکسی چرخان — تعداد بلوکه‌ها کاهش یافت و نرخ موفقیت افزایش یافت (موفق).
  • Headless browser با شبیه‌سازی تعاملات — برای صفحات دینامیک و امن‌تر لازم بود (موفق، اما هزینه‌بر).
  • Google cache — در این مورد خاص کش قابل‌استفاده نبود (ناموفق).

نکات عیب‌یابی:

  • برای IP Blocking: پروکسی‌ها را بیشتر بچرخانید و الگوی اپراتور را تعدیل کنید (throttling و random delays).
  • برای CAPTCHA: حل‌کننده‌ها و retry با تأخیر افزایشی را ترکیب کنید.
  • برای محتوای داینامیک: بررسی کنید آیا داده از APIهای پنهانی می‌آید که می‌توانید مستقیم‌تر به آن‌ها مراجعه کنید.

نکات عملی، بهترین روش‌ها و هشدارها

  • قانونی و اخلاقی: همیشه پیش از اسکریپ کردن، شرایط سرویس را بررسی کرده و از داده‌های حساس محافظت کنید.
  • نرخ‌گذاری و Throttling: برای جلوگیری از بلاک شدن از الگوی طبیعی استفاده کنید — نرخ ثابت و بالا باعث تشخیص سریع می‌شود.
  • لاگینگ و مانیتورینگ: خطاها، نرخ پاسخ‌ و نسبت موفقیت را ثبت کنید تا به‌موقع استراتژی را تغییر دهید.
  • مدیریت سشن و کوکی: برای سایت‌هایی که وابسته به سشن‌اند، کوکی‌ها را ذخیره و بازپخش کنید.
  • مقیاس‌پذیری: headless browserها را در کانتینر اجرا و از pool کردن instances استفاده کنید تا منابع کنترل شود.

جمع‌بندی

برای موفقیت در وب اسکریپینگ مقابل سیستم‌های ضدبات باید از رویکردی چندلایه استفاده کنید: بهینه‌سازی هدرها و fingerprint، پروکسی‌های چرخان، استفاده از headless browser برای صفحات دینامیک، و در صورت نیاز سرویس‌های مدیریت‌شده یا حل‌کننده‌های CAPTCHA. هر روش مزایا و هزینهٔ خودش را دارد؛ بنابراین ترکیب هوشمندانهٔ آن‌ها همراه با مانیتورینگ و رعایت چارچوب‌های قانونی بهترین نتیجه را می‌دهد.

اگر نیاز دارید، می‌توانم برای هدف مشخص شما یک نمونهٔ پیاده‌سازی کامل (با مدیریت پروکسی، استراتژی retry و مانیتورینگ) بنویسم یا کدهای بالا را به‌صورت پروژهٔ آماده برای اجرا تنظیم کنم.

مقاله‌های مرتبط