Cara Menyiapkan Custom Proxy di Scrapy (Siap Produksi)

Terakhir diperbarui pada August 11, 2026
Hand-drawn Scrapy crawler routing through a proxy pool, retrying a 503 route and completing through a 200 route
Ringkasan AI
  • Bangun custom Scrapy proxy middleware yang menetapkan rute yang diizinkan, menambahkan autentikasi secara aman, mencatat alasan kegagalan, dan mempertahankan metadata request saat retry.
  • Pahami urutan downloader middleware, terutama bagaimana logika proxy kustom berinteraksi dengan HttpProxyMiddleware, RetryMiddleware, redirect, dan penanganan exception.
  • Tambahkan rotasi dengan jumlah percobaan terbatas, cooldown, status kesehatan proxy, dan kebijakan yang aware terhadap target, alih-alih memilih proxy acak untuk setiap request.
  • Bedakan kegagalan autentikasi proxy, error koneksi, masalah DNS, respons 403 dari target, dan rate limit agar tiap kondisi mendapat respons yang tepat.
  • Gunakan safeguard produksi untuk penyimpanan secret, concurrency, observability, konsistensi session, dan perilaku fail-closed saat tidak ada proxy yang diizinkan yang masih tersedia.

Spider Scrapy kamu bisa melaju mulus di 100 halaman uji, lalu tiba-tiba ambruk saat sudah sampai 10.000 halaman. Itu bukan sekadar bug scraping—biasanya ada masalah jaringan yang menyamar jadi bug scraping. Solusi yang paling sering dipakai adalah proxy, dan menambahkannya ke request.meta cuma butuh sekitar tiga puluh detik.

Masalahnya, perbaikan 30 detik itulah yang sering jadi batas akhir banyak tutorial dasar. Mereka cuma nunjukin meta={"proxy": "http://IP:PORT"}, mungkin ditambah satu class middleware, lalu selesai. Hal-hal penting seperti apa yang terjadi kalau proxy mati di tengah crawl, bagaimana kredensial bisa bocor ke riwayat Git, atau kenapa retry bisa tetap memakai proxy gagal yang sama, sering banget tidak dibahas. Itulah isu produksi yang dicakup panduan ini: konfigurasi fail-closed, pengelolaan secret, pemilihan proxy yang disengaja saat retry, batasan protokol, dan trade-off biaya yang bisa diukur.

Apa Itu Proxy Middleware di Scrapy?

Proxy middleware adalah potongan kode yang duduk di pipeline downloader Scrapy dan menentukan alamat IP mana yang akan terlihat sebagai sumber request sebelum request itu dikirim. Scrapy sudah menyediakan bawaan bernama HttpProxyMiddleware, yang membaca key proxy dari request.meta, menambahkan autentikasi proxy kalau perlu, lalu menyerahkan request ke download handler yang benar-benar membuka koneksi. Custom proxy middleware tidak menggantikan langkah transport itu — ia berperan sebagai selector yang menentukan proxy mana yang dipasang sebelum mekanisme bawaan mengambil alih. Perbedaan ini jauh lebih penting daripada kelihatannya, dan sering jadi sumber laporan bug seperti “custom middleware saya tidak jalan”.

Mengapa Proxy Penting untuk Proyek Scrapy Produksi

Proxy mengubah jalur jaringan dan IP sumber yang terlihat. Ini bisa membantu untuk pengujian berbasis lokasi yang sah, mendistribusikan traffic request yang diizinkan, dan mengisolasi kegagalan jaringan. Tapi proxy tidak memberi izin, tidak otomatis melewati rate limit, dan tidak menjamin akses. Apakah sebuah crawl memang butuh proxy atau tidak bergantung pada target, syarat penggunaannya, laju request, dan kebutuhan reliabilitas pekerjaan.

Tidak semua proxy dibuat sama, dan memilih kelas yang salah bisa jadi insiden produksi tersendiri:

