مقدمه
در این راهنمای عملی یاد میگیرید چگونه با Cheerio در محیط Node.js صفحات HTML را بارگذاری، پرسوجو و دادهها را استخراج کنید؛ از نصب و خواندن فایلهای محلی یا درخواست HTTP گرفته تا نمونهی کامل یک اسکریپر که خروجی JSON تولید میکند. مخاطب فرضی این مقاله توسعهدهندهی پایتون/Node در سطح متوسط است که دنبال جزئیات پیادهسازی، مدیریت خطا و نکات عملی برای تولید اسکریپر پایدار است.
چرا از Cheerio برای وب اسکریپینگ استفاده کنیم
- سینتکس آشنا و شبیه jQuery که انتخاب با CSS selector را ساده میکند.
- کار بر روی سرور: اجرا در محیط Node.js بدون نیاز به مرورگرِ واقعی (سرعت و سبکی).
- مناسب برای صفحات ایستا (static HTML) و پردازش سریع چند صد یا چند هزار صفحه کوچک.
- قابل گسترش: میتوانید منطق سفارشی جاوااسکریپت را روی درخت پارسشده پیاده کنید.
نکته: Cheerio جاوااسکریپتِ سمت کلاینت را اجرا نمیکند؛ برای صفحات داینامیک باید از راهکارهای جایگزین استفاده کنید.
نصب و راهاندازی
مراحل پایهای برای شروع:
mkdir web-scraping
cd web-scraping
npm init -y
npm install cheerio axios
توضیح: با npm init -y یک package.json پایه ساخته میشود. اگر میخواهید از import/export استفاده کنید، مقدار "type":"module" را در فایل package.json قرار دهید.
بارگذاری HTML — از وب و از فایل
دو منبع اصلی HTML عبارتند از درخواست HTTP و فایل محلی. در هر دو حالت خروجی یک رشته HTML است که به cheerio.load پاس میدهیم تا تابع انتخابگر $ را بدست آوریم.
مثال: گرفتن HTML از وب با axios (با مدیریت خطا و هدر)
import * as cheerio from 'cheerio'
import axios from 'axios'
async function fetchHtml(url) {
try {
const response = await axios.get(url, {
headers: { 'User-Agent': 'Mozilla/5.0 (compatible; MyScraper/1.0)'} ,
timeout: 10000
})
const html = response.data // خروجی: رشتهٔ HTML
return cheerio.load(html) // بازگشت: تابع انتخابگر $
} catch (err) {
console.error('fetchHtml error:', err.message)
throw err
}
}
توضیح خطبهخط: ورودی تابع fetchHtml یک url است؛ خروجی تابع یک تابع انتخابگر $ است که روی آن میتوان عملیات جستجو/تغییر انجام داد. ما هدر User-Agent و timeout تعیین کردیم تا رفتار قابلپیشبینیتری داشته باشیم.
خواندن از فایل محلی با fs/promises:
import * as cheerio from 'cheerio'
import fs from 'fs/promises'
async function loadFromFile(path) {
const html = await fs.readFile(path, 'utf8') // ورودی: مسیر فایل، خروجی: رشتهٔ HTML
return cheerio.load(html)
}
پرسوجو و انتخاب عناصر (Querying DOM)
پس از بارگذاری HTML، از تابع $ مانند jQuery استفاده میکنیم. روشهای رایج: text(), attr(), each().
const $ = cheerio.load('Example ')
const title = $('title').text() // خروجی: متن داخل تگ title
// پیمایش لینکها
$('a').each((i, el) => {
const href = $(el).attr('href') // آدرس
const text = $(el).text() // متن لینک
console.log(i, text, href)
})
نکته: each آرگومانهای index و element را میگیرد؛ برای دسترسی دوباره به متدهای Cheerio باید عنصر را با $(element) بستهبندی کنید.
پیمایش درخت DOM (Traversing)
برای جابجایی در ساختار از متدهایی مثل find, children, parent, parents, next, prev استفاده کنید. این متدها ترکیبپذیرند و انعطاف بالایی در استخراج ساختار پیچیده میدهند.
// پیدا کردن همهٔ های داخل یک کانتِینر
const $container = $('.container')
const paragraphs = $container.find('p')
paragraphs.each((i, p) => console.log($(p).text()))
// گرفتن والد مستقیم
const parentClass = $('.some-child').parent().attr('class')
مثالهای بالا ورودی را میگیرند (انتخابگر یا عنصر) و خروجی معمولاً یک مجموعهٔ Cheerio است که میتوانید روی آن each اجرا کرده و دادهها را جمعآوری کنید.
استخراج با Regex و فیلتر عناصر
برای استخراج الگوهای متنی مانند ایمیل یا شماره تلفن میتوانید از regex در ترکیب با text() یا html() استفاده کنید.
const emails = []
$('li').each((i, el) => {
const text = $(el).text()
const m = text.match(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/)
if (m) emails.push(m[0])
})
برای فیلتر کردن مجموعهها از filter() و برای معکوس کردن شرطها از not() استفاده کنید.
دستکاری DOM (Manipulation)
Cheerio علاوه بر خواندن میتواند DOM را بهصورت برنامهای تغییر دهد: صفتها، کلاسها، متن یا ساختار HTML را ویرایش کنید.
const $ = cheerio.load('link')
const $a = $('a')
$a.attr('href', 'https://nodejs.org') // تغییر attribute
$a.prop('target', '_self') // تغییر property
$a.text('Node.js') // تغییر متن
خروجی این تغییرات را میتوانید با prop('outerHTML') یا html() مشاهده کنید.
نمونه پروژه: اسکرپر Quotes (خروجی JSON)
مثال کامل که همهٔ مفاهیم بالا را جمع میکند: دریافت صفحه، انتخاب بلوکهای نقلقول، استخراج متن، نویسنده و تگها، و تولید آرایهٔ JSON.
import * as cheerio from 'cheerio'
import axios from 'axios'
async function scrapeQuotes(url) {
// ورودی: url (رشته)، خروجی: آرایهٔ اشیاء
const res = await axios.get(url, { timeout: 10000 })
const $ = cheerio.load(res.data)
const quotes = []
$('div.quote').each((i, block) => {
const quoteText = $(block).find('span.text').text().trim()
const author = $(block).find('small.author').text().trim()
const tags = []
$(block).find('a.tag').each((j, t) => tags.push($(t).text().trim()))
quotes.push({ No: i + 1, Quote: quoteText, Author: author, tags })
})
return quotes // خروجی: [{No, Quote, Author, tags}, ...]
}
// استفاده
scrapeQuotes('https://quotes.toscrape.com')
.then(data => console.log(JSON.stringify(data, null, 2)))
.catch(err => console.error('scrape error', err.message))
توضیح: تابع scrapeQuotes یک درخواست HTTP انجام میدهد، درخت DOM را با Cheerio میسازد و سپس بهصورت مرحلهای بلوکهای div.quote را پردازش میکند. خروجی مناسب برای ذخیره در فایل JSON یا تبدیل به CSV است.
ملاحظات فنی و بهترینروشها
- مدیریت خطا: همیشه try/catch یا promise.catch داشته باشید و برای خطاهای قابل بازگشت (retryable) مکانیزم تکرار (exponential backoff) پیاده کنید.
- هدرها و زمانبندی: هدر User-Agent، کوکیهای لازم و محدودیت نرخ (rate limit) را رعایت کنید.
- مصرف حافظه: Cheerio کل HTML را در حافظه میسازد؛ برای صفحات بسیار بزرگ یا تعداد زیاد صفحات از صفبندی (queue) با محدودیت concurrency استفاده کنید.
- همزمانی: از محدودیت همزمانی (مثلاً پکیجهایی مثل p-limit یا یک worker pool ساده) برای جلوگیری از مصرف بیش از حد منابع و بلاک شدن استفاده کنید.
- امنیت و اخلاق: قانون مالکیت داده، robots.txt و قوانین API سایتها را رعایت کنید؛ از جمعآوری دادههای حساس خودداری کنید.
- مقابله با بلاک: برای عبور از مکانیزمهای سادهٔ بلاکینگ از پراکسی، گردش IP، و تغییر User-Agent استفاده کنید، اما از روشهای غیرقانونی یا دورزدن قوانین سایت استفاده نکنید.
محدودیتها و جایگزینها
محدودیت اصلی Cheerio این است که جاوااسکریپت اجرا نمیشود؛ اگر نیاز به رندر یا تعامل (کلیک، اسکرول) دارید از ابزارهای زیر استفاده کنید:
- Puppeteer / Playwright: مرورگر واقعی برای صفحات داینامیک و تعاملات پیچیده.
- jsdom: شبیهسازی محیط DOM با امکان اجرای بعضی از اسکریپتها.
- htmlparser2 و parse5: کتابخانههای پارسینگ سبک و سریع برای نیازهای سفارشی.
جمعبندی
Cheerio ابزار قدرتمندی برای وب اسکریپینگ صفحات ایستا در Node.js است: سبک، سریع و با API آشنا. در عین حال باید محدودیتها (عدم اجرای JS، حافظه) را در طراحی اسکریپر در نظر بگیرید و بهترینروشها مانند مدیریت خطا، محدودسازی نرخ و رعایت اصول اخلاقی را اعمال کنید. با ترکیب Cheerio با ابزارهای شبکهای مانند axios و الگوهای مانند صفبندی و retry میتوانید اسکریپرهای قابلاعتماد و مقیاسپذیر بسازید.



