Scrapy 2026 में भी production crawls के लिए मेहनती घोड़ा है — और अब भी वही framework है जहाँ प्रॉक्सी सेटअप लोगों को सबसे ज़्यादा भ्रमित करता है, क्योंकि प्रॉक्सी को प्लग करने के लिए चार अलग-अलग जगहें हैं और उनमें से तीन ज़्यादातर प्रोजेक्ट्स के लिए ग़लत हैं। यह गाइड आपको सही वाली देती है: per-request routing, sticky sessions, ban detection, और समझदार retry behavior के साथ एक छोटा custom middleware।
अगर आप इसके बजाय साधारण requests/httpx/aiohttp पर हैं, तो Python में प्रॉक्सी कैसे rotate करें देखें। यह लेख Scrapy-विशिष्ट है।
एक rotating residential gateway के लिए, न्यूनतम व्यवहार्य सेटअप प्रति request एक line है — किसी middleware की ज़रूरत नहीं:
def start_requests(self):
for url in self.urls:
yield scrapy.Request(
url,
meta={"proxy": "http://USERNAME:[email protected]:913"},
)
Scrapy का बिल्ट-इन HttpProxyMiddleware request.meta["proxy"] पढ़ता है और URL से authentication संभालता है। Gateway आपके लिए exit IP rotate करता है। अगर आपको बस इतना ही चाहिए, तो यहीं रुक जाएँ। इस गाइड का बाक़ी हिस्सा तब के लिए है जब आपको नियंत्रण चाहिए: sticky sessions, country routing, ban-aware rotation, और concurrency tuning।
इसे middlewares.py में डालें। यह प्रति domain sticky sessions assign करता है, bans पर rotate करता है, और हर request को tag करता है ताकि आप debug कर सकें कि किस session ने क्या fetch किया:
import random
import string
GATEWAY = "us.jibaoproxy.com:913"
USERNAME = "USERNAME" # move to settings.py / env in real projects
PASSWORD = "PASSWORD"
def _new_session(n=8):
return "".join(random.choices(string.ascii_lowercase + string.digits, k=n))
class JibaoProxyMiddleware:
"""Sticky session per domain; rotate session on ban."""
def __init__(self):
self.sessions = {} # domain -> session id
def _proxy_url(self, session_id):
user = f"{USERNAME}-session-{session_id}"
return f"http://{user}:{PASSWORD}@{GATEWAY}"
def process_request(self, request, spider):
domain = request.url.split("/")[2]
session = self.sessions.setdefault(domain, _new_session())
request.meta["proxy"] = self._proxy_url(session)
request.meta["proxy_session"] = session
def rotate(self, domain):
"""Call when a session is burned."""
self.sessions[domain] = _new_session()
और एक साथी downloader middleware जो bans का पता लगाता है और एक नए session पर retry करता है:
from scrapy.downloadermiddlewares.retry import RetryMiddleware
from scrapy.utils.response import response_status_message
BAN_CODES = {403, 429}
BAN_MARKERS = (b"captcha", b"access denied", b"unusual traffic")
class BanAwareRetryMiddleware(RetryMiddleware):
def process_response(self, request, response, spider):
banned = (
response.status in BAN_CODES
or any(m in response.body[:2048].lower() for m in BAN_MARKERS)
)
if banned:
domain = request.url.split("/")[2]
proxy_mw = spider.crawler.engine.downloader.middleware.middlewares
for mw in proxy_mw:
if hasattr(mw, "rotate"):
mw.rotate(domain) # burn the session
reason = response_status_message(response.status)
return self._retry(request, reason, spider) or response
return super().process_response(request, response, spider)
दोनों को settings.py में वायर करें:
DOWNLOADER_MIDDLEWARES = {
"myproject.middlewares.JibaoProxyMiddleware": 350,
"scrapy.downloadermiddlewares.retry.RetryMiddleware": None, # replace stock retry
"myproject.middlewares.BanAwareRetryMiddleware": 550,
}
RETRY_TIMES = 2
Priority मायने रखती है: प्रॉक्सी middleware को Scrapy के HttpProxyMiddleware (750) से पहले चलना चाहिए, इसलिए 750 से नीचे की कोई भी चीज़ काम करती है; 350 इसे जल्दी और पूर्वानुमानयोग्य रखता है।
| Crawl टाइप | मोड | Implementation |
|---|---|---|
| Stateless पेज harvesting | Rotating | सादा username, gateway प्रति request rotate करता है |
| Login + auth के पीछे crawl | प्रति account sticky | -session-{account_id}, login के बीच में कभी rotate न करें |
| Pagination-भारी listings | प्रति domain sticky, ban पर rotate | ऊपर वाला middleware |
| Geo-विशिष्ट pricing | Rotating + country pin | USERNAME-country-de शैली के पैरामीटर |
इस trade-off का गहरा विश्लेषण: Sticky बनाम Rotating प्रॉक्सी Sessions।
Scrapy डिफ़ॉल्ट विनम्र single-IP crawling के लिए ट्यून किए गए हैं। एक rotating pool के पीछे आप कहीं ज़्यादा ज़ोर लगा सकते हैं — लेकिन per-domain सीमाएँ अब भी मायने रखती हैं क्योंकि target कुल व्यवहार देखता है:
# settings.py - sane starting point behind a residential pool
CONCURRENT_REQUESTS = 64
CONCURRENT_REQUESTS_PER_DOMAIN = 8 # what the target experiences
DOWNLOAD_DELAY = 0.25 # jitter applied per slot
RANDOMIZE_DOWNLOAD_DELAY = True # 0.5x-1.5x the delay
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_TARGET_CONCURRENCY = 6.0
DOWNLOAD_TIMEOUT = 30
ROBOTSTXT_OBEY = True
CONCURRENT_REQUESTS_PER_DOMAIN को तभी बढ़ाएँ जब आप कुछ हज़ार requests तक मौजूदा स्तर पर अपनी 403 दर देख चुके हों। "प्रॉक्सी वैसे भी rotate होते हैं" सोचकर 8 → 32 करना ही वह तरीक़ा है जिससे लोग retries पर GB जला देते हैं।
IMAGES_STORE pipelines को एक datacenter प्रॉक्सी या सीधे connection के ज़रिए fetch करने के लिए सेट करें, अगर CDN को कोई फ़र्क़ नहीं पड़ता — media आपके अधिकांश GB है और शायद ही कभी संरक्षित होता है।HTTPCACHE_ENABLED = True जब आप parsers पर iterate करते हैं तो responses को pool के ज़रिए फिर से fetch करने के बजाय disk से replay करता है। यह एक सेटिंग आमतौर पर एक प्रोजेक्ट का bandwidth बिल आधा कर देती है।COMPRESSION_ENABLED = True (डिफ़ॉल्ट) रखें — gzip किया हुआ HTML तार पर 5–10x छोटा होता है।407 Proxy Authentication RequiredCredentials प्रॉक्सी तक नहीं पहुँचे। उन्हें meta["proxy"] में URL (http://user:pass@host:port) में डालें — Scrapy parse करता है और आपके लिए Proxy-Authorization सेट करता है। Header को मैन्युअल रूप से सेट करना और URL credentials इस्तेमाल करना double-auth विचित्रता पैदा करता है; एक चुनें।
TunnelError: Could not open CONNECT tunnelलगभग हमेशा एक typo किया हुआ host/port, या एक ऐसे endpoint के ज़रिए HTTPS target जो उस port पर CONNECT की अनुमति नहीं देता। पहले Scrapy के बाहर curl -x से सत्यापित करें।
आपका sticky session अपने स्वागत से ज़्यादा जी गया, या आपकी per-domain दर बहुत तेज़ है। ऊपर वाला ban-aware middleware पहले मामले को संभालता है; दूसरे के लिए CONCURRENT_REQUESTS_PER_DOMAIN कम करें। अगर यह एक JA4-जाँचने वाला target है, तो Scrapy का TLS stack ख़ुद ही पोल खोल सकता है — देखें कि कोई प्रॉक्सी उसे क्यों ठीक नहीं करता, इसके लिए JA3/JA4 समझाया गया।
meta["proxy"] ही पूरा सेटअप है।एक gateway पर rotating और sticky residential sessions। crawl करने के लिए 500MB मुफ़्त ट्रैफ़िक क्रेडिट।
Start Free Trialनए यूज़र्स को साइन अप पर 500MB मिलते हैं, साथ ही पहली रिचार्ज पर बोनस। सीमित समय की पेशकश।