২০২৬ সালেও Scrapy এখনও প্রোডাকশন ক্রলের প্রধান কর্মী — এবং এখনও সেই ফ্রেমওয়ার্ক যেখানে proxy সেটআপ মানুষকে সবচেয়ে বেশি বিভ্রান্ত করে, কারণ proxy যুক্ত করার চারটি আলাদা জায়গা আছে এবং তার মধ্যে তিনটিই বেশিরভাগ প্রকল্পের জন্য ভুল। এই গাইডটি আপনাকে সঠিকটি দেয়: একটি ছোট কাস্টম middleware যাতে আছে per-request রাউটিং, sticky সেশন, ব্যান শনাক্তকরণ এবং যুক্তিসঙ্গত retry আচরণ।
আপনি যদি এর বদলে সাধারণ requests/httpx/aiohttp ব্যবহার করেন, তাহলে দেখুন Python-এ কীভাবে Proxy ঘোরাবেন। এই নিবন্ধটি Scrapy-নির্দিষ্ট।
একটি rotating residential gateway-এর জন্য, ন্যূনতম কার্যকর সেটআপ হলো প্রতি request-এ এক লাইন — কোনো 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 ঘোরায়। আপনার যদি এটুকুই দরকার হয়, এখানেই থামুন। এই গাইডের বাকি অংশ সেইসব ক্ষেত্রের জন্য যেখানে আপনার নিয়ন্ত্রণ দরকার: sticky সেশন, দেশভিত্তিক রাউটিং, ব্যান-সচেতন rotation এবং concurrency টিউনিং।
এটি আপনার middlewares.py-তে রাখুন। এটি প্রতি ডোমেইনে sticky সেশন বরাদ্দ করে, ব্যানের সময় ঘোরায়, এবং প্রতিটি request ট্যাগ করে যাতে আপনি ডিবাগ করতে পারেন কোন সেশন কী 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 যা ব্যান শনাক্ত করে এবং একটি নতুন সেশনে 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
অগ্রাধিকার গুরুত্বপূর্ণ: proxy middleware অবশ্যই Scrapy-এর HttpProxyMiddleware (750)-এর আগে চলতে হবে, তাই 750-এর নিচের যেকোনো মান কাজ করে; 350 এটিকে আগেভাগে এবং অনুমেয় রাখে।
| ক্রল ধরন | মোড | বাস্তবায়ন |
|---|---|---|
| স্টেটলেস পেজ সংগ্রহ | Rotating | খালি username, gateway প্রতি request-এ ঘোরায় |
| Login + auth-এর পেছনে ক্রল | প্রতি অ্যাকাউন্টে Sticky | -session-{account_id}, login-এর মাঝখানে কখনো ঘোরাবেন না |
| Pagination-ভারী তালিকা | প্রতি ডোমেইনে Sticky, ব্যানে ঘোরান | উপরের middleware |
| ভৌগোলিক-নির্দিষ্ট মূল্য | Rotating + দেশ পিন | USERNAME-country-de ধরনের প্যারামিটার |
এই ট্রেড-অফের গভীর আলোচনা: Sticky বনাম Rotating Proxy সেশন।
Scrapy-এর ডিফল্ট ভদ্রভাবে একক-IP ক্রলের জন্য টিউন করা। একটি rotating পুলের পেছনে আপনি অনেক বেশি চাপ দিতে পারেন — কিন্তু প্রতি-ডোমেইন সীমা এখনও গুরুত্বপূর্ণ কারণ লক্ষ্যবস্তু সামগ্রিক আচরণ দেখে:
# 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 বাড়ান কেবল তখনই যখন আপনি বর্তমান স্তরে কয়েক হাজার request-এর জন্য আপনার 403 হার পর্যবেক্ষণ করেছেন। "proxy তো এমনিতেই ঘোরে" বলে 8 → 32 করা হলো সেই উপায় যেভাবে মানুষ retry-তে GB পুড়িয়ে ফেলে।
IMAGES_STORE pipeline সেট করুন যাতে CDN-এর যদি সমস্যা না থাকে তবে একটি datacenter proxy বা সরাসরি সংযোগের মাধ্যমে fetch করে — মিডিয়াই আপনার GB-এর বেশিরভাগ এবং খুব কমই সুরক্ষিত থাকে।HTTPCACHE_ENABLED = True থাকলে আপনি যখন parser নিয়ে কাজ করেন তখন এটি পুলের মাধ্যমে পুনরায় fetch না করে ডিস্ক থেকে response পুনরায় চালায়। এই একটি সেটিং সাধারণত একটি প্রকল্পের bandwidth বিল অর্ধেক করে দেয়।COMPRESSION_ENABLED = True (ডিফল্ট) রাখুন — gzip করা HTML তারে ৫–১০ গুণ ছোট।407 Proxy Authentication RequiredCredential proxy পর্যন্ত পৌঁছায়নি। সেগুলো meta["proxy"]-তে URL-এর মধ্যে রাখুন (http://user:pass@host:port) — Scrapy পার্স করে আপনার জন্য Proxy-Authorization সেট করে। হেডার ম্যানুয়ালি সেট করা এবং URL credential ব্যবহার করা দুটোই করলে double-auth অস্বাভাবিকতা ঘটে; একটি বেছে নিন।
TunnelError: Could not open CONNECT tunnelপ্রায় সবসময় host/port-এ টাইপো, অথবা এমন একটি endpoint-এর মাধ্যমে HTTPS লক্ষ্যবস্তু যা সেই port-এ CONNECT অনুমতি দেয় না। প্রথমে Scrapy-এর বাইরে curl -x দিয়ে যাচাই করুন।
আপনার sticky সেশন তার স্বাগত মেয়াদ ছাড়িয়ে গেছে, অথবা আপনার প্রতি-ডোমেইন হার অতিরিক্ত গরম। উপরের ব্যান-সচেতন middleware প্রথম ক্ষেত্রটি সামলায়; দ্বিতীয়টির জন্য CONCURRENT_REQUESTS_PER_DOMAIN কমান। যদি এটি একটি JA4-যাচাইকারী লক্ষ্যবস্তু হয়, তবে Scrapy-এর TLS স্ট্যাক নিজেই হয়তো সংকেত দিচ্ছে — কেন কোনো proxy সেটি ঠিক করে না তা জানতে দেখুন JA3/JA4 ব্যাখ্যা।
meta["proxy"]-ই হলো পুরো সেটআপ।একটি gateway-এ rotating এবং sticky residential সেশন। ক্রল করার জন্য 500MB ফ্রি ট্রাফিক।
ফ্রি ট্রায়াল শুরু করুননতুন ব্যবহারকারীরা নিবন্ধনের সময় 500MB পান, সাথে প্রথম রিচার্জে বোনাস। সীমিত সময়ের অফার।