Socks5Proxy

Scrapy প্রোক্সি সেটিং, meta proxy দিয়ে প্রতি রিকোয়েস্টে ভিন্ন আইপি ব্যবহার

এই গাইডে Scrapy-তে Socks5Proxy-এর HTTP প্রোক্সি meta proxy দিয়ে সংযোগ, API থেকে প্রাপ্ত তালিকা রিকোয়েস্ট অনুযায়ী রোটেট করার ডাউনলোডার মিডলওয়্যার, টার্গেট সাইটের জন্য গতি সেটিং বর্ণনা করা হয়েছে।

Scrapy কিভাবে প্রোক্সি হ্যান্ডেল করে?

Scrapy-তে HttpProxyMiddleware ডিফল্টভাবে চালু থাকে। রিকোয়েস্টের meta ডিকশনারিতে proxy কী হিসেবে অ্যাড্রেস দিলে সেই রিকোয়েস্ট সেই প্রোক্সিতে যায়, এবং অ্যাড্রেসের ইউজারনেম-পাসওয়ার্ড মিডলওয়্যার Proxy-Authorization হেডারে কনভার্ট করে পাঠায়। HTTPS অ্যাড্রেস CONNECT টানেলের মাধ্যমে যায়।

Scrapy-র ডিফল্ট ডাউনলোড হ্যান্ডলার HTTP প্রোক্সি সাপোর্ট করে। SOCKS5 একান্ত প্রয়োজন হলে আলাদা হ্যান্ডলার লাগে, তাই Scrapy-তে একই আইপির HTTP পোর্ট ব্যবহারের পরামর্শ দিই। টার্গেট সাইটে দেখা আইপি একই থাকে।

উদাহরণে IP 198.51.100.23, HTTP পোর্ট 8000, ইউজারনেম spx_user, পাসওয়ার্ড spx_pass ব্যবহার করা হয়।

pip install scrapy
scrapy startproject shop
cd shop

একটি অনুরোধে প্রোক্সি কিভাবে যুক্ত করবেন?

start_requests-এ Request তৈরি করার সময় meta-তে proxy যোগ করুন। কলব্যাকে পরের পৃষ্ঠা রিকোয়েস্ট করার সময়ও একইভাবে যোগ করুন। একই সেশন চালিয়ে যেতে হলে আগের রেসপন্সের meta থেকে proxy মান একইভাবে পাস করলে একই IP বজায় থাকে।

import scrapy

PROXY = "http://spx_user:spx_pass@198.51.100.23:8000"

class IpCheckSpider(scrapy.Spider):
    name = "ip_check"

    def start_requests(self):
        yield scrapy.Request("https://api.ipify.org?format=json", meta={"proxy": PROXY})

    def parse(self, response):
        self.logger.info("seen as %s", response.json()["ip"])

প্রতিটি অনুরোধে আইপি কিভাবে রোটেট করবেন?

একটি ডাউনলোডার মিডলওয়্যার তৈরি করে সমস্ত অনুরোধে পরবর্তী প্রক্সি যুক্ত করলে স্পাইডার কোড পরিবর্তন না করে রোটেট করা যায়। নিচের মিডলওয়্যার শুরুতে API থেকে তালিকা নেয়, meta-তে proxy ইতিমধ্যে থাকলে তা অপরিবর্তিত রেখে সেশন স্থিরতা ও রোটেশন একসাথে ব্যবহারের সুযোগ দেয়।

API কী settings.py এ রাখুন বা পরিবেশ ভেরিয়েবল থেকে পড়ুন। ক্রমটি ডিফল্ট HttpProxyMiddleware(750) এর আগে একটি সংখ্যা দিয়ে নিবন্ধিত করতে হবে যাতে মিডলওয়্যার দ্বারা ইনজেক্ট করা ঠিকানা ডিফল্ট মিডলওয়্যার প্রসেস করে।

import itertools
import requests

class RotatingProxyMiddleware:
    def __init__(self, key):
        text = requests.get(
            "https://socks5proxy.io/api/v1/proxies/download",
            params={"format": "user:pass@ip:port", "protocol": "http"},
            headers={"Authorization": "Bearer " + key},
            timeout=30,
        ).text
        self.pool = itertools.cycle(["http://" + l.strip() for l in text.splitlines() if l.strip()])

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler.settings.get("SPX_API_KEY"))

    def process_request(self, request, spider):
        if "proxy" not in request.meta:  # keep a proxy that was set on purpose (sticky sessions)
            request.meta["proxy"] = next(self.pool)

