مقدمه
گرفتن اسکرینشات یکی از مهارتهای پایه در وب اسکریپینگ و تست خودکار است. اسکرینشاتها برای دیباگ، گزارشدهی، بررسی رگرسیون بصری و ثبت حالت صفحه در زمان مشخص کاربرد دارند. در این مقاله عملی برای توسعهدهندههای پایتون/جاوااسکریپت سطح متوسط توضیح میدهیم چگونه با Playwright اسکرینشات بگیرید، تنظیمات مهم را کنترل کنید، خطاهای رایج را رفع کنید و چند الگوی عملی برای پروژههای وب اسکریپینگ ارائه میکنیم.
اصول و گزینههای مهم page.screenshot()
متد page.screenshot() چند گزینه کلیدی دارد که رفتار تصویر خروجی را تعیین میکنند. اینجا مشخصات اصلی را با توضیح فنی میبینید:
- path: مسیر فایل برای ذخیره تصویر؛ اگر مشخص نشود تصویر بر روی دیسک ذخیره نمیشود و به صورت Buffer برمیگردد.
- type: فرمت خروجی—معمولاً "png" یا "jpeg".
- quality: عددی بین 0 تا 100 برای کیفیت که فقط در فرمت JPEG کاربرد دارد.
- fullPage: اگر true شود، کل صفحه (تا انتهای اسکرول) کپچر میشود.
- clip: یک شیء با {x, y, width, height} برای برش دقیق یک ناحیه از صفحه.
- omitBackground: پسزمینه پیشفرض را حذف میکند و اجازه میدهد تصاویر شفاف باشند (PNG).
نمونه پایه: گرفتن یک اسکرینشات ساده
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch(); // یا { headless: true }
const page = await browser.newPage();
await page.goto('https://quotes.toscrape.com');
// خروجی: فایل example.png در فولدر جاری
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
توضیح خطبهخط:
- ورودیها: آدرس صفحه در page.goto و مسیر در path.
- خروجی: فایل تصویر در دیسک یا در صورت عدم تعیین path یک Buffer بازگردانده میشود.
- نقش توابع: browser.newPage() یک تب جدید ایجاد میکند؛ page.screenshot() تصویر را میگیرد.
گرفتن اسکرینشات از کل صفحه (Full Page)
await page.screenshot({ path: 'full-page.png', fullPage: true });
وقتی صفحه طولانی است و میخواهید تمام محتوا را بدون اسکرول دستی ذخیره کنید، از fullPage: true استفاده کنید. توجه داشته باشید که در بعضی صفحات با محتوای داینامیک ممکن است قبل از گرفتن تصویر لازم باشد منتظر بارگذاری کامل منابع بمانید.
گرفتن اسکرینشات از یک Viewport یا ناحیه مشخص
برای ضبط تصویر با رزولوشن دلخواه یا گرفتن ناحیه خاص از صفحه:
// مشخص کردن اندازه پنجره (رزولوشن تصویر خروجی)
await page.setViewportSize({ width: 1920, height: 1080 });
// یا برش یک ناحیه مشخص
await page.screenshot({
path: 'clip.png',
clip: { x: 0, y: 0, width: 1200, height: 400 }
});
نکات مهم:
- تعیین viewport عملاً تعداد پیکسلهای خروجی را کنترل میکند (رزولوشن).
- clip مختص ناحیه داخل viewport است؛ مقادیر اشتباه میتواند منجر به خطا یا تصویر خالی شود.
گرفتن اسکرینشات از یک DOM Element
const element = page.locator('div.quote:nth-child(1)');
await element.screenshot({ path: 'element.png' });
در این حالت page.locator() یک سلکتور را نشان میدهد و متد screenshot() روی همان المنت اجرا میشود.
- ورودی: یک CSS selector معتبر.
- خروجی: تصویر حاوی همان المنت فقط.
- هشدار: هنگام گرفتن اسکرینشات از المنت، از گزینههای fullPage و clip استفاده نکنید—اینها با هم ناسازگارند و خطا تولید میکنند.
چندین اسکرینشات بهصورت سری یا پیمایشی
const urls = [
'https://www.google.com',
'https://www.bing.com',
'https://quotes.toscrape.com'
];
let id = 1;
for (const url of urls) {
await page.goto(url, { waitUntil: 'networkidle' });
await page.screenshot({ path: `screenshots/IMG_${id++}.png` });
}
نکات عملی:
- برای کار موازی و ایزولاسیون بهتر از browser.newContext() یا چندین صفحه (browser.newPage()) استفاده کنید.
- قبل از حلقه مطمئن شوید دایرکتوری خروجی وجود دارد (مثلاً با fs.mkdirSync یا ابزارهای node).
تنظیم کیفیت و فرمت تصویر
// کیفیت فقط برای jpeg معتبر است
await page.screenshot({ path: 'screenshot.jpg', type: 'jpeg', quality: 50 });
نکته: فرمت PNG فشردهسازی بدون افت را ارائه میدهد و گزینه quality روی PNG تاثیری ندارد.
کنترل رزولوشن (Resolution)
رزولوشن خروجی با اندازه viewport تعیین میشود. برای گرفتن تصاویر با رزولوشن بالاتر اندازه viewport را بزرگتر کنید یا از مقیاسهای CSS/zoom استفاده کنید:
await page.setViewportSize({ width: 2560, height: 1440 });
await page.screenshot({ path: 'highres.png' });
هشدار: افزایش رزولوشن حافظه و زمان پردازش را افزایش میدهد؛ برای اسکریپهای بزرگ، مصرف منابع را مانیتور کنید.
گرفتن خروجی در حافظه (Buffer) برای پردازش بعدی
const buffer = await page.screenshot();
// ارسال به سرویس مقایسه پیکسل، آپلود یا تبدیل به base64
console.log(buffer.toString('base64'));
این الگو مناسب زمانی است که نمیخواهید فایل روی دیسک ذخیره شود و قصد دارید تصویر را مستقیماً به سرویس دیگری ارسال یا در حافظه پردازش کنید.
تبدیل صفحات به PDF
await page.goto('https://quotes.toscrape.com', { waitUntil: 'networkidle' });
await page.pdf({ path: 'file.pdf', format: 'A4' });
وقتی متن انتخابشدنی، چند صفحه یا فرمت چاپ اهمیت دارد، PDF گزینه مناسبتری است. page.pdf() تنظیماتی برای حاشیهها، قالب صفحه و غیره دارد.
رفع خطاهای رایج و بهترین روشها
- Invalid Selector: اگر سلکتور المنتی را پیدا نمیکند، با ابزار Inspect مرورگر، ساختار DOM را چک کنید و از شناسهها/کلاسهای پایدار استفاده کنید.
- Timeout: اگر صفحه دیر لود میشود، از گزینههای زمانبندی استفاده کنید:
await page.goto(url, { timeout: 15000, waitUntil: 'networkidle' }); - مسیر فایل و مجوزها: حتماً مسیرها را بررسی و از مسیرهای مطلق در محیطهای سرور استفاده کنید. اطمینان از دسترسی نوشتن به پوشه ضروری است.
- محتوای داینامیک یا تصاویر ناپدید/بارگذاری نشده: از
await page.waitForSelector('img', { visible: true })یا منتظر شدن برای یک ایونت خاص استفاده کنید تا محتوای لازم رندر شود. - کند بودن زمان اسکرینشات: کاهش کیفیت JPEG یا کوچکتر کردن viewport میتواند زمان را کاهش دهد. همچنین از Retry منطقی و محدودیت همزمانی استفاده کنید.
- پایداری و مقیاسپذیری: برای اسکریپهای بزرگ از pool کردن مرورگر/کانتکست و محدود کردن تعداد parallel pages استفاده کنید تا فشار روی CPU/RAM کنترل شود.
نمونه الگوی خطاگیری و Retry
async function safeScreenshot(page, options = {}, attempts = 3) {
for (let i = 0; i < attempts; i++) {
try {
return await page.screenshot(options);
} catch (err) {
if (i === attempts - 1) throw err;
await new Promise(r => setTimeout(r, 1000 * (i + 1))); // backoff ساده
}
}
}
این الگو به ویژه هنگام مواجهه با خطاهای موقتی شبکه یا منابع کمک میکند.
جمعبندی
Playwright ابزار قدرتمندی برای گرفتن اسکرینشات در وب اسکریپینگ و تست است. با کنترل گزینههایی مثل fullPage، clip، quality و viewport میتوانید خروجیهای متناسب با نیازتان تهیه کنید. همیشه از wait مناسب برای محتوای داینامیک استفاده کنید، خطاها را با الگوهایی مانند retry مدیریت کنید و در صورت نیاز خروجی را به صورت Buffer دریافت کنید تا برای مقایسه بصری یا آپلود آماده باشد.
اگر دنبال بهبود پایداری و مقیاسپذیری هستید، کانتکستها را مدیریت کنید، از محدودیت همزمانی استفاده کنید و مسیرهای ذخیرهسازی را مستحکم کنید.
پیوست: نکات کوتاه برای تولیدکنندگان اسکریپ
- از CSS سلکتورهای پایدار (ID یا attribute-based) استفاده کنید تا خطای Invalid Selector کمتر شود.
- برای صفحات داینامیک همیشه از waitUntil: 'networkidle' یا waitForSelector استفاده کنید.
- کیفیت و رزولوشن را بر اساس نیاز عملیاتی (زمان/فضا) تنظیم کنید.
- هنگام ذخیره فایل از مسیرهای مطلق و مدیریت خطا برای مجوزها استفاده کنید.