Jenis ProxyKeandalanKecepatanRisiko TerdeteksiBiaya Umum
Proxy publik gratisSangat bervariasiBervariasiSering tinggiGratis, tapi risikonya besar secara keamanan dan operasional
Proxy datacenterBergantung pada penyedia dan targetSering cepatBergantung pada targetUmumnya ditagih per GB atau per IP
Proxy residentialBergantung pada penyedia dan targetBervariasiBergantung pada targetUmumnya ditagih per GB
Proxy ISPBergantung pada penyedia dan targetBervariasiBergantung pada targetTergantung penyedia

Proxy gratis perlu disorot khusus karena risikonya memang besar. Studi 30 bulan Free Proxies Unmasked melacak lebih dari 640.000 alamat dari 11 penyedia: 34,5% aktif setidaknya sekali, dan 16.923 memanipulasi konten. Temuan ini jadi peringatan keamanan yang kuat untuk daftar publik; ini bukan angka kegagalan yang bisa langsung dipakai ke setiap daftar, pool berbayar, target, atau beban kerja.

Proxy juga tidak otomatis menembus deteksi bot modern. Layanan seperti Cloudflare menilai request memakai puluhan sinyal — fingerprint TLS, konsistensi header, eksekusi JavaScript, pola perilaku — dan IP kamu cuma salah satu input di antaranya. Proxy residential yang bersih pun masih bisa ditandai kalau header tidak konsisten dan cookie jar kosong. Jaga ekspektasi ini sebelum kamu membangun arsitektur cuma berdasarkan “tinggal rotasi IP saja”.

Sebelum Mulai

  • Tingkat kesulitan: Menengah
  • Waktu yang dibutuhkan: ~30–45 menit untuk setup produksi penuh, ~5 menit untuk tes cepat
  • Yang dibutuhkan: Python 3.9+, Scrapy terpasang (panduan ini diuji dengan Scrapy 2.17.0, dirilis Juli 2026), spider yang sudah berjalan dari scrapy startproject, dan setidaknya satu endpoint proxy (free trial dari penyedia proxy datacenter mana pun cukup untuk testing)

Langkah 1: Uji Proxy dengan Parameter Request Meta

Cara tercepat memastikan proxy bekerja adalah melewati seluruh arsitektur middleware dan mengujinya langsung.

Built-in HttpProxyMiddleware milik Scrapy membaca key proxy langsung dari request.meta dan merutekan request lewat proxy tersebut. Tidak perlu ubah settings, tidak perlu class middleware — cukup satu keyword argument.

import scrapy

class ProxyTestSpider(scrapy.Spider):
    name = "proxy_test"
    start_urls = ["https://httpbin.org/ip"]

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(
                url,
                meta={"proxy": "http://203.0.113.10:8080"},
                callback=self.parse,
            )

    def parse(self, response):
        self.logger.info(response.text)

Jalankan dengan scrapy runspider proxy_test.py. Kalau proxy berfungsi, httpbin.org/ip akan menampilkan IP proxy, bukan IP kamu sendiri — itu tanda konfirmasinya. Kalau response macet lalu akhirnya melempar error TCP connection timed out, berarti proxy mati atau tidak bisa dijangkau, yang, spoiler, lebih sering terjadi daripada yang vendor proxy mau akui.

Metode ini cocok untuk spider sekali pakai atau tes cepat. Begitu kamu punya lebih dari satu spider, pendekatan ini mulai berantakan karena kamu meng-hardcode string proxy yang sama di lima file berbeda.

Langkah 2: Bangun Custom Proxy Middleware

Untuk apa pun selain satu spider, logika proxy sebaiknya dipusatkan di satu tempat. Buat class ProxyMiddleware di middlewares.py proyek kamu:

from scrapy.exceptions import NotConfigured