গতি এবং রিট্রাই কীভাবে সামঞ্জস্য করবেন?

CONCURRENT_REQUESTS_PER_DOMAIN একই ডোমেইনে একসাথে পাঠানো রিকোয়েস্ট সংখ্যা। প্রোক্সি IP যত বেশি হবে এই মান বাড়ালেও IP প্রতি যাওয়া বোঝা একই থাকে। যেমন IP 500 টি দিয়ে একসাথে রিকোয়েস্ট 50 টি পাঠালে IP প্রতি গড়ে 10 বার রিকোয়েস্টে একবার ব্যবহৃত হয়।

AUTOTHROTTLE চালু রাখলে রেসপন্স স্পিড অনুযায়ী রিকোয়েস্ট ব্যবধান অটোমেটিকভাবে নিয়ন্ত্রণ করে। 429 রেসপন্স বাড়লে RETRY_HTTP_CODES দিয়ে আবার চেষ্টা করুন, আবার চেষ্টা করার সময় মিডলওয়্যার পরবর্তী প্রোক্সি ইনজেক্ট করার জন্য meta এর proxy মুছে ফেলার পদ্ধতিও আছে।

আপনার ডেটা পাইপলাইনে একটি চেক রাখুন যে সংগৃহীত ফলাফল কনফার্মেশন পেজ না বাস্তব পেজ। যদি প্রয়োজনীয় এলিমেন্ট না থাকে, তাহলে অন্য IP দিয়ে আবার রিকোয়েস্ট পাঠান।

  • IP সংখ্যার সাথে মিলিয়ে ডোমেইন প্রতি একই সময়ে অনুরোধ সংখ্যা নিয়ন্ত্রণ করুন
  • AUTOTHROTTLE দিয়ে রেসপন্স স্পিড অনুযায়ী ব্যবধান
  • 429 এবং 5xx হলে অন্য IP দিয়ে আবার চেষ্টা করুন
  • রেসপন্স কন্টেন্ট চেক করে ক্যাপচা ফিল্টার করুন

IP অনুমোদন দিয়ে সংযোগ করলে কী পরিবর্তন হয়?

ড্যাশবোর্ডে Scrapy চলছে এমন সার্ভারের IPv4 রেজিস্টার করুন, তারপর meta proxy-এ http://198.51.100.23:8000 এর মতো ইউজারনেম ও পাসওয়ার্ড ছাড়াই ব্যবহার করুন। লিস্টও format=ip:port হিসেবে পেতে পারেন। একাধিক সার্ভারে স্পাইডার চালালে প্রতিটি সার্ভারের IP রেজিস্টার করুন। সর্বোচ্চ 10টি IP রেজিস্টার করা যায়।

সেশন প্রয়োজনীয় রিকোয়েস্ট একই আইপিতে বাঁধতে কী করতে হবে?

লগইন বা শপিং কার্টের মতো কুকি ধারাবাহিকতা প্রয়োজন এমন প্রক্রিয়াগুলির জন্য একই IP ঠিকানা ব্যবহার করা উচিত। প্রথম অনুরোধে meta proxy সরাসরি যোগ করুন, এবং কলব্যাকে পরবর্তী অনুরোধ তৈরি করার সময় response.meta-এর proxy মানটি একইভাবে পাস করুন, যাতে সাইক্লিক মিডলওয়্যার এটি পরিবর্তন না করে। Scrapy-এর cookiejar meta কী একই সাথে ব্যবহার করলে কুকিও প্রতিটি সেশনের জন্য আলাদা থাকে।

একটি সেশনে একটি প্রক্সি এবং একটি কুকি ব্যাচ জুড়ে রাখলে একাধিক সেশন একই সাথে চালালেও পরস্পর মিশে যাবে না।

import scrapy

PROXIES = [
    "http://spx_user:spx_pass@198.51.100.23:8000",
    "http://spx_user:spx_pass@198.51.100.24:8000",
]

