

Playwright یک کتابخانهٔ اتوماسیون ساختهشده توسط Microsoft است که API سطحبالا و مناسب برای تعامل با صفحات وب دینامیک در Node.js فراهم میکند. برای توسعهدهندگان پایتون سطح متوسط که با وب اسکریپینگ آشنا هستند، Playwright در نسخهٔ Node گزینهای قدرتمند برای کنترل مرورگر (Chromium, WebKit, Firefox) است؛ مخصوصاً وقتی به تعامل با جاوااسکریپتِ دینامیک، کلیک، اسکرول نامحدود و گرفتن اسکرینشات نیاز دارید. در انتهای این مقاله شما یاد میگیرید چگونه Playwright را نصب کنید، اسکریپهای ساده برای استخراج داده بنویسید، مسائل مربوط به زمانبندی و همگامسازی (waiting) را مدیریت کنید، از پراکسی استفاده کنید و چند بهترینروش برای پایداری و کارایی را پیادهسازی نمایید.
قدمهای پایه برای راهاندازی یک پروژه Node.js که از Playwright استفاده میکند بسیار ساده است. موارد ضروری:
دستورات نمونه (در ترمینال):
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();توضیح خطبهخط:
برای استخراج دادهها از صفحهٔ 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();نکات مهم در این مثال:
سینک شدن با صفحه یکی از مهمترین چالشها در وب اسکریپینگ است. دو روش رایج:
// 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) میشود، باید هم کلیک را اجرا کنید و هم منتظر پایان ناوبری بمانید تا شرایط همگام بماند.
// مثال امن برای کلیک که باعث ناوبری میشود
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),
]);نکات:
برای جمعآوری داده از صفحات با اسکرول نامحدود معمولاً باید تا لود کاملِ محتوای جدید اسکرول کنید و تکرار کنید تا دیگر محتوایی نیاید.
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);هشدارها و بهینهسازیها:
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();نکات امنیتی و عملی:
قبل از اسکریپ کردن هر سایت، شرایط استفاده و قوانین رباتها (robots.txt) را بررسی کنید. از بار بیش از حد روی سرور میزبان جلوگیری کنید و به حریم خصوصی پایبند باشید.
Playwright یک ابزار قوی برای وب اسکریپینگ است که کنترل دقیق مرورگر، امکانات waiting، کلیک، اسکرول و مدیریت پراکسی را به شما میدهد. در این راهنما نصب، نمونههای عملی و نکات فنی برای پایدارسازی اسکریپها پوشش داده شد. برای پروژههای تولیدی روی مدیریت خطا، محدودسازی همزمانی، و امنسازی اطلاعات حساس (مثل کلید پراکسی) تمرکز کنید. اگر به زبان پایتون عادت دارید، توجه کنید که Playwright برای Python هم binding دارد؛ اما اگر قصد دارید از Node.js استفاده کنید، الگوهای این مقاله قابل بسط برای پروژههای بزرگتر هستند.


