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

رندرینگ جاوااسکریپت از طریق پروکسی: نحوه جلوگیری از مسدودیت و خطاها

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

📅۱۳ آذر ۱۴۰۴
```html

رندرینگ JavaScript از طریق پروکسی: چگونه از مسدودیت‌ها و خطاها اجتناب کنیم

هنگامی که شما سایت‌های وبی را تجزیه می‌کنید که محتوای خود را از طریق JavaScript بارگذاری می‌کنند، درخواست‌های ساده HTTP ناکارآمد می‌شوند. اگر حفاظت از ربات‌ها و محدودیت‌های جغرافیایی را به این اضافه کنید، کار چندین برابر پیچیده‌تر می‌شود. پروکسی‌ها بخشی از مشکلات را حل می‌کنند، اما نیاز به تنظیم صحیح دارند.

چرا رندرینگ JavaScript به پروکسی نیاز دارد

سایت‌های مدرن اغلب از چارچوب‌هایی مانند React، Vue یا Angular استفاده می‌کنند که محتوا را در سمت کلاینت بارگذاری می‌کنند. هنگامی که شما یک درخواست ساده GET ارسال می‌کنید، HTML خالی با برچسب <div id="root"></div> دریافت می‌کنید، نه محتوای آماده.

مشکلاتی که پروکسی‌ها حل می‌کنند:

  • مسدودیت‌های جغرافیایی. سایت‌ها دسترسی را بر اساس کشورها محدود می‌کنند. پروکسی‌های دارای IP از منطقه مورد نظر این محدودیت‌ها را دور می‌زنند.
  • حفاظت از ربات‌ها. Cloudflare، hCaptcha و سیستم‌های مشابه درخواست‌های خودکار را مسدود می‌کنند. پروکسی‌های مسکونی مانند کاربران عادی به نظر می‌رسند و بهتر از بررسی‌ها عبور می‌کنند.
  • محدودیت نرخ. سرور می‌تواند یک IP را پس از درخواست‌های متعدد مسدود کند. پروکسی‌ها ترافیک را توزیع می‌کنند و از مسدودیت‌ها اجتناب می‌کنند.
  • ناشناسی. IP واقعی شما را هنگام تجزیه‌گری پنهان می‌کنند.

مرورگرهای بدون رابط و پروکسی: مبانی

برای رندرینگ JavaScript از مرورگرهای بدون رابط استفاده می‌کنند — Chromium بدون رابط گرافیکی. گزینه‌های محبوب:

  • Puppeteer — کتابخانه Node.js برای کنترل Chrome/Chromium.
  • Playwright — جایگزین چند مرورگری، از Chrome، Firefox، Safari پشتیبانی می‌کند.
  • Selenium — انتخاب کلاسیک، با مرورگرهای مختلف کار می‌کند.

همه آن‌ها از طریق پارامترهای راه‌اندازی مرورگر یا گزینه‌های اتصال از پروکسی پشتیبانی می‌کنند.

تنظیم عملی

Puppeteer با پروکسی

مثال پایه‌ای برای اتصال پروکسی به Puppeteer:

const puppeteer = require('puppeteer');

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

  const page = await browser.newPage();
  await page.goto('https://example.com');
  
  const content = await page.content();
  console.log(content);
  
  await browser.close();
})();

اگر پروکسی نیاز به احراز هویت دارد:

const puppeteer = require('puppeteer');

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

  const page = await browser.newPage();
  
  // تنظیم اعتبارات برای پروکسی
  await page.authenticate({
    username: 'user',
    password: 'pass'
  });
  
  await page.goto('https://example.com');
  const content = await page.content();
  
  await browser.close();
})();

Playwright با پروکسی

در Playwright پروکسی از طریق زمینه مرورگر تنظیم می‌شود:

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

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

  const context = await browser.newContext();
  const page = await context.newPage();
  
  await page.goto('https://example.com');
  const content = await page.content();
  
  await browser.close();
})();

چرخش پروکسی برای درخواست‌های متعدد

برای تجزیه‌گری در مقیاس بزرگ نیاز به چرخش پروکسی دارید. در اینجا مثال ساده‌ای با آرایه:

const puppeteer = require('puppeteer');

const proxies = [
  'http://proxy1.com:8080',
  'http://proxy2.com:8080',
  'http://proxy3.com:8080'
];

let proxyIndex = 0;

async function getPageWithProxy(url) {
  const currentProxy = proxies[proxyIndex % proxies.length];
  proxyIndex++;
  
  const browser = await puppeteer.launch({
    args: [`--proxy-server=${currentProxy}`]
  });
  
  const page = await browser.newPage();
  await page.goto(url);
  const content = await page.content();
  
  await browser.close();
  return content;
}

// استفاده
(async () => {
  const urls = ['https://example.com/1', 'https://example.com/2'];
  for (const url of urls) {
    const content = await getPageWithProxy(url);
    console.log('Parsed:', url);
  }
})();

خطاهای معمول و راه‌حل‌ها

خطا دلیل راه‌حل
ERR_TUNNEL_CONNECTION_FAILED پروکسی در دسترس نیست یا اعتبارات نادرست IP:port پروکسی، نام کاربری/رمز عبور را بررسی کنید. از طریق curl تست کنید
Timeout هنگام بارگذاری پروکسی کند یا سایت درخواست را مسدود می‌کند timeout را افزایش دهید، User-Agent اضافه کنید، از پروکسی‌های مسکونی استفاده کنید
403 Forbidden سایت ربات را تشخیص داده است header‌های واقع‌گرایانه اضافه کنید، از پروکسی‌های مسکونی استفاده کنید، تاخیر بین درخواست‌ها اضافه کنید
CAPTCHA در هر درخواست سایت User-Agent یکسان را می‌بیند User-Agent را چرخش دهید، برای هر مرورگر از پروکسی‌های مختلف استفاده کنید

اضافه کردن header‌های واقع‌گرایانه

const page = await browser.newPage();

await page.setUserAgent(
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
);

await page.setExtraHTTPHeaders({
  'Accept-Language': 'en-US,en;q=0.9',
  'Accept': 'text/html,application/xhtml+xml',
  'Referer': 'https://google.com'
});

await page.goto('https://example.com');

بهینه‌سازی کارایی

غیرفعال کردن منابع غیرضروری

بارگذاری تصاویر و سبک‌ها تجزیه‌گری را کند می‌کند. اگر فقط به متن نیاز دارید:

const page = await browser.newPage();

// بارگذاری تصاویر و سبک‌ها را مسدود کنید
await page.on('request', (request) => {
  const resourceType = request.resourceType();
  if (['image', 'stylesheet', 'font', 'media'].includes(resourceType)) {
    request.abort();
  } else {
    request.continue();
  }
});

await page.goto('https://example.com');

استفاده از استخر مرورگر

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

const puppeteer = require('puppeteer');

let browser;
const maxPages = 5;
let activePage = 0;

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

async function parsePage(url) {
  const page = await browser.newPage();
  try {
    await page.goto(url);
    const content = await page.content();
    return content;
  } finally {
    await page.close();
  }
}

// استفاده
(async () => {
  await initBrowser();
  const urls = ['url1', 'url2', 'url3'];
  
  for (const url of urls) {
    await parsePage(url);
  }
  
  await browser.close();
})();

ابزارها و کتابخانه‌ها

  • Puppeteer Extra — افزونه Puppeteer با پشتیبانی افزونه برای دور زدن حفاظت از ربات‌ها.
  • Cheerio — کتابخانه سبک برای تجزیه HTML پس از رندرینگ مرورگر.
  • Axios + Proxy Agent — برای درخواست‌های ساده از طریق پروکسی بدون مرورگر.
  • Scrapy — چارچوب Python با پشتیبانی داخلی برای پروکسی و تجزیه‌گری توزیع‌شده.

مهم: هنگام کار با پروکسی، مطمئن شوید که شرایط استفاده سایت هدف را رعایت می‌کنید و robots.txt را نقض نمی‌کنید. تجزیه‌گری باید اخلاقی باشد و سرورها را بیش‌تر بار نکند.

نتیجه‌گیری

رندرینگ JavaScript از طریق پروکسی ابزار قدرتمندی برای خودکارسازی تجزیه‌گری است، اما نیاز به توجه به جزئیات دارد. تنظیم صحیح مرورگر، چرخش پروکسی، header‌های واقع‌گرایانه و بهینه‌سازی کارایی کلیدهای کار قابل‌اعتماد هستند.

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

```