class ProxyMiddleware:
    def __init__(self, proxy_url):
        self.proxy_url = proxy_url

    @classmethod
    def from_crawler(cls, crawler):
        proxy_url = crawler.settings.get("PROXY_URL")
        if not proxy_url:
            raise NotConfigured("PROXY_URL wajib diisi; direct fallback tanpa sengaja ditolak")
        return cls(proxy_url=proxy_url)

    def process_request(self, request, spider):
        if "proxy" not in request.meta:
            request.meta["proxy"] = self.proxy_url

Lalu daftarkan di settings.py:

import os

PROXY_URL = os.environ.get("PROXY_URL")

DOWNLOADER_MIDDLEWARES = {
    "myproject.middlewares.ProxyMiddleware": 350,
}

Perhatikan penggunaan classmethod from_crawler, bukan __init__ biasa. Inilah pola yang memang direkomendasikan Scrapy untuk membaca settings, dan hook yang akan kita pakai lagi di Langkah 4 saat membahas secret. Keuntungannya sederhana: ubah satu setting, semua spider dalam project ikut pakai proxy baru. Kamu tidak perlu lagi mencari-cari IP lama di lima file.

Langkah 3: Pahami Urutan Eksekusi Middleware (Supaya Proxy Tidak Diam-Diam Tidak Berfungsi)

Ini bagian yang sering dilewati dengan kalimat seperti “set saja priority ke 350, percaya deh.” Downloader middleware di Scrapy berjalan dalam urutan yang spesifik dan konsisten. Kalau kamu tidak paham alurnya, setup proxy bisa memunculkan bug yang kelihatannya sama sekali tidak ada hubungannya dengan proxy.

Hook sisi request (process_request) berjalan dalam urutan priority menaik — angka paling kecil duluan. Hook sisi response (process_response, process_exception) berjalan dalam urutan menurun — angka paling besar duluan, lalu mundur ke bawah.

Alur request (menaik):
  Spider → [100] RobotsTxt → [300] HttpAuth → [350] YOUR PROXY MIDDLEWARE
         → [500] UserAgent → [550] Retry → [700] Cookies → [750] HttpProxy
         → Downloader

Alur response (menurun):
  Downloader → [750] HttpProxy → [700] Cookies → [550] Retry
             → [500] UserAgent → [350] YOUR PROXY MIDDLEWARE → [300] HttpAuth
             → [100] RobotsTxt → Spider

Berikut tabel priority default terbaru untuk middleware bawaan Scrapy (divalidasi terhadap 2.17.0):

MiddlewarePriority Default
RobotsTxtMiddleware100
HttpAuthMiddleware300
DownloadTimeoutMiddleware350
DefaultHeadersMiddleware400
UserAgentMiddleware500
RetryMiddleware550
RedirectMiddleware600
CookiesMiddleware700
HttpProxyMiddleware750
DownloaderStats850
HttpCacheMiddleware900

Saat RetryMiddleware menjadwalkan retry, ia menyalin request yang gagal—termasuk metadata-nya—dan request baru itu masuk lagi ke chain downloader middleware. Hubungan selector dengan priority 550 tidak otomatis menjamin rotasi. Rotasi hanya terjadi kalau kode selector mengenali bahwa itu retry dan sengaja menimpa nilai meta["proxy"] yang ikut tersalin. Priority 350 adalah tempat yang nyaman untuk selector karena ia berjalan sebelum langkah transport bawaan di 750, tapi itu bukan mekanisme rotasi itu sendiri.

Jalur request dan response Scrapy melalui priority 350, 550, dan 750, dengan retry 503 yang masuk kembali ke middleware chain

