

اگر میخواهید درخواستهای وباسکریپ خود را از آیپی محلی جدا کنید، از فیلترها و بلوکها فرار کنید یا به محتوای جغرافیایی محدود دسترسی یابید، داشتن یک پروکسی شخصی بسیار مفید است. در این مقاله به صورت عملی و فنی گامبهگام میسازیم، استقرار میکنیم، شبکهای از پراکسیها میسازیم و قابلیتهای سفارشیسازی Node-Unblocker را برای بهبود عملیات وب اسکریپینگ بررسی میکنیم.
پس از خواندن این مقاله باید بتوانید یک سرور Node-Unblocker را راهاندازی کنید، آن را در محیط ابری مستقر کنید، یک شبکه پراکسی بسازید، و با استفاده از میانافزارها (middlewares) رفتار درخواستها و پاسخها را کنترل و بهینه کنید.
Node-Unblocker یک کتابخانهٔ Node.js است که روی Express سوار میشود و وظیفهٔ proxying و بازنویسی صفحات از راه دور را بر عهده دارد. این ابزار برای مواردی مثل:
مناسب است. Node-Unblocker بهصورت REST عمل میکند: شما آدرس هدف را به انتهای /proxy/ اضافه میکنید و سرور محتوای هدف را با استفاده از آیپی سرور دریافت و بهصورت استریم به کلاینت بازمیگرداند.
اگر با Express آشنا هستید، راهاندازی سرور سریع است. ابتدا وابستگیها را نصب میکنیم.
npm init -y
npm install unblocker express
نکته: نسخهٔ Node را در محیط تولید مشخص کنید (مثلاً در package.json) تا رفتارهای متفاوت نسخهها مشکلات بعدی ایجاد نکنند.
در پوشهٔ پروژه یک فایل app.js بسازید. مثال زیر نسخهٔ مرتب و مدرن با const است:
// app.js
const express = require('express');
const Unblocker = require('unblocker');
const app = express();
// ایجاد نمونهٔ Unblocker و تعیین پیششمارهٔ مسیر proxy
const unblocker = new Unblocker({
prefix: '/proxy/' // درخواستها به شکل /proxy/https://target.example.com ارسال میشوند
});
// فعالسازی middleware پروکسی
app.use(unblocker);
// مدیریت WebSocket یا تغییر پروتکل (برای مثال در استفاده از upgrade)
app.listen(process.env.PORT || 8080).on('upgrade', unblocker.onUpgrade);
console.log('Node Unblocker Server Running On Port:', process.env.PORT || 8080);
شرح مختصر نقش قطعات مهم:
برای اجرای محلی:
node app.js
و مثال تست با curl (در ترمینال):
curl http://localhost:8080/proxy/https://www.example.com
در این حالت سرور هدف، آیپیِ ماشین میزبان Node-Unblocker را میبیند. اگر روی لوکال اجرا میکنید، تغییری در آیپی رخ نمیدهد؛ برای تغییر آیپی باید سرور را در هاست ریموت مستقر کنید.
برای استقرار در سرویسهایی مانند Heroku باید package.json را بهدرستی تنظیم کنید تا پلتفرم بداند چگونه برنامه را اجرا کند. مثال:
{
"name": "proxy-server",
"version": "1.0.0",
"main": "app.js",
"private": true,
"engines": {
"node": "16.x"
},
"dependencies": {
"express": "^4.17.1",
"unblocker": "^2.3.0"
},
"scripts": {
"start": "node app.js"
}
}
یک .gitignore پایه هم بسازید تا node_modules، لاگها و فایلهای محیطی را خارج کنید:
# Dependencies
node_modules
# yarn error logs
yarn-error.log
# Environment variables
.env*
!.env*.example
# Code coverage
coverage
دستورهای پایه برای گیت و استقرار در Heroku (یا مشابه):
git init
heroku git:remote -a your-app-name
git add .
git commit -am "first deploy"
git push heroku master
نکتهٔ مهم: سرویسهایی مثل Heroku یا هر VPS، آیپی عمومی را ارائه میدهند که سرور هدف آن را میبیند. برخی هاستها آیپی متغیر دارند یا محدودیتهای رایگان اعمال میکنند؛ قبل از مقیاسدهی این موارد را بررسی کنید.
برای شکستِ نرخمحدودکنندهها و توزیع ترافیک، میتوانید چندین سرور Node-Unblocker در مناطق جغرافیایی مختلف مستقر کنید و در کلاینتها هر درخواست را از یک سرور تصادفی بفرستید.
دو روش اصلی برای استفاده از سرورهای Unblocker در کلاینتها وجود دارد:
این مثال مشابه ورودی اولیه است؛ ما فهرستی از آدرسهای سرورهای Unblocker را میسازیم و آنها را بهصورت چرخان برای هر درخواست انتخاب میکنیم.
import requests
from itertools import cycle
# فهرست سرورهای Node-Unblocker (میتواند آدرسهای کامل پروکسی یا آدرسهای /proxy/ باشد)
proxies_list = [
"http://100.200.30.30:8080",
"http://100.200.30.31:8080",
"http://100.200.30.32:8080",
]
proxy_cycle = cycle(proxies_list)
target = 'https://www.example.com'
for i in range(10):
proxy = next(proxy_cycle)
print('using proxy:', proxy)
# اگر سرور شما بهعنوان HTTP proxy کار میکند:
proxies = { 'http': proxy, 'https': proxy }
try:
r = requests.get(target, proxies=proxies, timeout=15)
print('status', r.status_code)
except requests.RequestException as e:
print('request failed:', e)
توضیحات ورودیها/خروجیها و نکات:
قابلیت قوی Node-Unblocker استفاده از میانافزارها برای دستکاری درخواستها و پاسخها است. این موضوع بهویژه در وب اسکریپینگ با اهداف زیر مفید است:
یک میانافزار ساده که هدر user-agent را برای هر درخواست تنظیم میکند:
// در app.js
function setUserAgent(data) {
// data.url و data.headers در شی داده ورودی موجود هستند
data.headers['user-agent'] = 'Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148';
}
const unblocker = new Unblocker({
prefix: '/proxy/',
requestMiddleware: [ setUserAgent ]
});
شرح:
function setUserAgentForGoogle(data) {
if (/^https?:\/\/([\w.-]+\.)?google\.com\//i.test(data.url)) {
data.headers['user-agent'] = 'Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148';
}
}
گاهی لازم است بخشهایی از HTML پاسخ را اصلاح یا حذف کنیم (مثلاً اسکریپهایی که BrowserCheck اجرا میکنند). برای پاسخهای متنی بهتر است از استریم استفاده کنیم تا حافظهٔ سرور بیرون نریزد.
const { Transform } = require('stream');
function replaceSnippet(config) {
return function(data) {
// data.contentType و data.stream در شی داده موجود است
if (config.processContentTypes.includes(data.contentType)) {
data.stream = data.stream.pipe(new Transform({
decodeStrings: false,
transform(chunk, encoding, next) {
const updated = chunk.toString().replace(config.searchFor, config.replaceWith);
this.push(updated, 'utf8');
next();
}
}));
}
};
}
const unblockerWithReplace = new Unblocker({
prefix: '/proxy/',
responseMiddleware: [ replaceSnippet({
processContentTypes: [ 'text/html' ],
searchFor: /