خانه/مقالات/وب اسکریپینگ با Playwright و پراکسی در NodeJS
پروکسی و چرخش IP
Playwright
برگشت به صفحه مقاله ها
وب اسکریپینگ با Playwright و پراکسی در NodeJS

وب اسکریپینگ با Playwright و پراکسی در NodeJS

راهنمای عملی برای افزودن پراکسی به اسکریپرهای NodeJS با Playwright؛ شامل مثال‌های کدنویسی برای پراکسی ساده، پراکسی با احراز هویت، ادغام با proxy port و نکات مهم در مورد SSL، retry، مدیریت کلیدها و بهترین روش‌ها برای پایداری و عملکرد.
آسان اسکریپ
آسان اسکریپ
1404-11-17

مقدمه

این مقاله به‌صورت عملی توضیح می‌دهد چطور در یک اسکریپر NodeJS مبتنی بر Playwright از پراکسی‌ها استفاده کنید. بعد از مطالعهِ مقاله خواهید دانست چه انواع پراکسی‌ای وجود دارد، چگونه پراکسی ساده یا دارای احراز هویت را به chromium.launch اضافه کنید، چرا برخی «APIهای پراکسی» با مرورگرهای هدلس مشکل دارند و چه نکات عملی برای پایداری، امنیت و عملکرد باید رعایت شود.

انواع پراکسی و انتخاب روش

پیش از شروع کدنویسی بهتر است انواع پراکسی را بشناسید:

  • پراکسی ساده HTTP(S) بدون احراز هویت (IP:PORT)
  • پراکسی با username و password (معمول در سرویس‌های تجاری)
  • پراکسی‌های «API/Smart» که به‌جای پورت مستقیم یک endpoint HTTP ارائه می‌کنند (معمولاً با rotation و ban-detection)

برای اسکریپ‌های مبتنی بر مرورگر، بهترین گزینه زمانی که فراهم است، استفاده از «پورت پراکسی» است زیرا مرورگرها هنگام مواجهه با آدرس‌های نسبی در صفحه ممکن است endpointهای API را به‌اشتباه به عنوان مبنا در نظر بگیرند و برخی منابع صفحه لود نشوند.

پراکسی ساده (بدون احراز هویت)

فرض کنید یک پراکسی ساده مانند 11.456.448.110:8080 دارید. برای اضافه کردن آن به Playwright کافی است در launchOptions شیء proxy را ست کنید:

const { chromium } = require('playwright');

const PROXY_SERVER = 'http://11.456.448.110:8080';

const launchOptions = {
  proxy: { server: PROXY_SERVER }
};

(async () => {
  const browser = await chromium.launch(launchOptions);
  const page = await browser.newPage();
  await page.goto('https://httpbin.org/ip');
  const pageContent = await page.textContent('body');
  console.log(pageContent);
  await browser.close();
})();

توضیح ورودی/خروجی و نقش توابع:

  • PROXY_SERVER: آدرس پراکسی به‌صورت 'http://IP:PORT' یا 'IP:PORT'.
  • launchOptions.proxy.server: به Playwright می‌گوید ترافیک مرورگر از چه پراکسی‌ای عبور کند.
  • chromium.launch: مرورگر را با گزینه‌های مشخص‌شده راه‌اندازی می‌کند؛ خروجی یک شیء browser است.
  • page.goto: صفحه را بارگذاری می‌کند؛ اگر پراکسی کار کند، درخواست از طریق آن ارسال می‌شود.

نکته: برای فایرفاکس کافی است chromium را با firefox جایگزین کنید و از firefox.launch استفاده کنید.

پراکسی با احراز هویت (username/password)

سرویس‌های تجاری اغلب یک نقطهٔ ورود واحد می‌دهند و احراز هویت را از طریق نام کاربری و رمز عبور انجام می‌دهند. ساختار کد شبیه حالت قبل است، اما فیلدهای username و password را اضافه می‌کنیم:

const { chromium } = require('playwright');

const proxyUrl = '11.456.448.110:8080';
const proxyUsername = 'PROXY_USERNAME';
const proxyPassword = 'PROXY_PASSWORD';

