مقدمه
Playwright یک کتابخانهٔ اتوماسیون ساختهشده توسط Microsoft است که API سطحبالا و مناسب برای تعامل با صفحات وب دینامیک در Node.js فراهم میکند. برای توسعهدهندگان پایتون سطح متوسط که با وب اسکریپینگ آشنا هستند، Playwright در نسخهٔ Node گزینهای قدرتمند برای کنترل مرورگر (Chromium, WebKit, Firefox) است؛ مخصوصاً وقتی به تعامل با جاوااسکریپتِ دینامیک، کلیک، اسکرول نامحدود و گرفتن اسکرینشات نیاز دارید. در انتهای این مقاله شما یاد میگیرید چگونه Playwright را نصب کنید، اسکریپهای ساده برای استخراج داده بنویسید، مسائل مربوط به زمانبندی و همگامسازی (waiting) را مدیریت کنید، از پراکسی استفاده کنید و چند بهترینروش برای پایداری و کارایی را پیادهسازی نمایید.
نصب Playwright
قدمهای پایه برای راهاندازی یک پروژه Node.js که از Playwright استفاده میکند بسیار ساده است. موارد ضروری:
- Node.js نصب شده روی سیستم.
- یک پروژهٔ جدید با npm یا pnpm.
دستورات نمونه (در ترمینال):
mkdir playwright_guide
cd playwright_guide
npm init -y
npm install playwright@latest
# اگر فقط میخواهید chromium نصب کنید:
npm install playwright-chromiumتوجه: اگر از سینتکس ES module استفاده میکنید، در package.json مقدار "type": "module" را اضافه کنید تا import با ES6 کار کند.
نمونهٔ شروع: باز کردن صفحه و گرفتن اسکرینشات
این مثال اولیه نشان میدهد چگونه مرورگر را اجرا کرده، صفحهای را باز کنید، اسکرینشات بگیرید و مرورگر را ببندید.
// index.js
import { chromium } from "playwright";
const scrapeData = async () => {
// راهاندازی مرورگر (headless: true برای بدون رابط گرافیکی)
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
// رفتن به آدرس هدف
await page.goto('http://quotes.toscrape.com/');
// ذخیرهٔ اسکرینشات از صفحه
await page.screenshot({ path: 'screenshot.png' });
await browser.close();
};
scrapeData();توضیح خطبهخط:
- import { chromium } from "playwright": وارد کردن رانتایم مرورگر Chromium از Playwright.
- chromium.launch: مرورگر جدید را اجرا میکند؛ پارامتر headless مشخص میکند با GUI باز شود یا نه.
- browser.newPage(): یک تب/صفحهٔ جدید میسازد و شیٔ page را برمیگرداند.
- page.goto: به URL مورد نظر میرود؛ میتوانید گزینهٔ waitUntil مثل domcontentloaded یا networkidle بدهید تا کنترل دقیقتری روی لود داشته باشید.
- page.screenshot: مسیر فایل خروجی و گزینههایی مثل fullPage میپذیرد.
- در پایان browser.close() مرورگر را میبندد تا منابع آزاد شوند.
اسکریپ کردن دادهها — انتخاب المان و استخراج
برای استخراج دادهها از صفحهٔ HTML معمولاً از page.evaluate استفاده میشود که تابعی را در کانتکستِ مرورگر اجرا میکند و مقدار سریالایزشده را برمیگرداند.
import { chromium } from "playwright";
const scrapeData = async () => {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.goto('http://quotes.toscrape.com/');
const quote = await page.evaluate(() => {
const el = document.querySelector('.quote');
if (!el) return null;
const text = el.querySelector('.text')?.innerText || '';
const author = el.querySelector('.author')?.innerText || '';
const tags = Array.from(el.querySelectorAll('.tags a')).map(t => t.innerText);
return { text, author, tags };
});
console.log(quote);
await browser.close();
};
scrapeData();نکات مهم در این مثال:
- خروجی page.evaluate باید قابل سریالیزاسیون باشد (آبجکت ساده، آرایه، رشته).
- از اپراتورهای دفاعی مثل ?. یا بررسی if (!el) استفاده کنید تا خطاهای زمان اجرا کم شود.
- در Playwright میتوانید از page.locator نیز استفاده کنید که API بهتری برای کار با چند المان و انتظار تا قابل مشاهده شدن عنصر فراهم میکند.
انتظار برای لود صفحه (Waiting)
سینک شدن با صفحه یکی از مهمترین چالشها در وب اسکریپینگ است. دو روش رایج:
- صبر کردن برای مدت ثابت با page.waitForTimeout (ساده اما شکننده).
- صبر کردن تا المان مشخصی ظاهر شود با page.waitForSelector یا استفاده از گزینهٔ waitUntil در page.goto، که قابل اعتمادتر است.
// Wait fixed time
await page.goto('http://quotes.toscrape.com/');
await page.waitForTimeout(5000);
// Wait for selector
await page.goto('http://quotes.toscrape.com/');
await page.waitForSelector('.quote', { state: 'visible' });بهترینروش: اول سعی کنید روی وقوع یک رویداد صفحه (مثل المانِ مشخص یا state شبکه) صبر کنید و از تایماوتهای دینامیک استفاده کنید. در مواردی که جاوااسکریپت سنگین است، waitUntil: 'networkidle' یا 'domcontentloaded' در page.goto مفید است.
کلیک کردن روی دکمهها و همگامسازیِ navigation
وقتی کلیک باعث ناوبری (navigation) میشود، باید هم کلیک را اجرا کنید و هم منتظر پایان ناوبری بمانید تا شرایط همگام بماند.
// مثال امن برای کلیک که باعث ناوبری میشود
await page.goto('http://quotes.toscrape.com/');
const buttonQuery = '.next > a';
await page.waitForSelector(buttonQuery);
// اگر کلیک باعث بارگذاری صفحهٔ جدید میشود، از Promise.all برای جلوگیری از race استفاده کنید
await Promise.all([
page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
page.click(buttonQuery),
]);نکات:
- استفاده از Promise.all تضمین میکند که کلیک و انتظار برای ناوبری بهدرستی هماهنگ شوند.
- برای کلیکهای AJAX-only، کافیست بعد از کلیک page.waitForSelector یا waitForResponse مناسب را صدا بزنید.
اسکرول و صفحات با بارگذاری تنبل (Infinite Scroll)
برای جمعآوری داده از صفحات با اسکرول نامحدود معمولاً باید تا لود کاملِ محتوای جدید اسکرول کنید و تکرار کنید تا دیگر محتوایی نیاید.
async function scrollToBottom(page) {
let previousHeight = 0;
while (true) {
const { scrollHeight } = await page.evaluate(() => ({ scrollHeight: document.documentElement.scrollHeight }));
await page.evaluate(() => window.scrollTo(0, document.documentElement.scrollHeight));
await page.waitForTimeout(1000); // منتظر بارگذاری
if (scrollHeight === previousHeight) break;
previousHeight = scrollHeight;
}
}
// استفاده
await page.goto('http://quotes.toscrape.com/scroll');
await scrollToBottom(page);هشدارها و بهینهسازیها:
- از حلقههای بیپایان با شرط خروج مطمئن استفاده کنید تا حافظه پر نشود.
- گاهی بهتر است از APIهای صفحه (مثلاً endpointهای JSON) استفاده کنید تا نیاز به اسکرول نباشد.
- تعداد درخواستها و سرعت اسکرول را کنترل کنید تا موجب بلاک شدن نشود.
گرفتن اسکرینشاتها
Playwright امکانات متنوعی برای گرفتن اسکرینشات ارائه میدهد، از عکس گرفتن از viewport جاری تا عکسبرداری full-page.
// کل صفحه
await page.screenshot({ path: 'scrapeops.jpeg', fullPage: true });
// منطقهٔ مشخص با تعیین viewport
await page.setViewportSize({ width: 800, height: 600 });
await page.screenshot({ path: 'scrapeops.png' });نکات فرمتها: jpeg معمولاً سریعتر است و حجم کمتری دارد؛ png کیفیت بدون اتلاف را حفظ میکند. اگر path تعیین نکنید، عکس در حافظهٔ رم نگه داشته میشود و ذخیرهای انجام نمیشود.
استفاده از پراکسی و احراز هویت
در اسکریپینگ واقعی، استفاده از پراکسی معمولاً ضروری است. Playwright اجازه میدهد پراکسی را در زمان launch تنظیم کنید یا برای هر context پراکسی متفاوت بدهید.
const { chromium } = require('playwright');
async function scrapeInfo() {
const PROXY_SERVER = 'http://proxy.example.com:8000';
const PROXY_USERNAME = 'username';
const PROXY_PASSWORD = 'password';
const browser = await chromium.launch({
headless: false,
proxy: {
server: PROXY_SERVER,
username: PROXY_USERNAME,
password: PROXY_PASSWORD,
},
});
const context = await browser.newContext({ ignoreHTTPSErrors: true });
const page = await context.newPage();
await page.goto('https://quotes.toscrape.com', { waitUntil: 'domcontentloaded' });
console.log('Title:', await page.title());
await page.waitForTimeout(5000);
await browser.close();
}
scrapeInfo();نکات امنیتی و عملی:
- اعتبارنامههای پراکسی را در متغیرهای محیطی ذخیره کنید و آنها را در سورس کنترل قرار ندهید.
- در صورت نیاز به چرخش پراکسی، برای هر درخواست یا هر context جدید پراکسی متفاوت قرار دهید.
- پراکسیهای residential معمولاً هزینهٔ بیشتری دارند اما نرخ بلاک شدن را پایین میآورند.
پایداری، عملکرد و بهترینروشها
- مدیریت خطا: همواره از try/catch برای جلوگیری از چسبیدن فرآیند بهخاطر خطا استفاده کنید و در بلوک finally مرورگر را ببندید.
- Retry و backoff: برای درخواستهای حساس از مکانیزم retry با تاخیر افزایشی استفاده کنید.
- محدودسازی همزمانی: باز کردن تعداد زیاد مرورگر همزمان هزینهٔ حافظه و CPU بالایی دارد؛ از pool یا reuse کردن browserContext استفاده کنید.
- استفاده از headless: حالت headless سریعتر و مناسب سرورهاست؛ حالت headed برای دیباگ مفید است.
- لاک کردن نسخهها: نسخهٔ Playwright و مرورگرها را در package.json قفل کنید تا رفتار بین محیطها قابل پیشبینی بماند.
مسائل اخلاقی و قانونی
قبل از اسکریپ کردن هر سایت، شرایط استفاده و قوانین رباتها (robots.txt) را بررسی کنید. از بار بیش از حد روی سرور میزبان جلوگیری کنید و به حریم خصوصی پایبند باشید.
جمعبندی
Playwright یک ابزار قوی برای وب اسکریپینگ است که کنترل دقیق مرورگر، امکانات waiting، کلیک، اسکرول و مدیریت پراکسی را به شما میدهد. در این راهنما نصب، نمونههای عملی و نکات فنی برای پایدارسازی اسکریپها پوشش داده شد. برای پروژههای تولیدی روی مدیریت خطا، محدودسازی همزمانی، و امنسازی اطلاعات حساس (مثل کلید پراکسی) تمرکز کنید. اگر به زبان پایتون عادت دارید، توجه کنید که Playwright برای Python هم binding دارد؛ اما اگر قصد دارید از Node.js استفاده کنید، الگوهای این مقاله قابل بسط برای پروژههای بزرگتر هستند.





