

در وب اسکریپینگ با مرورگرهای خودکار مثل Playwright، بارگذاری کامل همهٔ منابع (تصاویر، CSS، اسکریپتها، XHR و…) میتواند سرعت و هزینهٔ عملیات را بسیار بالا ببرد. در این مقاله قدمبهقدم یاد میگیریم چطور با هدف بهبود عملکرد و پایداری، منابع غیرضروری را در Playwright مسدود کنیم و تنها دادهٔ مورد نیاز را بارگیری کنیم.
بعد از خواندن این مطلب شما میتوانید: تنظیمات پایهٔ page.route را بنویسید، انواع منابع را شناسایی و مسدود کنید، موارد لِیزیلود و محتوای داینامیک را مدیریت کنید، و نکات عملکرد/امنیت هنگام بلاک کردن منابع را رعایت کنید.
سه متد اصلی که در این راهنما مرتب از آنها استفاده میکنیم عبارتاند از: page.route برای رهگیری مسیرها، request.resourceType() برای تشخیص نوع منبع، و route.abort/route.continue برای متوقف یا اجازه دادن به درخواستها. رفتار کلی این است که ابتدا برای یک الگوی مسیر (مثلاً "**/*") یک هندلر تعریف میکنیم و سپس بر اساس resourceType() تصمیم میگیریم که درخواست را رد کنیم یا بگذرانیم.
مثال زیر نسخهٔ سریع و عملیاتی است که تصاویر، استایلها، مدیا، اسکریپتها و درخواستهای XHR/Fetch را مسدود میکند. این کد ورودی: یک آرایهٔ آدرس یا یک URL است؛ خروجی: اسکرینشات صفحهٔ بارگذاریشده بدون منابع مسدودشده و بسته شدن مرورگر.
const playwright = require('playwright');
async function scrapeData(url) {
const browser = await playwright.chromium.launch({ headless: true });
const page = await browser.newPage();
// رهگیری همهٔ درخواستها
await page.route('**/*', (route, request) => {
const type = request.resourceType();
if (type === 'image' || type === 'stylesheet' || type === 'media' || type === 'script' || type === 'xhr' || type === 'fetch') {
// مسدود کردن منابع غیرضروری
route.abort();
} else {
route.continue();
}
});
await page.goto(url, { waitUntil: 'domcontentloaded' });
await page.screenshot({ path: 'noResources.png', fullPage: true });
await browser.close();
}
scrapeData('https://example.com');توضیح خطها (خلاصه):
در ادامه نمونههای کوچکتری میبینید و برای هرکدام ورودیها/خروجیها و نکات مهم توضیح داده شدهاند.
بلاک تصاویر
// تنها تصاویر را بلاک میکند
await page.route('**/*', (route, request) => {
if (request.resourceType() === 'image') route.abort();
else route.continue();
});ورودی: درخواستهای شبکه؛ خروجی: جلوگیری از دانلود بایتهای مربوط به تصاویر. کاربرد: زمانی که تصویر برای استخراج دیتا لازم نیست.
بلاک CSS (استایلها)
await page.route('**/*', (route, request) => {
if (request.resourceType() === 'stylesheet') route.abort();
else route.continue();
});نکته: حذف CSS ممکن است باعث تغییر ساختار DOMِ رندرشده شود؛ اگر ساختار صفحه برای انتخابگرها اهمیت دارد مراقب باشید.
بلاک مدیا (صوت/ویدیو)
await page.route('**/*', (route, request) => {
if (request.resourceType() === 'media') route.abort();
else route.continue();
});بلاک اسکریپتها
await page.route('**/*', (route, request) => {
if (request.resourceType() === 'script') route.abort();
else route.continue();
});هشدار مهم: اگر محتوای هدف از طریق JavaScript بارگذاری میشود، بلاک کردن script باعث از کار افتادن آن خواهد شد و دادهٔ مورد نظر را از دست میدهید.
بلاک XHR و Fetch
await page.route('**/*', (route, request) => {
const t = request.resourceType();
if (t === 'xhr' || t === 'fetch') route.abort();
else route.continue();
});این باعث جلوگیری از فراخوانی APIهای فرانتاند میشود؛ اگر دادهها مستقیماً از XHR/fetch میآیند، نباید آنها را بلاک کنید.
برخی تصاویر و محتواها عملاً با JavaScript لِیزیلود میشوند یا آدرسهای آنها بعد از اجرای اسکریپت ساخته میشود. اگر فقط تصاویر را بلاک کنید اما اسکریپت اجازهٔ لِیزیلود را صادر کند، ممکن است باز هم درخواستهایی ایجاد شوند. برای چنین مواردی معمولاً دو راه وجود دارد:
مثال شرطی: تنها تصاویر با URLِ حاوی کلمهٔ "premium" را بلاک کن
await page.route('**/*', (route, request) => {
if (request.resourceType() === 'image' && request.url().includes('premium')) {
route.abort();
} else {
route.continue();
}
});رعایت کنید که request.url() در زمان درخواست در دسترس است و میتوان روی آن فیلتر نوشت.
برای اطمینان از اینکه فیلترها درست کار میکنند از دو روش استفاده کنید:
page.on('request', req => console.log('REQ:', req.method(), req.url(), req.resourceType()));
page.on('response', res => console.log('RES:', res.status(), res.url()));
page.on('requestfailed', failure => console.log('FAILED:', failure.url(), failure.failure()));همچنین آزمون اتوماتیک میتواند شامل مقایسهٔ زمان اجرا (با console.time/ console.timeEnd) یا مقایسهٔ سایز نتایج خروجی باشد.
یک سناریوی رایج: پیمایش فهرستی از URLها. با مسدود کردن تصاویر و اسکریپتها میتوان زمان هر صفحه را بهطور قابلتوجهی کاهش داد. در مثال منبع، کاهشِ نزدیک به 20% گزارش شده است که در پردازشهای گسترده بسیار ارزشمند است.
const urls = ['https://quotes.toscrape.com', 'https://example.com', 'https://another.example'];
console.time('scrape');
for (let u of urls) {
await page.goto(u, { waitUntil: 'domcontentloaded' });
}
console.timeEnd('scrape');توجه: برای اسکریپهای همزمان (concurrent) بهتر است از چند context یا pool از مرورگرها استفاده کنید و محدودیتهای حافظه/CPU را مدنظر داشته باشید.
مسدود کردن منابع در Playwright با استفاده از page.route و request.resourceType() ابزار قدرتمندی برای بهبود سرعت و کاهش مصرف منابع در وب اسکریپینگ است. اما باید هوشمندانه و با آگاهی از وابستگیهای صفحه عمل کنید: گاهی بلاک کردن اسکریپتها یا XHR موجب از دست رفتن دادهٔ هدف میشود. با تست، لاگگیری و شرطگذاری دقیق میتوانید بهترین توازن بین سرعت و درستی را پیدا کنید.
شروع کنید با یک بلاککن ساده (مثلاً تصاویر) و بهتدریج شروط پیچیدهتر (URL، هدرها، یا whitelist/blacklist) اضافه کنید تا اسکریپ شما سریعتر و پایدارتر اجرا شود.


