

این مقاله یک راهنمای فنی و عملی برای توسعهدهندههای سطح متوسط پایتون/Node.js است که میخواهند وب اسکریپینگ را مقابل سیستمهای ضدبات (anti-bot) قابل اتکا کنند. در پایان این مطلب شما با انواع مکانیسمهای تشخیص بات، مجموعهای از روشهای کاربردی (از بهینهسازی هدرها تا مرورگرهای headless مستحکم و سرویسهای مدیریتشده) آشنا میشوید و مثالهای کد NodeJS برای هر روش را خواهید دید.
هدف این راهنما ارائهٔ توضیحات خطبهخط برای کدها، ذکر ورودیها و خروجیها، و نکات عملی در مورد امنیت، عملکرد و نگهداری است — نه فقط فهرستوار مرور روشها.
اگر دنبال راهحل سریع هستید: ترکیب Playwright یا Puppeteer (برای رندر جاوااسکریپت) با یک پول پروکسیِ چرخان، به همراه بهینهسازی هدرها و مدیریت کوکی/سشن، برای بسیاری از سایتها کافی است. در موارد سختتر از سرویسهای مدیریتشده یا حلکنندهٔ CAPTCHA استفاده کنید.
قبل از هر چیز باید بدانید چه چیزی را باید دور زد. روشهای معمول تشخیص بات شامل موارد زیر هستند:
معمولاً ترکیبی از این مکانیسمها به کار میرود؛ بنابراین راهحل هم باید ترکیبی و لایهای باشد.
ایدهٔ کلی: درخواستهای شما باید از نظر هدرها و 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));توضیحات بخشبهبخش:
ایدهٔ کلی: با تغییر IP برای هر درخواست یا هر جلسه، ریسک بلوکهشدن بر اساس IP را کاهش میدهیم.
نکات مهم:
مثال با 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();
}
})();نکات عملی:
ایدهٔ کلی: وقتی سایت از جاوااسکریپت برای تست اصالت کاربر استفاده میکند، باید یک محیط مرورگر واقعی شبیهسازی کنیم.
چند گزینه رایج: 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));نکات عملکردی و هزینهای:
ایدهٔ کلی: وقتی زمان یا توان فنی محدود است، از سرویسهایی استفاده کنید که لایههای عبور را بهصورت سرویس ارائه میدهند؛ این سرویسها معمولاً ترکیبی از رندر سروری، پروکسیهای residential و حلکنندهٔ چالش هستند.
چه چیزهای مهم است:
نکات امنیتی و حفظ حریم خصوصی: اطلاعات حساس (مثل کوکیهای لاگین) را در سرویسهای ثالث ذخیره نکنید مگر سیاستهای آنها را بررسی کرده باشید.
ایدهٔ کلی: 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));نکات عملی:
ایدهٔ کلی: در مواردی که نیاز به دادهٔ بلافاصله بهروز ندارید، میتوان از نسخههای 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));مزایا و معایب:
ایدهٔ کلی: بررسی دقیق ترافیک، کدهای جاوااسکریپت و مکانیزمهای سمت سرور برای ساخت یک راهحل اختصاصیِ سبک و کمهزینه. این روش پیچیده، زمانبر و نیازمند مهارت است.
مراحل عملیاتی:
موارد احتیاطی و اخلاقی: این مسیر میتواند مفاد شرایط استفادهٔ سایت را نقض کند و ریسکهای قانونی داشته باشد؛ قبل از اقدام، جنبههای قانونی را بررسی کنید.
خلاصهٔ اجرای تکنیکها روی Petsathome.com:
نکات عیبیابی:
برای موفقیت در وب اسکریپینگ مقابل سیستمهای ضدبات باید از رویکردی چندلایه استفاده کنید: بهینهسازی هدرها و fingerprint، پروکسیهای چرخان، استفاده از headless browser برای صفحات دینامیک، و در صورت نیاز سرویسهای مدیریتشده یا حلکنندههای CAPTCHA. هر روش مزایا و هزینهٔ خودش را دارد؛ بنابراین ترکیب هوشمندانهٔ آنها همراه با مانیتورینگ و رعایت چارچوبهای قانونی بهترین نتیجه را میدهد.
اگر نیاز دارید، میتوانم برای هدف مشخص شما یک نمونهٔ پیادهسازی کامل (با مدیریت پروکسی، استراتژی retry و مانیتورینگ) بنویسم یا کدهای بالا را بهصورت پروژهٔ آماده برای اجرا تنظیم کنم.