Kesalahan Umum Saat Menentukan Urutan Middleware

  • Menetapkan middleware kamu ke priority yang sama dengan HttpProxyMiddleware (750): Ini menciptakan race condition di mana urutan pemrosesan request ditentukan oleh ordering dict Scrapy, bukan logika kamu. Gejalanya: perilaku proxy kadang ada, kadang hilang, dan sulit dijelaskan.
  • Memakai setdefault() atau if "proxy" not in request.meta di selector yang berotasi: retry yang disalin akan tetap memakai proxy lama. Gejalanya: setiap retry mengulangi rute gagal yang sama. Solusinya: deteksi retry (misalnya retry_times > 0) dan ganti secara eksplisit nilai proxy yang dimiliki selector.
  • Menonaktifkan HttpProxyMiddleware sepenuhnya: Sebagian tutorial menyarankan kamu men-set "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": None karena “custom middleware sudah mengurusnya.” Tidak begitu — custom middleware kamu adalah selector, bukan layer transport. Kalau bawaan ini dimatikan, header autentikasi proxy tidak pernah ditambahkan, dan request bisa keluar tanpa autentikasi (atau tidak keluar sama sekali).

Langkah 4: Hentikan Hardcode Kredensial Proxy

Hampir semua tutorial proxy Scrapy yang ada di halaman teratas menulis http://username:password@proxy.example.com:8080 langsung ke file Python. Artinya secret kamu tersimpan selamanya di riwayat Git, muncul di setiap clone, fork, dan log dump kalau ada orang yang ceroboh pakai print().

Secara praktis ada tiga tingkat pendekatan:

MetodeKeamananFleksibilitasPaling Cocok Untuk
Hardcode di spider/settings.pyBuruk — secret tersimpan di repoRendahHanya testing lokal cepat
Variabel environment http_proxy (native Scrapy)Lebih baik — keluar dari codeRendah (satu proxy)Pipeline CI/CD, Docker
File .env + python-dotenv + from_crawlerTerbaik — keluar dari code, per environmentTinggi (banyak proxy, rotasi)Scraper produksi

Opsi ketiga layak dibangun dengan benar. Install python-dotenv, buat file .env (dan langsung tambahkan ke .gitignore — saya serius, lakukan ini sekarang):

PROXY_USER=myuser
PROXY_PASSWORD=my$ecret!Pass
PROXY_HOST=proxy.example.com
PROXY_PORT=8080

Muat di bagian atas settings.py:

from dotenv import load_dotenv
import os

load_dotenv()

PROXY_USER = os.getenv("PROXY_USER")
PROXY_PASSWORD = os.getenv("PROXY_PASSWORD")
PROXY_HOST = os.getenv("PROXY_HOST")
PROXY_PORT = os.getenv("PROXY_PORT")

Lalu baca secara aman di middleware menggunakan from_crawler — ini pola yang menyelesaikan kebingungan yang sering muncul di forum, seperti pertanyaan “gimana saya set ini sebelum menjalankan scrapy crawl kalau kredensialnya berubah tiap run?”:

import os
from urllib.parse import quote

class SecureProxyMiddleware:
    def __init__(self, user, password, host, port):
        self.user = quote(user, safe="")
        self.password = quote(password, safe="")
        self.host = host
        self.port = port

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        return cls(
            user=settings.get("PROXY_USER"),
            password=settings.get("PROXY_PASSWORD"),
            host=settings.get("PROXY_HOST"),
            port=settings.get("PROXY_PORT"),
        )

    def process_request(self, request, spider):
        proxy_url = f"http://{self.user}:{self.password}@{self.host}:{self.port}"
        request.meta["proxy"] = proxy_url

Perhatikan pemanggilan urllib.parse.quote() pada kredensial. Kalau password kamu mengandung @, : atau / (dan generator password memang suka memasukkan karakter ini), parsing URL akan rusak kecuali di-encode dulu dengan percent-encoding. Ini perbaikan satu baris yang bisa menyelamatkan kamu dari satu jam debugging memalukan terhadap error “invalid proxy URL” yang sebenarnya bukan berasal dari proxy yang invalid.

