مقدمه
در این مقاله با زبان صمیمی و آموزشی، دو ابزار محبوب برای اسکریپینگِ وب که اجرای مرورگر را میسر میکنند — Playwright (معمولاً با Node.js) و Selenium (معمولاً با Python) — مقایسه میکنیم. هدف این راهنما این است که در پایان بدانید کدام ابزار برای سناریوی شما مناسبتر است، چگونه نصب و اجرا شوند، و چه نکات عملی، بهینهسازی و مخاطراتی را باید در نظر بگیرید.
خوانندهی این متن توسعهدهندهی Python در سطح متوسط در نظر گرفته شده اما مثالهای JavaScript/Node.js برای Playwright هم داریم تا تفاوتها روشن شود. در طول مقاله مثالهای کد، توضیح ورودی/خروجی توابع، و نکات بهترینعمل ارائه میشود.
TLDR: نتیجه سریع
- Playwright: سریعتر، نصب سادهتر، پشتیبانی قوی از async/await و اجرای موازیِ داخلی؛ مناسب وقتی سرعت و همزمانی اهمیت دارد.
- Selenium: بالغ، با جامعه بزرگ و APIِ همگرا با سبکهای سنتیِ همگام (synchronous) در Python؛ مناسب وقتی میخواهید از مدل برنامهنویسی همگام بهره ببرید یا ابزارها/زبانهای دیگر را به کار ببندید.
Playwright — معرفی و مزایا
ایده کلی: Playwright یک کتابخانهٔ Node.js برای اتوماسیون مرورگر است که مرورگرهای خاص خودش را تأمین میکند و طراحیشده تا با SPAها و محتوای دینامیک بهخوبی کار کند.
مزایای اصلی Playwright:
- مدیریت محتوای دینامیک: مناسب اپلیکیشنهای تکصفحهای و المنتهای پویا که بدون رفرش کامل تغییر میکنند.
- بستهبندی مرورگر: معمولا مرورگرهای موردنیاز همراه بسته نصب میآیند که مشکل ناسازگاری درایور را حذف میکند.
- پشتیبانی از async/await: برای کنترل دقیقتر جریانهای غیرهمزمان و مدیریت تایماوتها مناسب است.
- اسکرینشات و ضبط: ابزارهای داخلی برای اعتبارسنجی بصری و دیباگ.
- اجرای موازی: از کارخانهٔ Playwright میتوان بهراحتی برای اجرای همزمان چند کار استفاده کرد.
معایب مهم:
- منحنی یادگیری async: اگر با JavaScript غیرهمزمان راحت نیستید، نوشتن اسکریپتهای پیچیده سخت میشود.
- مصرف منابع: اجرای مرورگر واقعی حافظه و CPU قابل توجهی مصرف میکند—برای اسکریپینگ در مقیاس بزرگ چالشزاست.
نصب و مثال پایه Playwright
نمونهٔ نصب و یک اسکریپت ساده که صفحه را باز کرده، عنوان را میخواند و بسته میشود. در این مثال فرض میکنیم Node.js نصب است.
const { chromium } = require('playwright');
async function main() {
// ورودی: هیچ؛ خروجی: چاپ عنوان صفحه در کنسول
const browser = await chromium.launch({ headless: true }); // headless:true در حالت سرویسپسند
const page = await browser.newPage();
await page.goto('https://quotes.toscrape.com', { timeout: 30000 }); // صبر حداکثر 30s
const title = await page.title();
console.log('Title:', title);
await browser.close();
}
main().catch(err => { console.error(err); process.exit(1); });شرح کوتاه خطبهخط:
- ایمپورت chromium از Playwright.
- chromium.launch: مرورگر را میسازد؛ headless را بسته به نیاز تغییر دهید (در توسعه اغلب false است).
- browser.newPage(): یک صفحه/تب جدید باز میکند.
- page.goto(url, {timeout}): به نشانی میرود؛ باید تایماوت مناسب بدهید چون پروکسی یا صفحات سنگین ممکن است زمان ببرند.
- page.title(): عنوان صفحه را برمیگرداند؛ سپس مرورگر بسته میشود.
نکات پیادهسازی:
- برای مدیریت کلیدهای محرمانه مثل API_KEY از متغیرهای محیطی استفاده کنید، نه hardcode.
- برای مقیاسپذیری از contexts و browser instances مجزا یا workerهای Playwright استفاده کنید.
Selenium — معرفی و مزایا
ایده کلی: Selenium یک چارچوب قدیمیتر و چندزبانه برای اتوماسیون مرورگر است که در میان تیمهای تست و اسکریپینگ بسیار مشهور است. در اینجا تمرکز روی استفاده با Python است.
مزایا:
- سینتکس همگام: نوشتن اسکریپتها برای کسانی که به مدل همگام عادت دارند سادهتر است.
- پشتیبانی گسترده از مرورگرها: با درایورهای مخصوص هر مرورگر (مثل ChromeDriver) کار میکند و گزینههای متنوعی دارد.
- جامعه و منابع آموزشی زیاد: مثالها و راهحلهای فراوانی در دسترس است.
معایب:
- نیاز به درایور و هماهنگی نسخهها: باید نسخهٔ درایور را با مرورگر همتراز کنید یا از ابزارهایی مثل webdriver-manager استفاده کنید.
- مصرف منابع و سرعت کمتر: بهویژه در مقایسه با Playwright که ارتباطات مستقیمی با موتور مرورگر دارد.
نصب و مثال پایه Selenium (Python)
نمونهٔ پایه که مشابه مثال Playwright رفتار میکند: باز کردن صفحه، خواندن عنوان، بسته شدن.
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep
# ورودی: باید chromedriver در PATH موجود باشد یا مسیر بدهید
# خروجی: چاپ عنوان صفحه
driver = webdriver.Chrome()
driver.get('https://quotes.toscrape.com')
print('Title:', driver.title)
sleep(2)
driver.quit()شرح خطبهخط:
- webdriver.Chrome(): نمونهٔ مرورگر را باز میکند (نیاز به درایور متناسب دارد).
- driver.get(url): صفحه را باز میکند. Selenium بهصورت همگام میماند تا مرورگر پاسخ دهد.
- driver.title: عنوان صفحه را میخواند.
- driver.quit(): مرورگر را میبندد و منابع را آزاد میکند.
نکات پیادهسازی:
- برای اجرای headless باید گزینههای مربوط به ChromeOptions را تنظیم کنید.
- برای مدیریت درایورها از ابزارهایی مثل webdriver-manager یا نصب نسخهٔ مناسب درایور استفاده کنید.
مقایسه فنی و عملیاتی
عناصر کلیدی که هنگام انتخاب باید مدنظر قرار دهید:
- عملکرد: Playwright معمولاً سریعتر و پاسخگوتر است چون بدون لایهٔ WebDriver اضافی کار میکند.
- مدیریت همزمانی: Playwright اجرای موازی را آسانتر میکند؛ در Selenium برای این کار معمولاً به threading/process pools و مدیریت درایور اضافی نیاز است.
- سادگی توسعه: اگر با Python راحتید و نمیخواهید async را مدیریت کنید، Selenium انتخاب سادهتری است.
- نصب و سازگاری: Playwright غالباً مرورگر را همراه بستهبندی میآورد؛ Selenium نیازمند مدیریت جداگانهٔ درایورهاست.
- اسکریپینگ در مقیاس: هر دو هنگام اجرا در مرورگر واقعی به منابع زیادی نیاز دارند؛ برای مقیاس بالا بهتر است ترکیبی از روشها (headless، کشینگ، APIها، یا استفاده از سرویسهای استخراج اختصاصی) مدنظر قرار گیرد.
مطالعه موردی: اسکریپ کردن لیست آگهیها با پروکسی
ایده: یک سایت تولیدی را با استفاده از پروکسی فراخوانی میکنیم تا شناسایی و بلاک شدن کاهش یابد. در هر دو مثال تابعی برای ساخت URL پروکسی نوشته شده و سپس با Playwright/Node و Selenium/Python عناصر صفحه خوانده میشوند.
الگوی کلی تابع پروکسی:
- ورودی: url (نشانی مقصد) و API_KEY (محرمانه).
- خروجی: URL ای که درخواست را از طریق پروکسی میفرستد.
نکات امنیتی: کلید API را در متغیر محیطی ذخیره کنید و در لاگها چاپ نکنید؛ از سیگنالهای rate-limit و رفتار خطا (retry/backoff) مراقبت کنید.
نمونه Playwright برای اسکریپ کردن با پروکسی
const { chromium } = require('playwright');
const { URLSearchParams } = require('url');
const API_KEY = process.env.SCRAPEOPS_API_KEY; // ورودی امن
function getScrapeOpsUrl(url) {
const payload = { api_key: API_KEY, url };
const qs = new URLSearchParams(payload).toString();
return `https://proxy.scrapeops.io/v1/?${qs}`; // خروجی: URL پروکسی
}
async function main() {
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
// تایماوت طولانیتر بهدلیل پروکسی
await page.goto(getScrapeOpsUrl('https://www.realtor.com/realestateandhomes-search/Detroit_MI/show-recently-sold/sby-6'), { timeout: 120000 });
const elements = await page.$$('.card-anchor'); // لیست المنتها
for (const el of elements) {
const href = await el.getAttribute('href');
if (!href) continue;
const parts = href.split('/');
console.log(parts[parts.length - 1]);
}
await browser.close();
}
main().catch(e => console.error(e));نکات و توضیحات:
- اجرای page.goto روی URL پروکسی ممکن است کندتر باشد؛ تایماوت را متناسب افزایش دهید.
- برای استخراج المنتها از page.$$(selector) استفاده میشود که یک لیست برمیگرداند.
- مدیریت خطا و null-check برای href ضروری است.
نمونه Selenium برای اسکریپ کردن با پروکسی
from selenium import webdriver
from selenium.webdriver.common.by import By
from urllib.parse import urlencode
import os
API_KEY = os.getenv('SCRAPEOPS_API_KEY') # ورودی امن
def get_scrapeops_url(url):
payload = {'api_key': API_KEY, 'url': url}
return 'https://proxy.scrapeops.io/v1/?' + urlencode(payload) # خروجی: URL پروکسی
# توجه: مسیر chromedriver یا Manager باید تنظیم شود
driver = webdriver.Chrome()
try:
driver.get(get_scrapeops_url('https://www.realtor.com/realestateandhomes-search/Detroit_MI/show-recently-sold/sby-6'))
elements = driver.find_elements(By.CLASS_NAME, 'card-anchor')
for el in elements:
link = el.get_attribute('href')
if not link:
continue
parts = link.split('/')
print(parts[-1])
finally:
driver.quit()توضیحات:
- در Selenium از find_elements استفاده میکنیم که لیستی از WebElementها برمیگرداند.
- برای مقیاس یا پایداری، ترکیب Selenium با session pooling یا اجرای چندین فرایند پیشنهاد میشود؛ اما مدیریت درایور و منابع پیچیدهتر است.
نکات عملی، بهینهسازی و هشدارها
- پروکسی و چرخش IP: برای سایتهای تولیدی از پروکسی، چرخش IP و مدیریت نرخ درخواست استفاده کنید تا بلاک نشوید.
- هدرها و user-agent: هدرهای واقعی و چرخاندن user-agent کمک میکند رفتار شبیهتر به مرورگر انسانی شود.
- مدیریت خطا و Retry: روی خطاهای شبکه، timeouts و captchas برنامهٔ retry با backoff پیاده کنید.
- ذخیرهسازی و کش: دادههایی که تکراریاند را کش کنید تا از بار غیرضروری روی مقصد جلوگیری شود.
- امنیت: کلیدها را در متغیر محیطی نگه دارید، لاگها را پالایش کنید و کد جاوااسکریپت ناامن اجرا نکنید.
- مقیاسپذیری: برای اسکریپینگ در حجم بالا بهتر است ترکیب headless، شیفت به API در صورت وجود، و سرویسهای صف/کارگر (worker queues) را در نظر بگیرید؛ اجرای همزمان مرورگرهای کامل هزینهبر است.
- قوانین و اخلاق: همیشه robots.txt، شرایط استفاده و قوانین سایت هدف را بررسی کنید و مطابق قانون عمل کنید.
جمعبندی
Playwright و Selenium هر دو برای اسکریپینگ مبتنی بر مرورگر مناسباند اما انتخاب بین آنها به نیاز شما بستگی دارد: اگر به سرعت، اجرای موازی و کنترل async نیاز دارید، Playwright برتری دارد؛ اگر میخواهید با سینتکس همگام Python کار کنید و مدیریت مرورگر/درایور برایتان قابل اداره است، Selenium گزینهٔ مناسبی است.
همیشه از پروکسیها و روشهای محافظتی برای جلوگیری از بلاک شدن استفاده کنید، کلیدها را ایمن نگه دارید و هنگام اسکریپینگ در مقیاس به مصرف منابع و معماری توزیعشده توجه کنید.





