مقدمه
در این مقاله میآموزید چگونه در فرایند وب اسکریپینگ با NodeJS درخواستهای POST ارسال کنید. هدف عملی است: ارسال JSON، ارسال فرم (application/x-www-form-urlencoded)، مدیریت هدرها، و نکات پایداری و ضدمسدودسازی (rate limiting، پراکسی، user-agent و session). مثالها با کتابخانههای محبوب NodeJS یعنی Got، SuperAgent، node-fetch، Axios و request-promise آمدهاند و برای هر مثال توضیح ورودی، خروجی و گامهای اجرایی داده شده است.
روشها و مقایسه سریع
- Got: مدرن، پشتیبانی از stream، retry داخلی و مناسب برای اسکریپ کردن در مقیاس متوسط.
- SuperAgent: زنجیرهپذیری راحت برای ساخت درخواست، API خوانا.
- node-fetch: مشابه fetch در مرورگر، سبک و ساده.
- Axios: رابط ساده، تبدیل خودکار JSON و پشتیبانی از cancel/timeout.
- request-promise: قدیمی و در بسیاری از پروژهها منسوخ شده؛ اگرچه API سادهای دارد اما توصیه میشود به گزینههای دیگر مهاجرت کنید.
ارسال JSON — اصول کلی
یک درخواست POST که JSON ارسال میکند معمولاً شامل هدر Content-Type: application/json و بدنهٔ رشتهشدهٔ JSON است. برخی کتابخانهها (مثلاً Got با پارامتر json یا Axios) این تبدیل را خودکار انجام میدهند.
الگوی کلی:
- تنظیم URL مقصد.
- ساخت آرایه/آبجکت دادهای که ارسال میشود.
- تنظیم هدرها (Authorization، Content-Type، User-Agent و غیره).
- پرداختن به پاسخ و مدیریت خطا.
مثال: Got (JSON)
import got from 'got';
const url = 'https://httpbin.org/post';
const data = { key: 'value' };
const options = {
json: data,
// got بهصورت خودکار Content-Type را application/json میگذارد
timeout: 5000,
};
got.post(url, options)
.then(response => {
console.log(response.body);
})
.catch(error => {
console.error(error);
});توضیح:
- ورودی: url و data (آبجکت جاوااسکریپت).
- خروجی: response.body که در Got معمولاً رشته یا آبجکت بسته به تنظیمات است.
- خطبهخط: json: data باعث میشود کتابخانه آبجکت را stringify کرده و Header مربوطه را تنظیم کند. پارامتر timeout برای جلوگیری از قفلشدن اسکریپ استفاده میشود.
مثال: SuperAgent (JSON)
const request = require('superagent');
const url = 'https://httpbin.org/post';
const body = { key: 'value' };
request.post(url)
.send(body) // SuperAgent بهطور پیشفرض JSON را stringify میکند
.set('Content-Type', 'application/json')
.then(response => console.log(response.body))
.catch(err => console.error(err));توضیح:
- ورودی: body؛ SuperAgent آن را stringify میکند.
- خروجی: response.body که معمولاً JSON پارسشده است.
- نکته: برای APIهای نیازمند توکن، هدر Authorization را با .set اضافه کنید.
مثال: node-fetch (JSON)
import fetch from 'node-fetch';
const url = 'https://httpbin.org/post';
const data = { key: 'value' };
const options = {
method: 'POST',
body: JSON.stringify(data),
headers: { 'Content-Type': 'application/json' },
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));توضیح:
- در node-fetch باید خودتان JSON.stringify و هدر Content-Type را تنظیم کنید.
- خروجی: با res.json() پاسخ را به آبجکت تبدیل میکنیم.
مثال: Axios (JSON)
const axios = require('axios');
const uri = 'https://httpbin.org/post';
const data = { key: 'value' };
const options = { headers: { 'Content-Type': 'application/json' } };
axios.post(uri, data, options)
.then(response => console.log(response.data))
.catch(error => console.error(error));توضیح:
- Axios دادهٔ آبجکتی را stringify میکند و در ادامه response.data حاوی پاسخ پارسشده است.
- میتوانید timeout و maxContentLength را در options تنظیم کنید.
مثال: request-promise (JSON) — با احتیاط
const request = require('request-promise');
const options = {
method: 'POST',
uri: 'https://httpbin.org/post',
body: { key: 'value' },
json: true, // اگر true باشد، کتابخانه body را stringify میکند و پاسخ را پارس میکند
headers: { 'Content-Type': 'application/json' }
};
request(options)
.then(response => console.log(response))
.catch(err => console.error(err));توضیح:
- توجه: request-promise در پروژههای جدید کمتر توصیه میشود؛ بهتر است از Axios یا Got استفاده کنید.
- پارامتر json: true باعث ارسال و دریافت خودکار JSON میشود.
ارسال فرم (application/x-www-form-urlencoded)
برای ارسال فرم معمولاً باید بدنه را به شکل query string بسازید (مثل key=value) و هدر Content-Type: application/x-www-form-urlencoded تنظیم شود. برخی کتابخانهها مثل Got پارامتر form دارند که این کار را ساده میکنند.
مثال: Got (Form)
import got from 'got';
const url = 'https://httpbin.org/post';
const data = { key: 'value' };
const options = { form: data };
got.post(url, options)
.then(res => console.log(res.body))
.catch(err => console.error(err));توضیح:
- form: data باعث میشود Got بدنه را به رشتهٔ فرم تبدیل کند و Content-Type را ست کند.
مثال: SuperAgent (Form)
const querystring = require('querystring');
const request = require('superagent');
const url = 'https://httpbin.org/post';
const data = { key: 'value' };
const body = querystring.stringify(data);
request.post(url)
.send(body)
.set('Content-Type', 'application/x-www-form-urlencoded')
.then(res => console.log(res.body))
.catch(err => console.error(err));توضیح:
- اینجا querystring.stringify داده را به key=value تبدیل میکند و سپس با .send فرستاده میشود.
مثال: node-fetch (Form)
import fetch from 'node-fetch';
import querystring from 'querystring';
const url = 'https://httpbin.org/post';
const data = { key: 'value' };
const options = {
method: 'POST',
body: querystring.stringify(data),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
};
fetch(url, options)
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err));مثال: Axios (Form)
const axios = require('axios');
const uri = 'https://httpbin.org/post';
const data = 'key1=value1&key2=value2';
const options = { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } };
axios.post(uri, data, options)
.then(res => console.log(res.data))
.catch(err => console.error(err));مثال: request-promise (Form)
const request = require('request-promise');
const querystring = require('querystring');
const options = {
method: 'POST',
uri: 'https://httpbin.org/post',
body: querystring.stringify({ key: 'value' }),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
};
request(options)
.then(res => console.log(res))
.catch(err => console.error(err));نکات عملی و بهترین روشها برای وب اسکریپینگ
- مدیریت خطا: همیشه try/catch یا .catch داشته باشید و برای خطاهای موقتی از مکانیزم retry استفاده کنید.
- محدودسازی سرعت: برای جلوگیری از بلاک شدن از تاخیر (delay) بین درخواستها و الگوریتم backoff استفاده کنید.
- هدرها: حداقل User-Agent و در صورت نیاز Accept و Authorization را درست تنظیم کنید.
- پراکسی و چرخش آیپی: در اسکریپ کردن مقیاس بزرگ، از پراکسیهای چرخشی استفاده کنید تا ریسک مسدودسازی کاهش یابد.
- جلسه و کوکیها: برای صفحات نیازمند جلسه، کوکیها را نگه دارید (Axios و Got امکان مدیریت cookie jar با پلاگین/ماژول را دارند).
- ارسال دادههای بزرگ: برای فایلها یا بدنههای بزرگ از استریمها استفاده کنید (Got و Axios قابلیت stream دارند).
- امنیت: هرگز توکنها یا اطلاعات حساس را در لاگ تولید شده ننویسید.
همزمانی و عملکرد
برای افزایش throughput در اسکریپ کردن، میتوانید از همزمانی محدود استفاده کنید: مجموعهای از Promises را با محدودیت همزمانی اجرا کنید (مثلاً p-limit یا یک صف ساده). اجرای بیرویهٔ همزمان باعث سرریز منابع یا trigger شدن جلوگیری از طرف سرور میشود.
خطاهای متداول و راه حل
- خطای timeout: Timeoutهای منطقی تعریف کنید و در صورت نیاز دوباره تلاش (retry) با backoff افزایشدهنده انجام دهید.
- پاسخهای غیرمنتظره (HTML به جای JSON): بررسی کنید Content-Type پاسخ و قبل از پارس کردن آن را اعتبارسنجی کنید.
- مسدودسازی IP: پراکسی، تغییر نرخ درخواست یا استفاده از سرورهای توزیعشده را بررسی کنید.
جمعبندی
ارسال POST در جریان وب اسکریپینگ با NodeJS بسیار رایج است و کتابخانههای متعددی این کار را ساده میکنند. برای مقادیر JSON از پارامترهای خودکار (مثل json در Got یا Axios) استفاده کنید، برای فرمها از تبدیل به query string و تنظیم هدر مناسب بهره ببرید، و همیشه به مسائل پایداری و امنیت توجه کنید.
توصیه نهایی: برای پروژههای جدید از کتابخانههای مدرن مثل Got یا Axios استفاده کنید و request-promise را تنها در پروژههای legacy نگه دارید. هنگام اسکریپ کردن در مقیاس، مدیریت پراکسی، کوکی و نرخ درخواست را در اولویت قرار دهید تا اسکرپ پایدار بماند.