Simpan kredensial di luar log dan uji percent-encoding dengan nilai yang representatif — tapi palsu. Tunneling HTTPS, SOCKS5, dan kredensial non-Latin punya batasan spesifik handler; jangan berasumsi satu pola autentikasi berlaku untuk semuanya tanpa integration test yang jelas.

Alur aman dari file environment yang terkunci ke setting proxy ter-encode lalu masuk ke metadata request Scrapy

Langkah 5: Tambahkan Rotasi Proxy

Satu proxy — bahkan yang bagus — kalau dipakai untuk 5.000 request ke situs yang sama, lama-lama akan ditandai. Kamu butuh pool.

Opsi A — bangun sendiri. Ini memang sederhana:

import random

class RotatingProxyMiddleware:
    def __init__(self, proxy_pool):
        self.proxy_pool = proxy_pool

    @classmethod
    def from_crawler(cls, crawler):
        return cls(proxy_pool=crawler.settings.getlist("PROXY_POOL"))

    def process_request(self, request, spider):
        request.meta["proxy"] = random.choice(self.proxy_pool)

Ini cocok untuk penggunaan dasar, tapi sama sekali tidak tahu proxy mana yang benar-benar hidup. Kamu seperti lempar dadu setiap request.

Opsi B — gunakan scrapy-rotating-proxies. Paket pihak ketiga ini menambahkan deteksi ban dan backoff otomatis secara bawaan:

pip install scrapy-rotating-proxies

Saya perlu jujur di sini: rilis terbaru di PyPI adalah versi 0.6.2, bertanggal 2019, dan proyeknya diberi label Alpha. Belum tentu rusak di Scrapy modern, tapi “tidak aktif dipelihara sejak 2019” jelas beda dengan “sudah teruji untuk traffic produksi 2026.” Kunci versi, uji terhadap target kamu sendiri, dan jangan berasumsi ia mendukung endpoint proxy berautentikasi — pada dasarnya tidak sepenuhnya begitu.

Langkah 6: Bangun Proxy Middleware yang Tahan Gangguan (Deteksi Proxy Mati)

Bagian ini hampir selalu dilewati tutorial lain, padahal inilah yang membedakan demo dengan sistem yang tetap hidup saat crawl 6 jam tanpa pengawasan.

SkenarioYang ditunjukkan sebagian besar tutorialTambahan dari middleware ini
Proxy mengembalikan 407Tidak dibahasDiperlakukan sebagai kegagalan autentikasi proxy
Target mengembalikan 403/429Sering digabungkanFeedback kebijakan/rate limit dipisahkan dari kesehatan proxy
Proxy timeoutTidak dibahasThreshold timeout yang bisa diatur, penurunan skor kesehatan
Semua proxy matiTidak dibahasFallback yang aman atau crawl dijeda dengan warning tercatat
Proxy flapping (intermiten)Tidak dibahasMasa cooldown sebelum dimasukkan lagi ke pool
import time
import random
from scrapy.exceptions import IgnoreRequest

class FaultTolerantProxyMiddleware:
    MAX_FAILURES = 3
    COOLDOWN_SECONDS = 300

    def __init__(self, proxy_pool):
        self.pool = {p: {"failures": 0, "banned_until": 0} for p in proxy_pool}

    @classmethod
    def from_crawler(cls, crawler):
        return cls(proxy_pool=crawler.settings.getlist("PROXY_POOL"))

    def _healthy_proxies(self):
        now = time.time()
        return [p for p, s in self.pool.items() if s["banned_until"] < now]

    def process_request(self, request, spider):
        healthy = self._healthy_proxies()
        if not healthy:
            spider.logger.warning("Semua proxy tidak sehat — crawl dijeda")
            raise IgnoreRequest("Tidak ada proxy sehat yang tersedia")
        request.meta["proxy"] = random.choice(healthy)

    def process_response(self, request, response, spider):
        proxy = request.meta.get("proxy")
        if proxy and response.status == 407:
            self._mark_failure(proxy)
        return response

    def process_exception(self, request, exception, spider):
        proxy = request.meta.get("proxy")
        if proxy:
            self._mark_failure(proxy)

    def _mark_failure(self, proxy):
        state = self.pool[proxy]
        state["failures"] += 1
        if state["failures"] >= self.MAX_FAILURES:
            state["banned_until"] = time.time() + self.COOLDOWN_SECONDS
            state["failures"] = 0