class SessionSpider(scrapy.Spider):
    name = "sessions"

    def start_requests(self):
        for i, proxy in enumerate(PROXIES):
            yield scrapy.Request("https://example.com/", meta={"proxy": proxy, "cookiejar": i}, dont_filter=True)

    def parse(self, response):
        # follow-up request keeps the same proxy and the same cookie jar
        yield response.follow("/account", meta={"proxy": response.meta["proxy"], "cookiejar": response.meta["cookiejar"]}, callback=self.parse_account)

    def parse_account(self, response):
        self.logger.info("status %s via %s", response.status, response.meta["proxy"])

ব্যর্থ প্রোক্সি কিছুক্ষণ বাদ দিতে চান?

মিডলওয়্যারের process_response-এ 403 বা 429 রেসপন্স পেলে সেই প্রোক্সিকে কয়েক মিনিটের জন্য রেস্ট দিতে পারেন, এবং একই রিকোয়েস্ট অন্য প্রোক্সি দিয়ে আবার পাঠাতে পারেন। রিকোয়েস্ট কপি করে meta-র proxy মুছে dont_filter চালু করে দিলে পরবর্তী প্রোক্সি ব্যবহার হবে।

রেস্টিং প্রোক্সি লিস্ট এবং পুনরায় ব্যবহারের সময় একটি ডিকশনারিতে ম্যানেজ করলে সহজ হবে। একই IP সাথে সাথেই পুনরায় ব্যবহার না করলে টার্গেট সাইটের রেস্ট্রিকশন কাটানোর সময় পাবে।

Scrapy-তে ব্যান্ডউইথ সেভ করতে কী সেট করব?

Scrapy ডিফল্টভাবে শুধু HTML নেয় তাই ব্রাউজার টুলের চেয়ে অনেক কম ব্যান্ডউইথ ব্যবহার করে। এতে HttpCompressionMiddleware ডিফল্টভাবে চালু থাকে যা ট্রান্সফার ভলিউম আরও কমায়। শেয়ার্ড প্ল্যানের মাসিক ব্যান্ডউইথ লিমিটের মধ্যে অনেক পেজ সংগ্রহ করা যায় এই কারণে।

একই পেজ বারবার রিসিভ না করতে HTTPCACHE_ENABLED ডেভেলপমেন্টের সময় অন রাখুন, তাহলে প্রতিবার টেস্ট করার সময় টার্গেট সাইট ও প্রক্সি আবার কল করতে হবে না। প্রোডাকশনে ডুপ্লিকেট URL ফিল্টারিং (ডিফল্ট অন) চালু রাখুন, আর শুধুমাত্র সত্যিই আবার রিসিভ করা দরকার এমন রিকুয়েস্টে dont_filter ব্যবহার করুন।

অপ্রয়োজনীয় সাবপেজে ছড়িয়ে না পড়ার জন্য লিঙ্ক অনুসরণের পরিসর সংকীর্ণ করাও গুরুত্বপূর্ণ। সংগ্রহ পরিসর স্পষ্টভাবে নির্ধারণ করলে সময়, ব্যান্ডউইথ এবং টার্গেট সাইটের বোঝা সবই কমে যায়।

ঘন ঘন হওয়া সমস্যার সমাধান কী?

407 রেসপন্স পেলে ঠিকানার মধ্যে ব্যবহারকারী নাম এবং পাসওয়ার্ড চেক করুন। পাসওয়ার্ডে বিশেষ অক্ষর থাকলে শতাংশ এনকোডিং করে নিতে হবে। TunnelError মানে প্রোক্সি CONNECT রিকোয়েস্ট পায়নি, পোর্ট HTTP পোর্ট কিনা চেক করুন।

সমস্ত অনুরোধ একই IP দিয়ে যায় যদি মিডলওয়্যার ক্রম সংখ্যা HttpProxyMiddleware-এর পরে থাকে, অথবা স্পাইডারে meta proxy সরাসরি যোগ করা থাকে। settings.py-এর ক্রম এবং স্পাইডার কোড একসাথে যাচাই করুন।

Scrapy প্রোক্সি সেটিং, meta proxy এবং রোটেটিং মিডলওয়্যার | Socks5Proxy