const launchOptions = {
  proxy: {
    server: proxyUrl,
    username: proxyUsername,
    password: proxyPassword
  }
};

(async () => {
  const browser = await chromium.launch(launchOptions);
  const page = await browser.newPage();
  await page.goto('https://httpbin.org/ip');
  const pageContent = await page.textContent('body');
  console.log(pageContent);
  await browser.close();
})();

توضیحات خط به خط (خلاصه):

  1. تعریف آدرس پراکسی و اطلاعات کاربری.
  2. قرار دادن این اطلاعات داخل launchOptions.proxy.
  3. راه‌اندازی مرورگر؛ Playwright هنگام برقراری اتصال از این credentials استفاده می‌کند.

ادغام Proxy APIها و تفاوت Port vs Endpoint

بعضی ارائه‌دهندگان پراکسی، یک API هوشمند ارائه می‌دهند که خودش rotation، بررسی بن و retry را انجام می‌دهد. این APIها معمولاً یک URL endpoint دارند. مسئله این است که وقتی مرورگر صفحه‌ای با لینک‌های نسبی دریافت می‌کند، Playwright ممکن است آن لینک‌ها را نسبت به آدرس پراکسی (endpoint) تفسیر کند و منابع صفحه درست لود نشوند.

راه‌حل: اگر ارائه‌دهنده پورت پراکسی (proxy port) ارائه می‌دهد، از آن استفاده کنید تا مرورگر مانند یک پراکسی معمولی عمل کند و آدرس‌های نسبی به درستی کار کنند. به عنوان مثال، در حالت پورت شما همانند نمونه‌های بالا آدرس proxy را به شکل 'proxy.example.io:5353' به launchOptions.proxy.server می‌دهید و نام کاربری/کلید API را در فیلد password قرار می‌دهید.

// مثال ادغام با proxy port و کلید API
const { chromium } = require('playwright');

const proxyUrl = 'proxy.scrapeops.io:5353';
const SCRAPEOPS_API_KEY = 'YOUR_API_KEY';

const launchOptions = {
  ignoreHTTPSErrors: true, // بعضی proxyها نیاز به نادیده گرفتن خطاهای SSL دارند
  proxy: {
    server: proxyUrl,
    username: 'scrapeops',
    password: SCRAPEOPS_API_KEY
  }
};

(async () => {
  const browser = await chromium.launch(launchOptions);
  const page = await browser.newPage();
  await page.goto('https://httpbin.org/ip');
  const pageContent = await page.textContent('body');
  console.log(pageContent);
  await browser.close();
})();

نکته SSL: بعضی proxyهای API برای هدایت ترافیک نیاز دارند که خطاهای گواهی‌نامهٔ TLS نادیده گرفته شوند (ignoreHTTPSErrors: true). این را فقط وقتی که مطمئن هستید به سرویس‌های قابل اعتماد متصل می‌شوید فعال کنید.

نکات عملی برای پایداری، خطاها و عملکرد

برای پروژه‌های واقعی این موارد را در نظر بگیرید:

  • Rotation و Pools: از مجموعه‌ای از پراکسی‌ها استفاده کنید تا ریسک بن‌شدن کاهش یابد.
  • Session‌ و کوکی‌ها: برای هر session یا user یک context جداگانه بسازید تا ایزولاسیون کوکی و cache داشته باشید (browser.newContext).
  • Retry و backoff: در مقابل خطاهای شبکه یا 5xx از retry با exponential backoff استفاده کنید.
  • Rate limiting: سرعت درخواست‌ها را کنترل کنید تا از throttling سمت سرور جلوگیری شود.
  • Timeout و cleanup: برای جلوگیری از منابع بلااستفاده، timeout مناسب برای page.goto و زمان‌بندی بستن مرورگر تعیین کنید.

نمونهٔ ساده برای wrapper retry که می‌توانید هنگام page.goto استفاده کنید:

async function withRetries(fn, attempts = 3, delay = 1000) {
  let lastErr;
  for (let i = 0; i < attempts; i++) {
    try {
      return await fn();
    } catch (err) {
      lastErr = err;
      const wait = delay * Math.pow(2, i); // exponential backoff
      await new Promise(r => setTimeout(r, wait));
    }
  }
  throw lastErr;
}

// استفاده:
await withRetries(() => page.goto('https://example.com'), 4, 500);

نکات امنیتی و مدیریت کلیدها

چند اصل مهم:

  • کلیدهای API و رمزهای پراکسی را در متغیرهای محیطی نگه دارید، نه در کد منبع.
  • دسترسی‌ها را محدود کنید و در صورت امکان از سرویس‌های مدیریت اسرار (vault) استفاده کنید.
  • هنگام استفاده از ignoreHTTPSErrors: true احتیاط کنید؛ تنها زمانی فعال شود که به endpoint مورد اعتماد متصل هستید.

موارد پیشرفته و مقایسه روش‌ها

وقتی انتخاب بین استفاده از پراکسی‌ها روی پورت و استفاده از API دارید، عوامل زیر را در نظر بگیرید:

  • سازگاری با مرورگرها: پورت پراکسی معمولاً با لینک‌های نسبی و منابع داخلی صفحات سازگارتر است.
  • کارایی و تاخیر: بعضی APIها ممکن است لایه‌های اضافی داشته باشند؛ تست عملکرد انجام دهید.
  • قابلیت‌هایی مثل هوشمندسازی retry و تشخیص بن: APIها این امکانات را ارائه می‌دهند اما باید مطمئن باشید که با مرورگر هماهنگ‌اند.

جمع‌بندی

اضافه کردن پراکسی به اسکریپرهای Playwright کاری مستقیم است: کافی است launchOptions.proxy را تنظیم کنید. برای پراکسی‌های احراز هویت فیلدهای username و password را اضافه کنید و در صورت استفاده از proxy APIها، تا جای ممکن از پورت پراکسی استفاده کنید تا مشکلات لینک‌های نسبی پیش نیاید. در نهایت، مدیریت خطا، rotation، و حفاظت از کلیدها، نقش کلیدی در پایداری و امنیت اسکریپر شما دارند.

مقاله‌های مرتبط
ابزارها و فریم‌ورک‌ها (Scrapy, Puppeteer و …)
1404-12-10
اسکریپینگ با Scrapy: پاک‌سازی داده و موارد مرزی
راهنمای عملی برای ساخت اسپایدرهای مقاوم با Scrapy: چگونگی سازماندهی داده با Items، پاک‌سازی هنگام استخراج با Item Loaders و پردازش نهایی و حذف تکراری‌ها با Item Pipelines به همراه مثال‌های کد و نکات عملکردی و امنیتی.
ابزارها و فریم‌ورک‌ها (Scrapy, Puppeteer و …)
1404-12-09
حل خطای 503 در اسکریپینگ با Scrapy
این مقاله گام‌به‌گام به شما نشان می‌دهد چگونه خطای HTTP 503 را هنگام اسکریپینگ با Scrapy تشخیص و رفع کنید: ابتدا بررسی وضعیت سرور، سپس استفاده از User-Agent جعلی و بهینه‌سازی هدرها، و در صورت نیاز به پراکسی‌های چرخان و مدیریت retry برای پایداری بلندمدت. توصیه‌ها عملی و شامل نمونه‌های کد برای pythonscrapy هستند.
ابزارها و فریم‌ورک‌ها (Scrapy, Puppeteer و …)
1404-12-07
اسکریپینگ Walmart با Scrapy: راهنمای عملی
این راهنما نشان می‌دهد چگونه با Scrapy یک اسکریپر عملی برای Walmart بسازید: طراحی معماری discovery + product scraper، استخراج JSON از تگ __NEXT_DATA__, صفحه‌بندی و محدودیت 25 صفحه، ذخیره‌سازی با FEEDS یا پایپلاین، و روش‌های مقابله با محافظت ضد-ربات مثل پراکسی چرخشی و headless browser. همچنین نکات مربوط به مانیتورینگ، بهترین‌روش‌های عملی و استقرار در محیط تولید پوشش داده شده‌اند.