Beberapa catatan dari pengalaman membangun ini: jangan menganggap setiap 403 sebagai bukti proxy-nya mati — RFC 9110 mendefinisikan 403 sebagai “server memahami tetapi menolak,” yang bisa saja berarti header atau sesi kamu terlihat mencurigakan, bukan proxynya. Sebaliknya, 407 berarti proxy secara spesifik menolak autentikasi kamu — sinyalnya lebih kuat dan lebih spesifik. Mencampur dua sinyal ini ke satu bucket adalah cara orang membuang proxy sehat tanpa alasan.

Buat default retry transient Scrapy tetap eksplisit di produksi supaya reviewer bisa melihat kebijakannya:

RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429]
RETRY_TIMES = 2

Itu adalah default Scrapy 2.17. Jangan asal tambahkan 403 atau 407: 403 adalah penolakan target dengan banyak kemungkinan penyebab, sedangkan 407 adalah masalah autentikasi proxy yang tidak akan diperbaiki oleh retry request generik. Kalau kontrak target tertentu memang membenarkan retry status lain, dokumentasikan alasannya dan uji secara terpisah.

Penanganan terpisah untuk gagal autentikasi 407, rate limit 429, retry 503, sukses 200, dan gerbang tertutup saat proxy tidak tersedia

Langkah 7: Pola Proxy-on-Retry yang Terukur

Sebagian target yang diizinkan bisa mengembalikan konten valid secara langsung, lalu baru butuh proxy setelah menerima response sementara yang terdokumentasi. Ini bisa mengurangi byte yang diproksikan, tapi tidak ada persentase penghematan universal yang bisa dipertahankan secara teknis, maupun tingkat keberhasilan direct request yang berlaku umum. Ukur workload kamu sendiri sebelum memakai pola ini.

Gunakan helper publik Scrapy get_retry_request() dan batasi eskalasi hanya pada status spesifik target yang sudah kamu klasifikasikan. Contoh ini memperlakukan 429 dan 503 sebagai sinyal tekanan yang bisa di-retry; 403 dan 407 sengaja tidak dimasukkan.

from scrapy.downloadermiddlewares.retry import get_retry_request

class CostAwareEscalationMiddleware:
    def process_response(self, request, response, spider):
        if response.status not in {429, 503}:
            return response

        retry = get_retry_request(
            request,
            spider=spider,
            reason=f"proxy_escalation_{response.status}",
            max_retry_times=2,
        )
        if retry is None:
            return response

        current_tier = request.meta.get("proxy_tier", "direct")
        if current_tier == "direct":
            retry.meta["proxy"] = spider.settings["DATACENTER_PROXY"]
            retry.meta["proxy_tier"] = "datacenter"
        elif current_tier == "datacenter":
            retry.meta["proxy"] = spider.settings["RESIDENTIAL_PROXY"]
            retry.meta["proxy_tier"] = "residential"
        else:
            return response
        return retry

Catat direct valid-content rate, proxied valid-content rate, byte per record sukses, retry per sukses, dan tambahan latensi. Desain direct-first hanya layak kalau akses direct memang diizinkan dan sistem benar-benar fail closed saat proxy dibutuhkan. Penghematan yang valid adalah penurunan terukur pada traffic yang diproksikan — bukan persentase yang diasumsikan.

Kapan Manajemen Proxy DIY Tidak Lagi Layak

