जब पार्सर या बॉट एक IP से प्रति मिनट सैकड़ों अनुरोध भेजता है, तो सर्वर जल्दी से दर सीमा (rate limit) लागू कर देता है, और उसके बाद - कैप्चा या बैन। समाधान - कार्यों की कतार है, जो अनुरोधों को श्रमिकों और प्रॉक्सी के बीच वितरित करती है। इस लेख में हम देखेंगे कि Celery, RQ और BullMQ में ऐसी वास्तुकला कैसे काम करती है, और प्रत्येक IP पते पर अनुरोधों की सीमा को सही तरीके से प्रबंधित कैसे किया जाए।
प्रॉक्सी के साथ काम करते समय कार्यों की कतार की आवश्यकता क्यों है
यदि कार्य - Wildberries से 50,000 उत्पाद कार्ड को पार्स करना या Instagram के 10,000 खातों की स्थिति की जांच करना है, तो अनुरोधों का अनुक्रमिक निष्पादन घंटों लेगा, और बिना नियंत्रण के समानांतर निष्पादन जल्दी से IP पर बैन लगवा देगा। कार्यों की कतार (task queue) दोनों समस्याओं का समाधान करती है: यह बड़े कार्यभार को छोटे कार्यों में विभाजित करती है, उन्हें कई श्रमिकों के बीच वितरित करती है और प्रत्येक श्रमिक के लिए एक अलग प्रॉक्सी को संलग्न करने की अनुमति देती है।
वास्तुकला आमतौर पर इस प्रकार होती है: संदेश ब्रोकर (Redis या RabbitMQ) कार्यों की कतार को संग्रहीत करता है, श्रमिक कतार से कार्य लेते हैं और उन्हें निष्पादित करते हैं, प्रत्येक श्रमिक अपनी प्रॉक्सी का उपयोग करता है या पूल से प्रॉक्सी को घुमाता है। यह प्रत्येक IP पर लोड को सुरक्षित सीमाओं में रखने की अनुमति देता है, भले ही कुल अनुरोधों की मात्रा विशाल हो।
इस दृष्टिकोण का उपयोग केवल पार्सर के डेवलपर्स द्वारा नहीं किया जाता है, बल्कि उन टीमों द्वारा भी किया जाता है जो Facebook Ads के विज्ञापन खातों की जांच को स्वचालित करती हैं, Ozon पर कीमतों की निगरानी करती हैं या एक साथ दर्जनों वेबसाइटों से डेटा एकत्र करती हैं। कतार और IP के अनुसार सही वितरण के बिना, ऐसी कोई भी प्रणाली पहले ही दिन में ब्लॉक होने के लिए अभिशप्त है।
एक IP पर अनुरोधों की सीमा की समस्या
अधिकांश वेबसाइटों और API में अत्यधिक लोड से सुरक्षा होती है। यह विभिन्न रूपों में प्रकट हो सकती है: सर्वर HTTP 429 (Too Many Requests) लौटाता है, कैप्चा दिखाता है, IP को 10-60 मिनट के लिए अस्थायी रूप से बैन करता है या इसे स्थायी रूप से काले सूची में डालता है। विभिन्न प्लेटफार्मों पर सीमाएँ बहुत भिन्न होती हैं - उदाहरण के लिए, Wildberries API एक पते से प्रति सेकंड सीमित संख्या में अनुरोधों को स्वीकार करता है, जबकि Instagram संदिग्ध गतिविधि पर पहले 15-20 लगातार क्रियाओं के बाद प्रतिक्रिया करता है।
कतार बनाने में मुख्य गलती - सभी श्रमिकों को एक ही IP के माध्यम से चलाना है। भले ही कार्य 20 श्रमिकों के बीच वितरित किए गए हों, लेकिन यदि वे सभी एक प्रॉक्सी का उपयोग करते हैं या इसे बिल्कुल भी उपयोग नहीं करते हैं, तो इस IP पर सीमा उतनी ही तेजी से लागू होगी जितनी कि अनुक्रमिक निष्पादन के दौरान। इसलिए श्रमिकों की संख्या को प्रॉक्सी के पूल में उपलब्ध IP पते की संख्या के साथ संबंधित होना चाहिए।
एक डोमेन पर उच्च अनुरोध आवृत्ति वाले कार्यों के लिए डेटा सेंटर प्रॉक्सी का उपयोग करना बेहतर है - वे कम विलंबता प्रदान करते हैं और बड़े पैमाने पर समानांतर पार्सिंग के लिए उपयुक्त होते हैं, जहां गति महत्वपूर्ण होती है, न कि सामान्य उपयोगकर्ता के रूप में छिपना। यदि लक्ष्य - मार्केटप्लेस या सोशल मीडिया के एंटी-बॉट सिस्टम जैसी अधिक कठोर सुरक्षा को बायपास करना है, तो ऐसे IP की आवश्यकता होती है जो सामान्य उपयोगकर्ताओं के समान हों, अर्थात् आवासीय या मोबाइल।
Celery: वास्तुकला और कोड में प्रॉक्सी का रोटेशन
Celery - Python पारिस्थितिकी तंत्र में सबसे परिपक्व और लोकप्रिय कार्यों की कतार है। यह ब्रोकर (अधिकतर Redis या RabbitMQ) के ऊपर काम करती है और प्रतिस्पर्धा, पुनः प्रयासों और कार्यों की प्राथमिकताओं के लचीले कॉन्फ़िगरेशन का समर्थन करती है। प्रॉक्सी के रोटेशन के लिए, IP का पूल Redis में संग्रहीत करना और कतार में कार्य डालते समय प्रत्येक कार्य को प्रॉक्सी आवंटित करना सुविधाजनक है।
from celery import Celery
import requests
import redis
import random
app = Celery('tasks', broker='redis://localhost:6379/0')
redis_client = redis.Redis(host='localhost', port=6379, db=1)
PROXY_POOL = [
"http://user:[email protected]:8000",
"http://user:[email protected]:8000",
"http://user:[email protected]:8000",
]
def get_proxy():
# Redis के माध्यम से राउंड-रॉबिन, ताकि एक IP पर न मारें
idx = redis_client.incr("proxy_cursor") % len(PROXY_POOL)
return PROXY_POOL[idx]
@app.task(bind=True, max_retries=3, default_retry_delay=30)
def fetch_url(self, url):
proxy = get_proxy()
try:
response = requests.get(
url,
proxies={"http": proxy, "https": proxy},
timeout=15
)
if response.status_code == 429:
raise self.retry(exc=Exception("Rate limited"))
return response.status_code
except requests.exceptions.RequestException as exc:
raise self.retry(exc=exc)
मुख्य बिंदु - get_proxy() फ़ंक्शन, जो Redis काउंटर के माध्यम से पूल से अगली प्रॉक्सी को घुमाता है। यह सुनिश्चित करता है कि लोड सभी IP के बीच समान रूप से वितरित हो, न कि एक पर केंद्रित हो। max_retries पैरामीटर और कोड 429 की हैंडलिंग कार्य को स्वचालित रूप से दूसरे प्रॉक्सी के साथ पुनः भेजने की अनुमति देती है, यदि वर्तमान IP को सीमा मिल गई है।
Celery पर श्रमिकों के स्तर पर प्रतिस्पर्धा को नियंत्रित करने के लिए, एक श्रमिक को प्रारंभ करते समय --concurrency पैरामीटर के माध्यम से एक साथ कार्यों की संख्या को सीमित करना संभव है, और विभिन्न प्राथमिकताओं के साथ कतारों के माध्यम से (उदाहरण के लिए, धीमे कार्यों के लिए एक अलग कतार जिसमें कठोर दर सीमा है)।
RQ (Redis Queue): एक सरल विकल्प
RQ - Celery की तुलना में एक हल्का पुस्तकालय है, जिसमें RabbitMQ ब्रोकर नहीं है और न्यूनतम कॉन्फ़िगरेशन है। यह तब उपयुक्त है जब प्रोजेक्ट छोटा हो और जटिल कार्यों की रूटिंग की आवश्यकता न हो, बल्कि केवल श्रमिकों के साथ एक कतार और कार्य के लिए प्रॉक्सी को संलग्न करने की आवश्यकता हो।
from redis import Redis
from rq import Queue
import requests
import itertools
redis_conn = Redis()
q = Queue(connection=redis_conn)
PROXY_POOL = [
"http://user:[email protected]:8000",
"http://user:[email protected]:8000",
]
proxy_cycle = itertools.cycle(PROXY_POOL)
def fetch_with_proxy(url):
proxy = next(proxy_cycle)
response = requests.get(
url,
proxies={"http": proxy, "https": proxy},
timeout=15
)
if response.status_code == 429:
# विलंब के साथ पुनः कतार में डालना
q.enqueue_in(60, fetch_with_proxy, url)
return None
return response.status_code
# कतार में कार्य डालना
urls = ["https://example.com/page1", "https://example.com/page2"]
for url in urls:
q.enqueue(fetch_with_proxy, url)
RQ में itertools.cycle के माध्यम से रोटेशन श्रमिक प्रक्रिया के भीतर काम करता है - यह Redis काउंटर की तुलना में सरल है, लेकिन कई समानांतर श्रमिकों के साथ स्केल करने में खराब है, क्योंकि प्रत्येक श्रमिक चक्र को शुरू से शुरू करता है। 1-5 श्रमिकों के साथ छोटे प्रोजेक्ट्स के लिए यह पर्याप्त है, बड़े प्रोजेक्ट्स के लिए Redis में केंद्रीकृत काउंटर पर लौटना बेहतर है, जैसा कि Celery के उदाहरण में है।
RQ उन डेवलपर्स के लिए अच्छी तरह से उपयुक्त है जो पहले से ही अपने प्रोजेक्ट में Redis का उपयोग कर रहे हैं और एक अलग संदेश ब्रोकर को स्थापित नहीं करना चाहते। नकारात्मक पक्ष - Celery की तुलना में प्राथमिकता और निगरानी के लिए कम अंतर्निहित तंत्र हैं, इसलिए उत्पादन प्रणालियों के लिए जिनमें प्रति दिन सैकड़ों हजारों कार्य होते हैं, अक्सर Celery को ही चुना जाता है।
BullMQ: Node.js पर IP सीमा के साथ कतार
BullMQ - Node.js पारिस्थितिकी तंत्र में कार्यों की कतार के लिए मानक है, Redis पर आधारित है और इसमें अंतर्निहित दर सीमाकर्ता (rate limiter) है, जो IP पर अनुरोधों की सीमा को नियंत्रित करने के लिए विशेष रूप से सुविधाजनक है। मैन्युअल रूप से अनुरोधों की गणना करने के बजाय, आप कतार के स्तर पर सीधे सीमाकर्ता निर्दिष्ट कर सकते हैं।
const { Queue, Worker } = require('bullmq');
const axios = require('axios');
const connection = { host: 'localhost', port: 6379 };
const proxyPool = [
'http://user:[email protected]:8000',
'http://user:[email protected]:8000',
'http://user:[email protected]:8000',
];
const queue = new Queue('fetchQueue', { connection });
// सीमाकर्ता: कतार पर प्रति सेकंड 5 कार्यों से अधिक नहीं
const worker = new Worker('fetchQueue', async job => {
const proxy = proxyPool[job.id % proxyPool.length];
try {
const response = await axios.get(job.data.url, {
proxy: false,
httpsAgent: new (require('https-proxy-agent'))(proxy),
timeout: 15000,
});
return response.status;
} catch (err) {
if (err.response && err.response.status === 429) {
throw new Error('Rate limited, retrying with another proxy');
}
throw err;
}
}, {
connection,
limiter: { max: 5, duration: 1000 },
concurrency: proxyPool.length,
});
for (let i = 0; i < 100; i++) {
queue.add('fetch', { url: `https://example.com/item/${i}` }, {
attempts: 3,
backoff: { type: 'exponential', delay: 5000 },
});
}
BullMQ में limiter पैरामीटर एक अंतर्निहित तंत्र है, जो समय के अंतराल में संसाधित कार्यों की कुल संख्या को सीमित करता है, जो पूरे सिस्टम में अनुरोधों की सीमा का पालन करने के लिए सुविधाजनक है। और concurrency पैरामीटर, जो प्रॉक्सी पूल के आकार के बराबर है, यह सुनिश्चित करता है कि जितने श्रमिक हैं, उतने ही स्वतंत्र IP एक साथ काम कर रहे हैं।
इस दृष्टिकोण का उपयोग अक्सर उन टीमों द्वारा किया जाता है जो TikTok या Telegram में क्रियाओं को स्वचालित करने के लिए अपने बॉट लिखती हैं - BullMQ अन्य Node.js स्टैक के साथ अच्छी तरह से एकीकृत होता है और एक कार्य के लिए Python पर स्विच करने की आवश्यकता नहीं होती है।
Celery, RQ और BullMQ की तुलना
| पैरामीटर | Celery | RQ | BullMQ |
|---|---|---|---|
| भाषा | Python | Python | Node.js |
| ब्रोकर | Redis / RabbitMQ | केवल Redis | केवल Redis |
| अंतर्निहित दर सीमाकर्ता | नहीं (हाथ से लिखा जाता है) | नहीं | हाँ, डिफ़ॉल्ट रूप से |
| प्रवेश का थ्रेशोल्ड | मध्यम | निम्न | मध्यम |
| के लिए उपयुक्त | बड़े उत्पादन प्रणाली | छोटे प्रोजेक्ट, प्रोटोटाइप | Node.js स्टैक, बॉट, स्वचालन |
IP के माध्यम से लोड वितरण की रणनीतियाँ
राउंड-रॉबिन, जिसका उपयोग ऊपर के उदाहरणों में किया गया है, सबसे सरल रणनीति है, लेकिन हमेशा सबसे अनुकूल नहीं होती। यहाँ कुछ विकल्प हैं जिन्हें कार्य के आधार पर विचार करना चाहिए:
- राउंड-रॉबिन - प्रत्येक अगला अनुरोध अगले प्रॉक्सी के माध्यम से चक्र में जाता है। जब सभी IP समान होते हैं और उन पर सीमाएँ समान होती हैं, तो यह उपयुक्त है।
- स्टिकी सत्र - एक प्रॉक्सी एक विशिष्ट खाते या सत्र के लिए सभी समय के लिए संलग्न होती है। यह सोशल मीडिया और मार्केटप्लेस के लिए महत्वपूर्ण है, जहां सत्र के बीच IP बदलना संदिग्ध लगता है।
- वेटेड वितरण - कुछ अनुरोध अधिक महंगे और विश्वसनीय IP (जैसे, मोबाइल) पर भेजे जाते हैं, कुछ सस्ते डेटा सेंटर पर, उस डोमेन के आधार पर जो संसाधित किया जा रहा है।
- एडाप्टिव थ्रॉटलिंग - यदि 429 या कैप्चा की त्रुटियों का प्रतिशत बढ़ता है, तो कार्यों की भेजने की गति स्वचालित रूप से कम हो जाती है, और जब त्रुटियाँ गायब हो जाती हैं, तो इसे फिर से बहाल किया जाता है।
उन कार्यों के लिए जहां सामान्य उपयोगकर्ता के रूप में छिपना महत्वपूर्ण है - उदाहरण के लिए, Instagram या TikTok में खातों को गर्म करना और जांचना एंटी-डिटेक्ट ब्राउज़रों जैसे Dolphin Anty या AdsPower के माध्यम से - मोबाइल प्रॉक्सी के साथ स्टिकी सत्र का उपयोग करना बेहतर है: वे एंटी-बॉट सिस्टम के संदेह में कम आते हैं और मोबाइल इंटरनेट के सामान्य उपयोगकर्ताओं की तरह व्यवहार करते हैं।
वेबसाइटों से डेटा के बड़े पैमाने पर संग्रह के लिए, जहां गति और मात्रा महत्वपूर्ण होती है, न कि एल्गोरिदम की विश्वसनीयता, राउंड-रॉबिन के साथ आवासीय प्रॉक्सी स्थिरता और कीमत के बीच संतुलन प्रदान करता है: IP वास्तविक उपयोगकर्ताओं की तरह दिखते हैं, लेकिन उन्हें एक विशिष्ट सत्र के लिए जोखिम के बिना अक्सर बदल सकते हैं।
त्रुटियों 429 और बैन की निगरानी
कार्यों की कतार बिना निगरानी के - यह एक काला बॉक्स है: यह समझना कठिन है कि कुछ कार्य क्यों विफल हो रहे हैं और कौन से IP पहले से ही संदिग्ध हैं। न्यूनतम मेट्रिक्स का सेट, जिसे ट्रैक करना चाहिए:
- प्रत्येक प्रॉक्सी के लिए 429 और 403 कोड के साथ उत्तरों का प्रतिशत
- औसत प्रतिक्रिया समय - विलंबता में वृद्धि अक्सर बैन से पहले होती है
- कार्य पर पुनः प्रयासों (retries) की संख्या
- वास्तविक समय में कार्यों की कतार की लंबाई - यदि यह बढ़ती है, तो श्रमिक नहीं संभाल पा रहे हैं
Celery में इसके लिए Flower का उपयोग करना सुविधाजनक है - वास्तविक समय में कार्यों और श्रमिकों की निगरानी के लिए एक वेब इंटरफेस। BullMQ में समान कार्यक्षमता के साथ Bull Board है। RQ के लिए RQ डैशबोर्ड है। ये तीनों उपकरण कार्यों की स्थिति, असफल प्रयासों की संख्या दिखाते हैं और यह जल्दी से समझने की अनुमति देते हैं कि किस पूल से प्रॉक्सी को अस्थायी रूप से रोटेशन से बाहर रखना चाहिए।
एक अच्छी प्रथा यह है कि 429 की लगातार त्रुटियों के बाद कुछ समय (15-30 मिनट) के लिए प्रॉक्सी को "क्वारंटाइन" के रूप में चिह्नित किया जाए, और इसे केवल सफल परीक्षण अनुरोध के बाद पूल में वापस लाया जाए। यह उस स्थिति को रोकता है जब बैन किया गया IP कार्य प्राप्त करना जारी रखता है और श्रमिकों का समय बर्बाद करता है।
निष्कर्ष
कार्यों की कतार अनुरोधों के स्केलिंग की समस्या को हल करती है, लेकिन यह स्वयं IP पर सीमा से नहीं बचाती - इसके लिए Celery, RQ या BullMQ के भीतर प्रॉक्सी का सोचा-समझा रोटेशन आवश्यक है। उपकरण का चयन स्टैक पर निर्भर करता है: Python प्रोजेक्ट्स अक्सर उत्पादन के लिए Celery लेते हैं और सरल कार्यों के लिए RQ, Node.js डेवलपर्स - इसके अंतर्निहित दर सीमाकर्ता के साथ BullMQ।
चयनित कतार के बावजूद, परिणाम स्वयं प्रॉक्सी पूल की गुणवत्ता पर बहुत निर्भर करता है। यदि कार्य - तेज़ बड़े पैमाने पर पार्सिंग है, तो गति के लिए डेटा सेंटर प्रॉक्सी पर ध्यान दें, और सोशल मीडिया और मार्केटप्लेस के साथ काम करने के लिए, जहां एंटी-बॉट सिस्टम की वफादारी महत्वपूर्ण है, आवासीय या मोबाइल IP उपयुक्त होंगे - वे 429 और बैन की त्रुटियों के प्रतिशत को कम करते हैं, जो सीधे पुनः प्रयासों की संख्या को कम करता है और कार्यों की पूरी कतार के निष्पादन को तेज करता है।