مقدمه
این مقاله یک راهنمای عملی و جزئینگر برای استفاده از کتابخانه Crawlee در پروژههای وب اسکریپینگ با Node.js است. اگر شما توسعهدهندهای با پسزمینهٔ Python هستید و میخواهید بهسرعت با مفاهیم مشابه مانند requests، پارسینگ با BeautifulSoup و اتوماسیون مرورگر آشنا شوید، این راهنما برای شما نوشته شده است. در پایان این مطلب شما توانایی راهاندازی یک پروژه Crawlee، استخراج داده، مدیریت صفها، استفاده از پراکسی و استقرار در کانتینر را خواهید داشت.
شروع سریع (TL;DR)
ایدهٔ کلی: یک نمونهٔ سادهٔ CheerioCrawler بسازید که عنوان صفحه را بگیرد و لینکهای درون دامنه را enqueue کند.
import { CheerioCrawler } from 'crawlee';
const crawler = new CheerioCrawler({
async requestHandler({ $, request, enqueueLinks }) {
console.log(`Title of ${request.url}: ${$('title').text()}`);
await enqueueLinks({ strategy: 'same-domain' });
},
});
await crawler.run(['https://books.toscrape.com']);
توضیح سریع: ورودی این اسکریپت یک آرایهٔ URL اولیه است؛ خروجی در اینجا چاپ عنوانها روی کنسول و افزودن لینکهای همدامنه به صف برای پردازش بعدی است.
راهاندازی محیط
مراحل پایهای برای راهاندازی پروژهٔ NodeJS که از Crawlee استفاده میکند:
- نصب Node.js — هر نسخهٔ LTS مناسب است.
- شروع پروژه — با npm init -y یک package.json بسازید.
- نصب Crawlee —
npm install crawlee.
اگر از سیستمهایی که قبلاً با Python کار کردهاید میآیید: Crawlee نقش مشابه requests + BeautifulSoup یا Scrapy را در اکوسیستم Node دارد، اما API آن برای صفبندی و تعامل با مرورگرها بهینه است.
ساخت اولین کرالر
ایدهٔ کلی: یک CheerioCrawler آماده کنید تا HTML را دانلود کند و از طریق Cheerio (jQuery-مانند) پارس کند.
import { CheerioCrawler } from 'crawlee';
const crawler = new CheerioCrawler({
async requestHandler({ $, request }) {
// ورودی: request (اطلاعات URL)؛ $: شی Cheerio برای پارس
// خروجی: چاپ عنوان صفحه
const title = $('title').text();
console.log(`Scraping ${request.url}: ${title}`);
},
});
await crawler.run(['https://books.toscrape.com']);
خطبهخط:
- ایمپورت CheerioCrawler.
- ساخت نمونه با یک requestHandler که برای هر صفحه اجرا میشود.
- درون requestHandler، از $ برای انتخاب المانها (مانند $('title')) استفاده میکنیم.
- اجرای کرالر با یک URL اولیه.
نکته: برای صفحات تکصفحهای یا heavy-JS به سراغ بخش مرورگر واقعی بروید (پایینی).
افزودن خودکار URLها و مدیریت صف
برای گسترش دامنهٔ پوشش کرالر باید لینکهای موجود در صفحات را enqueue کنید تا بهصورت خودکار پردازش شوند.
const crawler = new CheerioCrawler({
async requestHandler({ $, request, enqueueLinks }) {
console.log(`Title of ${request.url}: ${$('title').text()}`);
// strategy: 'same-domain' باعث میشود کرالر فقط لینکهای همان دامنه را اضافه کند
await enqueueLinks({ strategy: 'same-domain' });
},
});
await crawler.run(['https://books.toscrape.com']);
نکات عملی:
- استفاده از استراتژیهای مختلف برای کنترل محدودهٔ crawling (مثلاً same-domain یا selector-based).
- صفها به شما اجازه میدهند crawl را متوقف، بازگشت و یا توزیع کنید.
- در پروژههای بزرگ از storage-based queues (مثلاً Redis یا queueهای داخلی Crawlee) برای پایداری استفاده کنید.
پروژهٔ واقعی: جمعآوری و ذخیرهٔ دادهها
یک مثال عملی که دادهها را جمعآوری و همزمان در JSON و CSV ذخیره میکند:
import { CheerioCrawler } from 'crawlee';
import fs from 'fs';
const results = [];
const crawler = new CheerioCrawler({
async requestHandler({ $, request, enqueueLinks }) {
const data = {
url: request.url,
title: $('title').text(),
description: $('meta[name="description"]').attr('content') || '',
};
results.push(data);
await enqueueLinks({ strategy: 'same-domain' });
},
});
await crawler.run(['https://books.toscrape.com']);
fs.writeFileSync('data.json', JSON.stringify(results, null, 2));
fs.writeFileSync('data.csv', results.map(r => Object.values(r).join(',')).join('\n'));
شرح: ورودیها: URLهای اولیه و تنظیمات crawler؛ خروجیها: آرایهٔ results که بعد از پایان crawl در فایلهای JSON و CSV نوشته میشود. توجه کنید در CSV باید مراقب کاماها و کاراکترهای خاص باشید (در عمل بهتر است از کتابخانهای مثل csv-writer استفاده کنید).
تکنیکهای Crawling
چند رویکرد متداول با مزایا و معایب هر کدام:
- HTTP Crawling: سریع، سبک، مناسب برای صفحات ایستا که رندر سمت سرور دارند. معایب: در صفحات JS-heavy کارایی ندارد.
- Real Browser Crawling: با Playwright یا Puppeteer برای صفحات که نیاز به اجرای JS دارند. مزیت: شبیهسازی دقیق رفتار کاربر؛ معایب: سنگینتر و نیاز به منابع بیشتر.
مثال: HTTP (Cheerio) با هدر سفارشی
const crawler = new CheerioCrawler({
preNavigationHooks: [
async ({ request }) => {
request.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
};
},
],
async requestHandler({ $, request }) {
console.log(`Title of ${request.url}: ${$('title').text()}`);
},
});
دلیل: تنظیم هدر User-Agent برای تقلید از مرورگر واقعی و کاهش احتمال بلاک شدن.
مثال: مرورگر واقعی با Playwright
import { PlaywrightCrawler } from 'crawlee';
const crawler = new PlaywrightCrawler({
async requestHandler({ page, request }) {
const title = await page.title();
console.log(`Title of ${request.url}: ${title}`);
},
});
await crawler.run(['https://books.toscrape.com']);
این روش لازم است وقتی محتوای صفحه با JavaScript تولید میشود یا برای تعاملاتی مانند کلیک و پیمایش لازم است.
پیکربندیهای پیشرفته و مدیریت خطا
پایداری از مهمترین مسائلی است که باید پوشش دهید؛ Retries و handler برای درخواستهای شکستخورده را فعال کنید:
const crawler = new CheerioCrawler({
maxRequestRetries: 3,
async handleFailedRequestFunction({ request }) {
console.log(`Request failed for ${request.url}`);
// اینجا میتوانید لینک را در یک لیست خطا ذخیره کنید یا هشدار ایمیلی ارسال کنید
},
async requestHandler({ $, request }) {
console.log(`Title of ${request.url}: ${$('title').text()}`);
},
});
نکات عملی: تنظیم تعداد retries برای مقابله با خطاهای موقتی شبکه؛ لاگ کردن URLهای مشکلدار برای بررسیهای بعدی.
اجتناب از بلاک شدن و مدیریت پراکسی
برای کاهش احتمال بلاک شدن از ترکیب چند تکنیک استفاده کنید: پراکسی چرخان، session management، تاخیر تصادفی و تغییر User-Agent.
import { ProxyConfiguration, CheerioCrawler } from 'crawlee';
const proxyConfiguration = new ProxyConfiguration({
proxyUrls: [
'http://username:password@proxy1:8000',
'http://username:password@proxy2:8000',
],
});
const crawler = new CheerioCrawler({
proxyConfiguration,
async requestHandler({ $, request }) {
console.log(`Title of ${request.url}: ${$('title').text()}`);
},
});
هشدارهای مهم:
- همیشه شرایط استفاده و قوانین سایت (robots.txt و Terms of Service) را بررسی کنید.
- پراکسیها را از منابع قابل اعتماد تهیه کنید و میزان درخواست را طوری تنظیم کنید که به سرور هدف آسیب نرساند.
بهینهسازی و مقیاسپذیری
برای پروژههای بزرگ باید همزمانی (concurrency)، محدودیت نرخ (rate limiting) و منابع را متعادل کنید:
const crawler = new CheerioCrawler({
maxConcurrency: 10, // تعداد همزمان درخواستها
async requestHandler({ $, request }) {
console.log(`Title of ${request.url}: ${$('title').text()}`);
},
});
نکات عملکردی:
- افزایش concurrency سرعت را بالا میبرد اما مصرف منابع و ریسک بلاک شدن را نیز افزایش میدهد.
- برای بارهای کاری بزرگ از توزیع در چند ماشین یا Kubernetes و از صفهای پایدار (مثل Redis) استفاده کنید.
استقرار با Docker
برای اجرای پایدار و قابلانتقال، اپ خود را در کانتینر بستهبندی کنید. نمونهٔ سادهٔ Dockerfile:
FROM node:14
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
CMD ["node", "index.js"]
مراحل بیلد و اجرا:
- ساخت تصویر: docker build -t my-crawler .
- اجرای کانتینر: docker run my-crawler
نکتهٔ عملی: برای محیطهای production از orchestration (مانند Kubernetes) و مانیتورینگ منابع استفاده کنید. همچنین از متغیرهای محیطی برای نگهداری کلیدهای پراکسی و تنظیمات حساس استفاده کنید.
نکات امنیتی و اخلاقی
- رعایت قوانین مالکیت و شرایط استفادهٔ سایتها.
- عدم استخراج دادههای حساس یا خصوصی بدون مجوز.
- عدم ایجاد بار اضافی روی سرور هدف با تنظیم نرخ و concurrency.
جمعبندی
با Crawlee میتوانید از کار با صفحات ایستا تا تعاملات پیچیدهٔ مرورگر را پوشش دهید. مسیر پیشنهادی برای یک پروژهٔ واقعی: راهاندازی اولیه → تست با Cheerio → در صورت نیاز مهاجرت به Playwright/Puppeteer → اضافه کردن پراکسی و مدیریت خطا → بهینهسازی concurrency → بستهبندی در Docker و استقرار. اگر شما از Python میآیید، مفاهیم صف، retries و پارسینگ برایتان آشنا خواهند بود؛ فقط API و ابزارها متفاوتاند. این راهنما نکات عملی و مثالهای کد را برای شروع و گسترش پروژههای وب اسکریپینگ با Crawlee ارائه کرد.