Saya ingin jujur, bukan seolah-olah seluruh artikel ini tidak penting: semua di atas adalah engineering yang nyata dan berguna, dan untuk banyak proyek — crawl volume tinggi, pipeline kustom, atau apa pun yang butuh kontrol penuh atas penjadwalan request — itu memang pilihan yang tepat.

Tapi kalau tujuan kamu sebenarnya adalah “mengambil data terstruktur dari halaman ini” bukan “mengoperasikan infrastruktur proxy,” extraction API bisa jadi batas yang lebih masuk akal. Dokumentasi POST /extract milik Thunderbit saat ini menerima URL halaman dan JSON Schema opsional; kalau schema tidak diberikan, layanan bisa membangunnya dari konten halaman. Endpoint ini juga menyediakan mode render none, basic, dan full, beserta kontrol timeout dan waktu tunggu setelah load. Ekstraksi berbasis prompt saja bukan bagian dari permukaan request yang didukung saat ini, jadi bangun integrasi produksi di sekitar kontrak schema yang terdokumentasi. Ini memindahkan antarmuka ekstraksi ke balik satu request; bukan berarti menjanjikan hasil universal untuk semua target anti-bot atau CAPTCHA.

FaktorDIY Scrapy + ProxyEkstraksi berbasis API (mis. Thunderbit)
Upaya setupTinggi — middleware, rotasi, logika retryRendah — satu API call dengan schema
Perilaku jaringan/renderingKamu mengatur handler, proxy, header, dan delayDikendalikan lewat opsi API yang terdokumentasi
PemeliharaanKamu menangani selector, kesehatan pool, dan perubahan targetKamu menangani kualitas schema, validasi, dan perilaku integrasi
Model biayaBiaya proxy + komputasi + waktu engineeringDokumen saat ini mencantumkan 20 unit per halaman (dicek 2026-08-10)
KontrolPenuh — pipeline kustom, chain middlewareTerbatas pada kemampuan API
Paling cocok untukCrawl kompleks, volume tinggi, logika kustomEkstraksi terarah, prototyping, enrichment

Kalau kamu terutama mengekstrak halaman terstruktur untuk daftar prospek, data produk, atau riset, jalankan pilot representatif dengan Thunderbit Chrome Extension atau API, lalu bandingkan record valid, latensi, unit, dan waktu pemeliharaan. Kalau proyek kamu butuh graph crawl kustom dan kontrol pipeline, Scrapy tetap lebih cocok.

Pelajari Lebih Lanjut

Tips & Kesalahan Umum

  • Tip: Uji proxy ke httpbin.org/ip sebelum mengarahkannya ke target asli. Ini cara tercepat memastikan routing berjalan sebelum kamu menambah kompleksitas di atasnya.
  • Kesalahan: Menaruh proxy di request.headers alih-alih request.meta. Ini bug yang sering banget terjadi karena kelihatannya mirip typo — HttpProxyMiddleware cuma membaca meta["proxy"], dan percobaan berbasis header akan gagal diam-diam tanpa error yang jelas.
  • Kesalahan: Menganggap konfigurasi proxy HTTP dan HTTPS selalu identik. URL proxy HTTP yang mengarah ke destination HTTPS umumnya berjalan lewat CONNECT tunneling di handler yang kompatibel, tapi memakai skema https:// untuk endpoint proxy itu sendiri adalah konfigurasi yang berbeda dan lebih jarang didukung — jangan disamakan.
  • Tip: Kalau kamu butuh dukungan SOCKS5, cek dulu kemampuan download handler pada versi Scrapy kamu. Scrapy 2.17 punya Httpx handler eksperimental yang menambahkan dukungan SOCKS5 lewat httpx[socks], tapi statusnya masih experimental — jangan jadikan ini dependensi produksi tanpa pengujian sendiri.

Metode Alternatif

