بازگشت به وبلاگ

ادغام پروکسی با پاپیتر و پلی‌رایت: راهنمای کامل با مثال‌های کد

راهنمای جامع برای تنظیم پروکسی HTTP، HTTPS و SOCKS5 در Puppeteer و Playwright با مثال‌های کد به زبان‌های JavaScript و TypeScript.

📅۲۴ بهمن ۱۴۰۴
```html

Puppeteer و Playwright — ابزارهای محبوب برای اتوماسیون مرورگر و وب‌اسکرپینگ هستند. هنگام کار با حجم بالای درخواست‌ها یا پارس کردن سایت‌های محافظت شده، استفاده از پروکسی برای جلوگیری از مسدود شدن IP به شدت ضروری است. در این راهنما، تمام روش‌های ادغام پروکسی در هر دو ابزار را بررسی خواهیم کرد، از تنظیمات پایه تا سناریوهای پیشرفته با چرخش و پردازش خطاها.

اصول کار پروکسی در مرورگرهای بدون سر

Puppeteer و Playwright مرورگرهای واقعی (Chromium، Firefox، WebKit) را از طریق پروتکل DevTools مدیریت می‌کنند. این بدان معناست که پروکسی در سطح راه‌اندازی مرورگر تنظیم می‌شود، نه درخواست‌های جداگانه. هر دو ابزار از پروکسی‌های HTTP، HTTPS و SOCKS5 پشتیبانی می‌کنند، اما API‌های متفاوتی برای تنظیم آن‌ها دارند.

تفاوت‌های کلیدی با کتابخانه‌های HTTP معمولی (axios، fetch):

  • پروکسی در زمان راه‌اندازی مرورگر تنظیم می‌شود — نمی‌توان پروکسی را در حین یک جلسه مرورگر تغییر داد
  • پشتیبانی از JavaScript و رندرینگ — پروکسی به تمام منابع صفحه (تصاویر، اسکریپت‌ها، XHR) اعمال می‌شود
  • پردازش خودکار ریدایرکت‌ها و کوکی‌ها — مرورگر مانند یک کاربر واقعی عمل می‌کند
  • اثر انگشت — حتی با پروکسی، سایت‌ها می‌توانند اتوماسیون را با ویژگی‌های مرورگر شناسایی کنند

مهم: برای وظایفی که نیاز به تغییر مکرر IP دارند (پارس کردن هزاران صفحه، ثبت‌نام انبوه)، استفاده از پروکسی‌های مسکونی با چرخش کارآمدتر است — آن‌ها اجازه می‌دهند IP را برای هر درخواست بدون راه‌اندازی مجدد مرورگر تغییر دهید.

تنظیم پروکسی در Puppeteer

Puppeteer — کتابخانه‌ای از Google برای مدیریت Chrome/Chromium. پروکسی از طریق آرگومان‌های راه‌اندازی مرورگر با استفاده از پرچم --proxy-server تنظیم می‌شود.

تنظیم پایه پروکسی HTTP/HTTPS

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless: true,
    args: [
      '--proxy-server=http://proxy.example.com:8080'
    ]
  });

  const page = await browser.newPage();
  
  // بررسی آدرس IP
  await page.goto('https://api.ipify.org?format=json');
  const content = await page.content();
  console.log('آدرس IP فعلی:', content);

  await browser.close();
})();

این کد مرورگر را از طریق سرور پروکسی راه‌اندازی می‌کند. تمام درخواست‌های HTTP و HTTPS از طریق پروکسی مشخص شده عبور خواهند کرد. برای بررسی قابلیت کار از سرویس ipify استفاده می‌شود که آدرس IP خارجی را برمی‌گرداند.

تنظیم پروکسی SOCKS5

const browser = await puppeteer.launch({
  headless: true,
  args: [
    '--proxy-server=socks5://proxy.example.com:1080'
  ]
});

// کد باقی‌مانده مشابه است

پروکسی‌های SOCKS5 در سطح پایین‌تری کار می‌کنند و از ترافیک UDP پشتیبانی می‌کنند که می‌تواند برای برخی از وب‌اپلیکیشن‌ها مفید باشد. نحو آن مشابه پروکسی HTTP است، فقط پروتکل در URL تغییر می‌کند.

استفاده از پروکسی برای دامنه‌های خاص

const browser = await puppeteer.launch({
  args: [
    '--proxy-server=http://proxy1.example.com:8080',
    '--proxy-bypass-list=localhost;127.0.0.1;*.internal.com'
  ]
});

// درخواست‌های محلی و درخواست‌های به *.internal.com به طور مستقیم خواهند رفت
// سایر درخواست‌ها — از طریق پروکسی

پرچم --proxy-bypass-list اجازه می‌دهد دامنه‌های خاصی از پروکسی‌کردن مستثنی شوند. این مفید است زمانی که نیاز به ترکیب درخواست‌های مستقیم و پروکسی‌شده باشد.

تنظیم پروکسی در Playwright

Playwright — کتابخانه‌ای مدرن‌تر از Microsoft است که از Chromium، Firefox و WebKit پشتیبانی می‌کند. پروکسی از طریق شیء پیکربندی تنظیم می‌شود که API را قابل فهم‌تر و نوع‌دارتر می‌کند.

تنظیم پایه پروکسی

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

(async () => {
  const browser = await chromium.launch({
    proxy: {
      server: 'http://proxy.example.com:8080'
    }
  });

  const context = await browser.newContext();
  const page = await context.newPage();
  
  await page.goto('https://api.ipify.org?format=json');
  const ip = await page.textContent('body');
  console.log('IP از طریق پروکسی:', ip);

  await browser.close();
})();

Playwright از شیء proxy به جای آرگومان‌های خط فرمان استفاده می‌کند. این نوع‌سازی بهتری در TypeScript و کد تمیزتری را فراهم می‌کند.

تنظیم پروکسی در سطح زمینه

const browser = await chromium.launch();

// زمینه 1 - با پروکسی
const context1 = await browser.newContext({
  proxy: {
    server: 'http://proxy1.example.com:8080'
  }
});

// زمینه 2 - با پروکسی دیگر
const context2 = await browser.newContext({
  proxy: {
    server: 'http://proxy2.example.com:8080'
  }
});

const page1 = await context1.newPage();
const page2 = await context2.newPage();

// هر صفحه از پروکسی خود استفاده می‌کند!

یکی از مزایای کلیدی Playwright — امکان ایجاد چندین زمینه مرورگر با پروکسی‌های مختلف در یک فرآیند است. این امر در هنگام کار با تعداد زیادی آدرس IP منابع را صرفه‌جویی می‌کند.

استثنای دامنه‌ها از پروکسی‌کردن

const browser = await chromium.launch({
  proxy: {
    server: 'http://proxy.example.com:8080',
    bypass: 'localhost,127.0.0.1,*.internal.com'
  }
});

// درخواست‌ها به localhost و *.internal.com به طور مستقیم خواهند رفت

احراز هویت با نام کاربری و رمز عبور

بیشتر پروکسی‌های تجاری نیاز به احراز هویت دارند. هر دو ابزار از مجوز پشتیبانی می‌کنند، اما آن را به شیوه‌های مختلف پیاده‌سازی می‌کنند.

احراز هویت در Puppeteer

const browser = await puppeteer.launch({
  args: ['--proxy-server=http://proxy.example.com:8080']
});

const page = await browser.newPage();

// تنظیم اعتبارنامه‌ها برای پروکسی
await page.authenticate({
  username: 'your_username',
  password: 'your_password'
});

await page.goto('https://httpbin.org/ip');
const content = await page.content();
console.log(content);

متد page.authenticate() اعتبارنامه‌ها را برای تمام درخواست‌های بعدی در این صفحه تنظیم می‌کند. مهم است که آن را قبل از اولین page.goto() فراخوانی کنید.

احراز هویت در Playwright

const browser = await chromium.launch({
  proxy: {
    server: 'http://proxy.example.com:8080',
    username: 'your_username',
    password: 'your_password'
  }
});

const page = await browser.newPage();
await page.goto('https://httpbin.org/ip');

Playwright اجازه می‌دهد اعتبارنامه‌ها را مستقیماً در شیء پیکربندی پروکسی مشخص کنید — این راحت‌تر و ایمن‌تر است، زیرا نیاز به فراخوانی متدهای اضافی ندارد.

روش جایگزین: اعتبارنامه‌ها در URL

// در هر دو فریم‌ورک کار می‌کند
const proxyUrl = 'http://username:password@proxy.example.com:8080';

// Puppeteer
const browser = await puppeteer.launch({
  args: [`--proxy-server=${proxyUrl}`]
});

// Playwright
const browser = await chromium.launch({
  proxy: { server: proxyUrl }
});

این روش کار می‌کند، اما برای تولید توصیه نمی‌شود — اعتبارنامه‌ها ممکن است در لاگ‌ها ظاهر شوند. از متغیرهای محیطی برای ذخیره داده‌های حساس استفاده کنید.

نکته: هنگام کار با پارسینگ سایت‌های تجاری، توصیه می‌شود از پروکسی‌های مسکونی استفاده کنید — آن‌ها دارای IP واقعی کاربران خانگی هستند و کمتر توسط سیستم‌های ضد ربات مسدود می‌شوند.

چرخش پروکسی و مدیریت استخر IP

برای پارسینگ مقیاس‌پذیر، نیاز به تغییر منظم آدرس‌های IP است. از آنجا که پروکسی در زمان راه‌اندازی مرورگر تنظیم می‌شود، چرخش نیاز به راه‌اندازی مجدد جلسه مرورگر دارد.

چرخش ساده با آرایه پروکسی (Puppeteer)

const puppeteer = require('puppeteer');

const proxyList = [
  'http://user1:pass1@proxy1.example.com:8080',
  'http://user2:pass2@proxy2.example.com:8080',
  'http://user3:pass3@proxy3.example.com:8080'
];

async function scrapeWithRotation(urls) {
  for (let i = 0; i < urls.length; i++) {
    const proxyUrl = proxyList[i % proxyList.length];
    
    const browser = await puppeteer.launch({
      args: [`--proxy-server=${proxyUrl}`]
    });

    try {
      const page = await browser.newPage();
      await page.goto(urls[i], { waitUntil: 'networkidle0' });
      
      const data = await page.evaluate(() => {
        return {
          title: document.title,
          url: window.location.href
        };
      });
      
      console.log(`URL ${i + 1}:`, data);
    } catch (error) {
      console.error(`خطا در ${urls[i]}:`, error.message);
    } finally {
      await browser.close();
    }
  }
}

const urlsToScrape = [
  'https://example.com/page1',
  'https://example.com/page2',
  'https://example.com/page3',
  'https://example.com/page4'
];

scrapeWithRotation(urlsToScrape);

این کد به صورت چرخه‌ای پروکسی‌ها را از لیست مرور می‌کند و برای هر URL یک مرورگر جدید راه‌اندازی می‌کند. متد i % proxyList.length چرخش چرخه‌ای را تضمین می‌کند.

چرخش با استخر زمینه‌ها (Playwright)

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

const proxyList = [
  { server: 'http://proxy1.example.com:8080', username: 'user1', password: 'pass1' },
  { server: 'http://proxy2.example.com:8080', username: 'user2', password: 'pass2' },
  { server: 'http://proxy3.example.com:8080', username: 'user3', password: 'pass3' }
];

async function scrapeWithContextPool(urls) {
  const browser = await chromium.launch();
  
  // ایجاد استخر زمینه‌ها با پروکسی‌های مختلف
  const contexts = await Promise.all(
    proxyList.map(proxy => browser.newContext({ proxy }))
  );

  for (let i = 0; i < urls.length; i++) {
    const context = contexts[i % contexts.length];
    const page = await context.newPage();
    
    try {
      await page.goto(urls[i], { waitUntil: 'networkidle' });
      const title = await page.title();
      console.log(`URL ${i + 1} (پروکسی ${i % contexts.length}):`, title);
    } catch (error) {
      console.error(`خطا در ${urls[i]}:`, error.message);
    } finally {
      await page.close();
    }
  }

  await browser.close();
}

const urls = [
  'https://example.com/page1',
  'https://example.com/page2',
  'https://example.com/page3'
];

scrapeWithContextPool(urls);

Playwright اجازه می‌دهد چندین زمینه را در یک مرورگر ایجاد کنید، هر کدام با پروکسی خود. این امر در مقایسه با راه‌اندازی کامل مرورگر، حافظه و زمان راه‌اندازی را صرفه‌جویی می‌کند.

چرخش هوشمند با ردیابی خطاها

class ProxyRotator {
  constructor(proxyList) {
    this.proxyList = proxyList;
    this.currentIndex = 0;
    this.failedProxies = new Set();
  }

  getNext() {
    const availableProxies = this.proxyList.filter(
      (_, index) => !this.failedProxies.has(index)
    );

    if (availableProxies.length === 0) {
      throw new Error('تمام پروکسی‌ها در دسترس نیستند');
    }

    const proxy = this.proxyList[this.currentIndex];
    this.currentIndex = (this.currentIndex + 1) % this.proxyList.length;
    
    return { proxy, index: this.currentIndex - 1 };
  }

  markFailed(index) {
    this.failedProxies.add(index);
    console.log(`پروکسی ${index} به عنوان غیرقابل دسترسی علامت‌گذاری شد`);
  }

  resetFailed() {
    this.failedProxies.clear();
  }
}

// استفاده
const rotator = new ProxyRotator(proxyList);

async function scrapeWithSmartRotation(url, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const { proxy, index } = rotator.getNext();
    
    const browser = await chromium.launch({ proxy });
    const page = await browser.newPage();

    try {
      await page.goto(url, { timeout: 30000 });
      const data = await page.content();
      await browser.close();
      return data;
    } catch (error) {
      console.error(`خطا با پروکسی ${index}:`, error.message);
      rotator.markFailed(index);
      await browser.close();
      
      if (attempt === maxRetries - 1) {
        throw new Error(`نتوانستیم ${url} را پس از ${maxRetries} تلاش بارگذاری کنیم`);
      }
    }
  }
}

این کلاس پروکسی‌های غیرعملکردی را ردیابی کرده و آن‌ها را از چرخش حذف می‌کند. در صورت بروز خطا، به طور خودکار به پروکسی بعدی در لیست سوئیچ می‌شود.

پردازش خطاها و بررسی قابلیت کار

هنگام کار با پروکسی، خطاهای خاصی بروز می‌کند: زمان‌های اتصال، رد مجوز، مسدود شدن IP توسط سایت هدف. پردازش صحیح خطاها برای عملکرد پایدار پارسر حیاتی است.

خطاهای متداول و پردازش آن‌ها

async function safePageLoad(page, url, options = {}) {
  const defaultOptions = {
    timeout: 30000,
    waitUntil: 'networkidle0',
    maxRetries: 3,
    retryDelay: 2000
  };

  const config = { ...defaultOptions, ...options };

  for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
    try {
      await page.goto(url, {
        timeout: config.timeout,
        waitUntil: config.waitUntil
      });
      
      return { success: true, attempt };
    } catch (error) {
      console.error(`تلاش ${attempt} ناموفق بود:`, error.message);

      // تحلیل نوع خطا
      if (error.message.includes('ERR_PROXY_CONNECTION_FAILED')) {
        throw new Error('پروکسی در دسترس نیست');
      }
      
      if (error.message.includes('ERR_TUNNEL_CONNECTION_FAILED')) {
        throw new Error('خطای تونل‌کردن پروکسی');
      }

      if (error.message.includes('407')) {
        throw new Error('خطای احراز هویت پروکسی (407)');
      }

      if (error.message.includes('Navigation timeout')) {
        console.log(`زمان بارگذاری به پایان رسید، تکرار در ${config.retryDelay}ms`);
        await new Promise(resolve => setTimeout(resolve, config.retryDelay));
        continue;
      }

      // اگر این آخرین تلاش است - خطا را پرتاب کنید
      if (attempt === config.maxRetries) {
        throw error;
      }
    }
  }
}

بررسی قابلیت کار پروکسی

async function testProxy(proxyConfig) {
  const browser = await chromium.launch({ proxy: proxyConfig });
  const page = await browser.newPage();

  const result = {
    working: false,
    ip: null,
    responseTime: null,
    error: null
  };

  const startTime = Date.now();

  try {
    await page.goto('https://api.ipify.org?format=json', { timeout: 10000 });
    const content = await page.textContent('body');
    const data = JSON.parse(content);
    
    result.working = true;
    result.ip = data.ip;
    result.responseTime = Date.now() - startTime;
  } catch (error) {
    result.error = error.message;
  } finally {
    await browser.close();
  }

  return result;
}

// تست لیست پروکسی
async function validateProxyList(proxyList) {
  console.log('بررسی پروکسی...');
  
  const results = await Promise.all(
    proxyList.map(async (proxy, index) => {
      const result = await testProxy(proxy);
      console.log(`پروکسی ${index + 1}:`, result.working ? `✓ ${result.ip} (${result.responseTime}ms)` : `✗ ${result.error}`);
      return { proxy, ...result };
    })
  );

  const workingProxies = results.filter(r => r.working);
  console.log(`\nپروکسی‌های کارآمد: ${workingProxies.length}/${proxyList.length}`);
  
  return workingProxies.map(r => r.proxy);
}

این تابع هر پروکسی را قبل از استفاده بررسی می‌کند، زمان پاسخ را اندازه‌گیری کرده و تنها پروکسی‌های کارآمد را برمی‌گرداند. توصیه می‌شود اعتبارسنجی را در زمان شروع برنامه اجرا کنید.

نظارت و لاگ‌گذاری

class ProxyMonitor {
  constructor() {
    this.stats = {
      totalRequests: 0,
      successfulRequests: 0,
      failedRequests: 0,
      proxyErrors: 0,
      averageResponseTime: 0,
      requestsByProxy: new Map()
    };
  }

  recordRequest(proxyIndex, success, responseTime, error = null) {
    this.stats.totalRequests++;
    
    if (success) {
      this.stats.successfulRequests++;
      this.stats.averageResponseTime = 
        (this.stats.averageResponseTime * (this.stats.successfulRequests - 1) + responseTime) / 
        this.stats.successfulRequests;
    } else {
      this.stats.failedRequests++;
      if (error && error.includes('proxy')) {
        this.stats.proxyErrors++;
      }
    }

    // آمار برای هر پروکسی
    if (!this.stats.requestsByProxy.has(proxyIndex)) {
      this.stats.requestsByProxy.set(proxyIndex, { success: 0, failed: 0 });
    }
    
    const proxyStats = this.stats.requestsByProxy.get(proxyIndex);
    success ? proxyStats.success++ : proxyStats.failed++;
  }

  getReport() {
    const successRate = (this.stats.successfulRequests / this.stats.totalRequests * 100).toFixed(2);
    
    return {
      ...this.stats,
      successRate: `${successRate}%`,
      averageResponseTime: `${this.stats.averageResponseTime.toFixed(0)}ms`
    };
  }
}

// استفاده
const monitor = new ProxyMonitor();

async function monitoredScrape(url, proxyIndex) {
  const startTime = Date.now();
  try {
    // ... کد پارسینگ ...
    const responseTime = Date.now() - startTime;
    monitor.recordRequest(proxyIndex, true, responseTime);
  } catch (error) {
    monitor.recordRequest(proxyIndex, false, 0, error.message);
    throw error;
  }
}

سناریوهای پیشرفته: موقعیت جغرافیایی و اثر انگشت

سیستم‌های ضد ربات مدرن تنها IP را بررسی نمی‌کنند، بلکه تطابق موقعیت جغرافیایی، منطقه زمانی، زبان مرورگر و سایر پارامترها را نیز بررسی می‌کنند. هنگام استفاده از پروکسی از کشور دیگر، مهم است که تمام این پارامترها به درستی تنظیم شوند.

تنظیم موقعیت جغرافیایی و زبان تحت پروکسی

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

async function createContextWithGeo(proxy, geoData) {
  const browser = await chromium.launch({ proxy });
  
  const context = await browser.newContext({
    locale: geoData.locale,           // 'en-US', 'de-DE', 'fr-FR'
    timezoneId: geoData.timezone,     // 'America/New_York', 'Europe/Berlin'
    geolocation: {
      latitude: geoData.latitude,
      longitude: geoData.longitude
    },
    permissions: ['geolocation']
  });

  return { browser, context };
}

// مثال: پروکسی از آلمان
const germanyProxy = {
  server: 'http://de-proxy.example.com:8080',
  username: 'user',
  password: 'pass'
};

const germanyGeo = {
  locale: 'de-DE',
  timezone: 'Europe/Berlin',
  latitude: 52.520008,
  longitude: 13.404954
};

const { browser, context } = await createContextWithGeo(germanyProxy, germanyGeo);
const page = await context.newPage();

await page.goto('https://www.google.com');
// گوگل نسخه آلمانی را با نتایج برای برلین نشان می‌دهد

این کد مرورگر را طوری تنظیم می‌کند که مانند یک کاربر واقعی از آلمان به نظر برسد: زبان رابط آلمانی، منطقه زمانی برلین و مختصات مرکز برلین.

تنظیم کامل اثر انگشت

async function createStealthContext(proxy, profile) {
  const context = await chromium.launch({ proxy }).then(b => 
    b.newContext({
      locale: profile.locale,
      timezoneId: profile.timezone,
      userAgent: profile.userAgent,
      viewport: profile.viewport,
      deviceScaleFactor: profile.deviceScaleFactor,
      isMobile: profile.isMobile,
      hasTouch: profile.hasTouch,
      colorScheme: profile.colorScheme,
      geolocation: profile.geolocation,
      permissions: ['geolocation']
    })
  );

  return context;
}

// پروفایل برای ویندوز 10 + کروم از ایالات متحده
const desktopUSProfile = {
  locale: 'en-US',
  timezone: 'America/New_York',
  userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  viewport: { width: 1920, height: 1080 },
  deviceScaleFactor: 1,
  isMobile: false,
  hasTouch: false,
  colorScheme: 'light',
  geolocation: { latitude: 40.7128, longitude: -74.0060 }
};

// پروفایل برای آیفون از بریتانیا
const mobileUKProfile = {
  locale: 'en-GB',
  timezone: 'Europe/London',
  userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
  viewport: { width: 390, height: 844 },
  deviceScaleFactor: 3,
  isMobile: true,
  hasTouch: true,
  colorScheme: 'light',
  geolocation: { latitude: 51.5074, longitude: -0.1278 }
};

تنظیم جامع اثر انگشت احتمال شناسایی اتوماسیون را کاهش می‌دهد. مهم است که تمام پارامترها با یکدیگر مطابقت داشته باشند: به عنوان مثال، User-Agent موبایل باید با وضوح صفحه موبایل همراه باشد.

مهم: هنگام کار با پلتفرم‌های تبلیغاتی (Google Ads، Facebook Ads) یا خدمات مالی، توصیه می‌شود از پروکسی‌های موبایل استفاده کنید — آن‌ها دارای نمره اعتماد واقعی اپراتورهای موبایل هستند و تقریباً مسدود نمی‌شوند.

دور زدن نشت WebRTC

// Puppeteer: مسدود کردن WebRTC
const browser = await puppeteer.launch({
  args: [
    '--proxy-server=http://proxy.example.com:8080',
    '--disable-webrtc',
    '--disable-webrtc-hw-encoding',
    '--disable-webrtc-hw-decoding'
  ]
});

// Playwright: بازنویسی API WebRTC
const context = await browser.newContext({ proxy: proxyConfig });

await context.addInitScript(() => {
  // مسدود کردن RTCPeerConnection
  window.RTCPeerConnection = undefined;
  window.RTCDataChannel = undefined;
  window.RTCSessionDescription = undefined;
  
  // بازنویسی getUserMedia
  navigator.mediaDevices.getUserMedia = undefined;
  navigator.getUserMedia = undefined;
});

WebRTC می‌تواند آدرس IP واقعی شما را حتی در هنگام استفاده از پروکسی افشا کند. این کد API WebRTC را به طور کامل در مرورگر غیرفعال می‌کند.

مقایسه Puppeteer و Playwright برای کار با پروکسی

معیار Puppeteer Playwright
تنظیم پروکسی از طریق args خط فرمان از طریق شیء پیکربندی
احراز هویت page.authenticate() پس از راه‌اندازی در شیء proxy هنگام ایجاد
چندین پروکسی در یک مرورگر خیر، نیاز به مرورگر جداگانه دارد بله، از طریق زمینه‌های مختلف
پشتیبانی از مرورگرها فقط Chromium/Chrome Chromium، Firefox، WebKit
عملکرد راه‌اندازی سریع یک مرورگر موثرتر در زمینه‌های متعدد
TypeScript نوع‌ها از طریق @types/puppeteer پشتیبانی داخلی از TypeScript
مستندات خوب، مثال‌های زیادی دارد عالی، ساختار یافته‌تر
اکوسیستم پلاگین‌ها و افزونه‌های بیشتری دارد سریع‌تر در حال توسعه، ویژگی‌های جدید

توصیه‌ها برای انتخاب

Puppeteer را انتخاب کنید اگر:

  • فقط با Chrome/Chromium کار می‌کنید
  • تنها یک پروکسی را در یک زمان استفاده می‌کنید
  • به حداکثر سازگاری با ابزارهای موجود نیاز دارید
  • قبلاً یک پایگاه کد بزرگ با Puppeteer دارید

Playwright را انتخاب کنید اگر:

  • به کار با Firefox یا Safari (WebKit) نیاز دارید
  • استفاده همزمان از چندین پروکسی ضروری است
  • عملکرد در مقیاس‌گذاری مهم است
  • در حال نوشتن با TypeScript هستید
  • یک پروژه جدید از ابتدا شروع می‌کنید

عملکرد در هنگام چرخش پروکسی

تست: پارس کردن 100 صفحه با چرخش 10 پروکسی بر روی MacBook Pro M1:

روش زمان اجرا مصرف RAM
Puppeteer (راه‌اندازی مجدد مرورگر) 8 دقیقه و 23 ثانیه ~1.2 GB حداکثر
Playwright (راه‌اندازی مجدد مرورگر) 7 دقیقه و 54 ثانیه ~1.1 GB حداکثر
Playwright (استخر زمینه‌ها) 4 دقیقه و 12 ثانیه ~800 MB ثابت

Playwright با استخر زمینه‌ها تقریباً دو برابر سریع‌تر است به دلیل عدم وجود هزینه‌های راه‌اندازی مرورگر. این امر در هنگام پارس کردن هزاران صفحه حیاتی است.

نتیجه‌گیری

ادغام پروکسی با Puppeteer و Playwright یک عمل استاندارد برای وب‌اسکرپینگ، تست و اتوماسیون است. Puppeteer سادگی و اکوسیستم وسیع را ارائه می‌دهد، در حالی که Playwright API مدرن و عملکرد بهتری را هنگام کار با چندین پروکسی از طریق زمینه‌های مرورگر فراهم می‌کند.

نکات کلیدی که ما بررسی کردیم:

  • تنظیم پایه پروکسی‌های HTTP، HTTPS و SOCKS5 در هر دو فریم‌ورک
  • احراز هویت با نام کاربری و رمز عبور
  • چرخش پروکسی برای پارسینگ مقیاس‌پذیر
  • پردازش خطاها و اعتبارسنجی پروکسی قبل از استفاده
  • تنظیم موقعیت جغرافیایی و اثر انگشت برای دور زدن سیستم‌های ضد ربات
  • مقایسه عملکرد روش‌های مختلف

برای راه‌حل‌های تولید، توصیه می‌شود پروکسی‌های با کیفیت را با تنظیم مناسب اثر انگشت، پردازش خطاها و نظارت ترکیب کنید. این امر عملکرد پایدار پارسر را حتی در سایت‌های محافظت شده تضمین می‌کند.

اگر قصد دارید سایت‌های تجاری، بازارها یا پلتفرم‌های تبلیغاتی را پارس کنید، توصیه می‌شود از پروکسی‌های مسکونی استفاده کنید — آن‌ها حداکثر ناشناسی و حداقل خطر مسدود شدن را به دلیل آدرس‌های IP واقعی کاربران خانگی فراهم می‌کنند.

```