مقدمه
در این مقاله عملی یاد میگیریم چگونه در پروژههای Node.js پراکسیها را برای وب اسکریپینگ تنظیم و مدیریت کنیم. هدف این راهنما ارائهٔ روشهای رایج استفاده از پراکسی با کتابخانههایی مثل Node-Fetch، Got، Request-Promise، Axios و SuperAgent و همچنین معرفی سه فرمت پراکسی پرکاربرد: لیست IPها، درگاه (gateway) و API پراکسی است. پس از خواندن این راهنما شما مثالهای کد عملی، نکات امنیتی، و الگوهای پایدار برای چرخش پراکسی و مدیریت خطا خواهید داشت.
پراکسی در کتابخانههای معمول Node.js — ایده کلی
ایدهٔ کلی: ارسال درخواست HTTP از طریق یک سرور واسط (پراکسی) تا IP منبع تغییر کند یا انتخابهای بیشتری برای مدیریت اتصال داشته باشیم. در عمل سه مدل فنی داریم:
- ایجاد یک agent که اتصال را به پراکسی هدایت کند (مثلاً https-proxy-agent یا hpagent)
- قرار دادن رشتهٔ پراکسی (proxy URL) در گزینههای درخواست
- ارسال URL هدف به یک API پراکسی که خود پاسخ را برمیگرداند
در ادامه برای هر کتابخانه روش کار، مثال و توضیح ورودی/خروجی را میبینیم.
Node-Fetch
مسئله: Node-Fetch به تنهایی پراکسی را پشتیبانی نمیکند؛ باید یک agent بسازیم. رویکرد معمول نصب و استفاده از https-proxy-agent یا مشابه آن است.
مثال کد و توضیح خطبهخط:
import fetch from 'node-fetch'
import HttpProxyAgent from 'https-proxy-agent'
;(async () => {
// ورودی: proxyUrl رشته ای مثل 'http://user:pass@proxy.host:8080'
const proxyUrl = 'http://USERNAME:PASSWORD@proxy.example.com:8080'
// ایجاد agent که fetch از آن استفاده می کند
const proxyAgent = new HttpProxyAgent(proxyUrl)
try {
// خروجی: response شیٔ پاسخ HTTP است؛ body را می توان text یا json خواند
const response = await fetch('https://httpbin.org/ip', { agent: proxyAgent })
const body = await response.text()
console.log(body)
} catch (error) {
console.error('error', error)
}
})()توضیح: ورودی اصلی proxyUrl است. agent از آن برای بازنویسی کانال TCP/TLS استفاده میکند. در صورت درخواست http به جای https باید از کلاس مربوط به HttpProxyAgent مناسب استفاده کنید. نکتهٔ عملی: همیشه timeout روی fetch تنظیم کنید و خطاها را catch کنید.
Got
Got مدرن و انعطافپذیر است و با hpagent یا https-proxy-agent بهخوبی کار میکند. ایده: به گزینهها یک شی agent بدهید که خصوصیت https را به نمونهٔ HttpsProxyAgent اختصاص داده باشد.
import got from 'got'
import { HttpsProxyAgent } from 'hpagent'
;(async () => {
const proxyUrl = 'http://USERNAME:PASSWORD@proxy.example.com:8080'
const options = {
agent: {
https: new HttpsProxyAgent({ proxy: proxyUrl })
},
timeout: 10000
}
try {
const response = await got.get('https://httpbin.org/ip', options)
console.log(response.body)
} catch (error) {
console.error('error', error)
}
})()توضیح: options ورودی است؛ خروجی response.body است. Got از agent برای همهٔ درخواستهای https استفاده میکند. اگر نیاز به requestهای http دارید، گزینهٔ agent.http را هم ست کنید.
Request-Promise
این کتابخانه مستقیم از گزینهٔ proxy پشتیبانی میکند؛ کافیست رشتهٔ پراکسی را در options قرار دهید.
import request from 'request-promise'
;(async () => {
const options = {
method: 'GET',
url: 'https://httpbin.org/ip',
proxy: 'http://USERNAME:PASSWORD@proxy.example.com:8080',
timeout: 10000
}
try {
const response = await request(options)
console.log(response)
} catch (error) {
console.error('error', error)
}
})()ورودی: options شامل proxy. خروجی: محتوای پاسخ. ساده و مناسب برای استفاده سریع، اما کتابخانههای جدیدتر مثل Got معمولاً پایدارتر و قابلپیکربندیترند.
Axios
Axios از بعضی از انواع پروکسی پشتیبانی محدود دارد؛ اغلب از https-proxy-agent و ستکردن httpAgent یا httpsAgent استفاده میکنیم و پراکسی داخلی axios را غیر فعال میکنیم (proxy: false).
import axios from 'axios'
import HttpProxyAgent from 'https-proxy-agent'
;(async () => {
try {
const agent = new HttpProxyAgent('http://USERNAME:PASSWORD@proxy.example.com:8080')
const response = await axios.get('https://httpbin.org/ip', {
proxy: false, // غیرفعال کردن پردازش پراکسی داخلی
httpAgent: agent,
httpsAgent: agent,
timeout: 10000
})
console.log(response.data)
} catch (error) {
console.error('error', error)
}
})()توضیح: با این روش axios از agent برای ایجاد اتصال استفاده میکند. ورود/خروج مشابه است: agent ورودی، response.data خروجی.
SuperAgent
برای SuperAgent ابتدا باید افزونهٔ پراکسی را فعال کنید (مثل superagent-proxy). سپس از متد proxy استفاده میکنیم.
const request = require('superagent')
const addProxy = require('superagent-proxy')
addProxy(request)
;(async () => {
try {
const response = await request.get('https://httpbin.org/ip').proxy('http://USERNAME:PASSWORD@proxy.example.com:8080')
console.log(response.body)
} catch (error) {
console.error('error', error)
}
})()توضیح: پس از addProxy، متد proxy به request اضافه میشود. ورودی: URL و رشتهٔ پراکسی؛ خروجی: body پاسخ.
تأیید هویت پراکسی (Proxy Authentication)
سادهترین روش، قرار دادن USERNAME:PASSWORD در ابتدای رشتهٔ پراکسی است. مثالها در بالا همه همین الگو را نشان میدهند. نکات امنیتی:
- هرگز credentials را در ریپو کد نذارید؛ از متغیر محیطی یا secret manager استفاده کنید.
- در لاگها کل پروکسی را ننویسید تا رمز فاش نشود.
فرمتهای رایج پراکسی
سه روش رایج که باید بدانید:
- Rotating list: ارائهٔ لیستی از IPها و چرخش دستی در سمت کلاینت
- Proxy gateway: یک URL واحد که ارائهدهنده خودش rotation و pool را مدیریت میکند
- Proxy API: ارسال URL هدف به API و دریافت HTML آماده؛ مناسب زمانی که میخواهید ساده کار کنید
یک: چرخش در لیست پراکسی (Rotating IP list)
الگوی ساده: هر درخواست یک پراکسی تصادفی از لیست انتخاب میکند. مثال عملی:
import fetch from 'node-fetch'
import HttpsProxyAgent from 'https-proxy-agent'
;(async () => {
const proxyList = [
'http://user:pass@85.237.57.198:20000',
'http://user:pass@85.237.57.198:21000',
'http://user:pass@85.237.57.198:22000'
]
// انتخاب تصادفی
const randomProxy = proxyList[Math.floor(Math.random() * proxyList.length)]
const agent = new HttpsProxyAgent(randomProxy)
try {
const response = await fetch('https://httpbin.org/ip', { agent, timeout: 10000 })
const data = await response.json()
console.log(data)
} catch (error) {
console.error('error', error)
}
})()محدودیتها و بهترین روشها:
- در مقیاس، باید سلامت هر IP را مانیتور و امتیازدهی کنید؛ نمونه معیارها: نرخ خطا، زمان پاسخ، تعداد 403/429.
- برای حذف IPهای مشکلدار از روتور از یک صف یا دیتابیس استفاده کنید و مجدداً آنها را بعد از پنجرهٔ زمانی تست کنید.
- همیشه محدودیت concurrency را تنظیم کنید تا یک پراکسی دچار overload نشود.
دو: استفاده از درگاه پراکسی (Proxy Gateway)
ایده: فقط یک URL پراکسی برای تمام درخواستها دارید؛ ارائهدهنده خودش pool را مدیریت میکند. مزیت سادگی و کاهش مدیریت در سمت شما.
import got from 'got'
import { HttpsProxyAgent } from 'hpagent'
;(async () => {
const gateway = 'http://USERNAME:PASSWORD@zproxy.example.com:22225'
const options = { agent: { https: new HttpsProxyAgent({ proxy: gateway }) }, timeout: 10000 }
try {
const response = await got.get('https://httpbin.org/ip', options)
console.log(response.body)
} catch (error) {
console.error('error', error)
}
})()نکات: با این روش نیازی به مدیریت لیست و چرخش ندارید؛ اما تضمین کیفیت و هزینهٔ provider اهمیت پیدا میکند. گاهی provider ها قابلیتهایی مثل ناحیه جغرافیایی یا sticky sessions ارائه میدهند.
سه: استفاده از Proxy API
در این الگو شما URL هدف را به API میفرستید و پاسخ HTML را دریافت میکنید. این روش مناسب کم کردن پیچیدگی است، اما باید به محدودیتهای API و هزینهها توجه کنید.
import fetch from 'node-fetch'
;(async () => {
try {
const apiKey = process.env.SCRAPEOPS_API_KEY
const target = 'https://httpbin.org/ip'
const url = 'https://proxy.scrapeops.io/v1/?' + new URLSearchParams({ api_key: apiKey, url: target })
const response = await fetch(url, { timeout: 15000 })
const body = await response.text()
console.log(body)
} catch (error) {
console.error('error', error)
}
})()توضیح: ورودیها api key و url هدف هستند؛ خروجی HTML یا JSON که provider برمیگرداند. مزیت: provider معمولا rotation، مدیریت header و انواع نرخها را انجام میدهد.
نکات عملی، امنیت و بهینهسازی
- Timeout و Retry: از timeout معقول (مثلا 10ثانیه) و retry با backoff نمایی استفاده کنید تا حملات قیمتی یا صفهای طولانی را مدیریت کنید.
- محدودیت همزمانی: concurrency را برای هر پراکسی محدود کنید تا از بلاک شدن سریع جلوگیری شود.
- مونیتورینگ پراکسی: برای هر proxy یک متریک ذخیره کنید (خطا، latency، response codes) و بر اساس آن تصمیم بگیرید.
- امنیت کلیدها: api key و credentials را در متغیر محیطی/secret manager نگهدارید؛ از لاگگیری حساس جلوگیری کنید.
- اعتبار TLS: در صورت نیاز به بررسی گواهی، گزینهٔ verify را روشن نگه دارید؛ بعضی پراکسیها certificate rewriting انجام میدهند و لازم است آگاه باشید.
- اجتناب از over-parallelism: سرعتبالا ممکن است سرچشمهٔ الگوی blocking شود؛ توزیع درخواست و uncoupling taskها را در نظر بگیرید.
- انواع پراکسیها: SOCKS5 در موارد خاص بهتر است، اما کتابخانهها و agentها باید از آن پشتیبانی کنند.
- رعایت اخلاق و قانون: به robots.txt و قوانین سایت احترام بگذارید و از نرخهای منطقی استفاده کنید.
جمعبندی
پراکسی یکی از ابزارهای کلیدی برای پایدارسازی وب اسکریپینگ است. برای انتخاب روش مناسب، ابتدا نیاز خود را مشخص کنید: اگر نمیخواهید زیرساخت پراکسی را مدیریت کنید از gateway یا proxy API استفاده کنید؛ اگر کنترل کامل و امکان آنالیز هر IP را میخواهید از لیست پراکسی و چرخش دستی بهره ببرید. در همهٔ حالات از timeout، retry، مانیتورینگ و محافظت از credentials استفاده کنید تا اسکریپ شما پایدار و امن بماند.