Selain scrapy-rotating-proxies, beberapa tim memilih mengalirkan seluruh logika proxy lewat gateway provider — satu URL proxy tempat vendor menangani rotasi, session stickiness, dan geo-targeting di belakang layar. Pendekatan ini mengurangi kode middleware, tapi mengorbankan sedikit kontrol, dan layak dibandingkan biayanya dengan pool yang dikelola sendiri sebelum kamu membangunnya dari nol.

Kesimpulan

Menetapkan proxy di Scrapy cuma butuh satu baris. Tapi supaya setup itu tahan menghadapi crawl produksi sungguhan, kamu perlu kebijakan kegagalan yang jelas, kredensial yang terlindungi, batas handler yang sudah diuji, dan kode selector yang secara sengaja mengganti metadata proxy yang tersalin saat retry. Kalau kamu cuma membawa dua kebiasaan dari artikel ini, jadikan ini: fail closed saat proxy dibutuhkan, dan jangan pernah commit password proxy ke file Python.

FAQ

Bagaimana cara menyiapkan custom proxy di Scrapy dengan autentikasi?
Gunakan format URL protocol://username:password@host:port, tapi percent-encode dulu username dan password dengan urllib.parse.quote() kalau ada karakter khusus. Untuk produksi, baca kredensial lewat classmethod from_crawler yang mengambil dari environment variables, bukan hardcode.

Priority number berapa yang sebaiknya dipakai untuk custom proxy middleware di Scrapy?
350 adalah priority selector yang umum karena berjalan sebelum HttpProxyMiddleware di 750. Namun angka ini tidak menjamin rotasi. Retry baru akan memakai proxy segar hanya kalau selector mengenali request retry yang disalin dan menimpa nilai meta["proxy"] sebelumnya.

Bagaimana cara menangani proxy mati di Scrapy secara otomatis?
Bangun middleware yang melacak jumlah kegagalan per proxy di process_response dan process_exception, menghapus proxy dari pool aktif setelah melewati ambang gagal, lalu menambahkannya lagi setelah masa cooldown, bukan memblokirnya selamanya.

Bisakah saya memakai Scrapy dengan proxy SOCKS5?
Scrapy 2.17 punya dokumentasi dukungan SOCKS5 di HttpxDownloadHandler eksperimental jika httpx[socks] dipasang. Default handler HTTP/1.1 tidak mendukung proxy SOCKS. Pin handler/version dan jalankan integration test sebelum menganggap jalur ini siap produksi.

Seberapa besar penghematan biaya proxy-on-retry yang benar-benar bisa didapat?
Tidak ada persentase universal. Ukur sendiri proporsi request yang secara sah mengembalikan konten valid langsung, byte yang lewat tiap tier proxy, retry per record sukses, dan tambahan latensi. Pengurangan terukur pada byte yang diproksikan adalah penghematan kamu; kalau akses direct-first tidak diizinkan atau tidak valid, jangan pakai pola ini.

Ke
Ke
CTO di Thunderbit | Senior Data Scientist & Expert ML Dengan pengalaman hampir satu dekade di bidang machine learning dan data science, Ke Shen adalah lulusan Columbia University dan mantan Senior Data Scientist di Walmart Labs. Dengan keahlian mendalam yang diakui sejawat dalam Python, R, Java, dan Statistik, ia membagikan wawasan teruji lapangan tentang bagaimana membawa algoritma AI yang kompleks dari teori ke arsitektur siap produksi.
Topics
Scrapy proxy middlewarePython web scrapingProxy rotation
Daftar Isi
Thunderbit · Agen data web AI

Ekstrak data dari halaman apa pun dalam 1 klik

Dipercaya oleh 250.000+ pengguna
tersedia paket gratis
Dari halaman web ke spreadsheet
Jelaskan apa yang kamu butuhkan — AI Agent Thunderbit akan men-scrape dan mengekspornya ke Excel, Google Sheets, Airtable, atau Notion. Gratis untuk memulai.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week