Pengaturan proxy Scrapy, menggunakan IP berbeda per permintaan dengan meta proxy
Panduan ini menjelaskan cara menghubungkan HTTP proxy Socks5Proxy ke meta proxy di Scrapy, downloader middleware untuk merotasi daftar yang diterima dari API per permintaan, dan pengaturan kecepatan yang sesuai dengan situs target.
Bagaimana Scrapy menangani proxy?
Scrapy memiliki HttpProxyMiddleware yang aktif secara default. Jika Anda menambahkan alamat proxy ke kunci meta proxy dalam permintaan, permintaan tersebut akan dikirim melalui proxy tersebut, dan username/password dalam alamat akan diubah oleh middleware menjadi header Proxy-Authorization. Alamat HTTPS melewati tunnel CONNECT.
Download handler default Scrapy mendukung HTTP proxy. Jika benar-benar membutuhkan SOCKS5, diperlukan handler terpisah, sehingga disarankan menggunakan port HTTP dari IP yang sama di Scrapy. IP yang terlihat oleh situs target tetap sama.
Contoh menggunakan IP 198.51.100.23, port HTTP 8000, username spx_user, password spx_pass.
pip install scrapy
scrapy startproject shop
cd shopBagaimana cara menambahkan proxy ke satu permintaan?
Tambahkan proxy ke meta saat membuat Request di start_requests. Gunakan cara yang sama saat meminta halaman berikutnya di callback. Untuk melanjutkan sesi yang sama, teruskan nilai proxy dari meta respons sebelumnya agar IP tetap sama.
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"])Bagaimana cara merotasi IP setiap permintaan?
Buat middleware downloader untuk memasukkan proxy berikutnya ke setiap permintaan sehingga Anda dapat melakukan rotasi tanpa mengubah kode spider. Middleware di bawah ini mengambil daftar dari API saat mulai dan membiarkan proxy di meta tetap jika sudah ada, memungkinkan penggunaan sesi tetap dan rotasi secara bersamaan.
Simpan API key di settings.py atau baca dari variabel lingkungan. Daftarkan dengan nomor lebih kecil dari HttpProxyMiddleware(750) agar middleware dasar memproses alamat yang dimasukkan oleh middleware.
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)SPX_API_KEY = "YOUR_API_KEY"
DOWNLOADER_MIDDLEWARES = {
"shop.middlewares.RotatingProxyMiddleware": 740,
}
CONCURRENT_REQUESTS = 32
CONCURRENT_REQUESTS_PER_DOMAIN = 16
DOWNLOAD_DELAY = 0.25
AUTOTHROTTLE_ENABLED = True
RETRY_TIMES = 3
RETRY_HTTP_CODES = [429, 500, 502, 503, 504, 522, 524, 408]
DOWNLOAD_TIMEOUT = 30Bagaimana menyesuaikan kecepatan dan percobaan ulang?
CONCURRENT_REQUESTS_PER_DOMAIN adalah jumlah permintaan simultan ke domain yang sama. Semakin banyak IP proxy, semakin tinggi nilai ini bisa dinaikkan tanpa menambah beban per IP. Misalnya, dengan 500 IP dan 50 permintaan simultan, setiap IP rata-rata hanya digunakan sekali setiap 10 permintaan.
Dengan mengaktifkan AUTOTHROTTLE, interval permintaan disesuaikan secara otomatis dengan kecepatan respons. Jika respon 429 meningkat, gunakan RETRY_HTTP_CODES untuk mencoba lagi, tetapi ada juga cara menghapus proxy dari meta saat mencoba lagi agar middleware memasukkan proxy berikutnya.
Menambahkan langkah pemeriksaan apakah hasil yang dikumpulkan adalah halaman aktual bukan halaman konfirmasi dalam pipeline akan meningkatkan kualitas data. Jika respons tidak memiliki elemen yang diinginkan, minta ulang dengan IP lain.
- Atur jumlah permintaan simultan per domain sesuai jumlah IP
- Interval otomatis dengan AUTOTHROTTLE sesuai kecepatan respons
- 429 dan 5xx, coba lagi dengan IP lain
- Memfilter halaman verifikasi dengan pemeriksaan konten respons
Apa yang berubah jika terhubung dengan IP authorization?
Jika Anda mendaftarkan IPv4 server yang menjalankan Scrapy di dashboard, Anda dapat menggunakannya tanpa username dan password, seperti http://198.51.100.23:8000 di meta proxy. Anda juga bisa mendapatkan daftar dengan format=ip:port. Jika Anda menjalankan spider di beberapa server, daftarkan semua IP server tersebut. Anda dapat mendaftarkan hingga 10 IP.
Bagaimana cara mengikat permintaan yang membutuhkan sesi ke IP yang sama?
Untuk alur yang memerlukan kelanjutan cookie seperti login atau keranjang belanja, Anda harus menggunakan IP yang sama. Masukkan meta proxy langsung pada permintaan pertama, dan saat membuat permintaan berikutnya di callback, teruskan nilai proxy dari response.meta tanpa diubah oleh middleware siklus. Jika Anda juga menggunakan kunci meta cookiejar Scrapy, cookie akan dipisahkan per sesi.
Dengan memasangkan satu proxy dan satu set cookie per sesi, beberapa sesi dapat berjalan bersamaan tanpa tercampur.
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"])Bagaimana cara mengistirahatkan proxy yang gagal sebentar?
Jika Anda menerima respons 403 atau 429 di middleware process_response, Anda dapat membuat proxy tersebut beristirahat selama beberapa menit dan mengirimkan permintaan yang sama ke proxy lain. Salin permintaan, hapus proxy dari meta, aktifkan dont_filter, lalu kembalikan agar proxy berikutnya dapat mengambil alih.
Mengelola daftar proxy istirahat dan waktu penggunaan ulang dengan kamus lebih sederhana. Tidak menggunakan IP yang sama segera memberi waktu bagi batasan situs target untuk direset.
Apa yang harus diatur untuk menghemat bandwidth di Scrapy?
Scrapy secara default hanya menerima HTML sehingga menggunakan bandwidth jauh lebih sedikit dibandingkan alat browser. Dengan HttpCompressionMiddleware yang aktif secara default untuk menerima respons terkompresi, jumlah transfer data lebih berkurang. Ini alasan mengapa banyak halaman dapat dikumpulkan dalam bandwidth bulanan shared plan.
Untuk menghindari menerima halaman yang sama berulang kali, aktifkan HTTPCACHE_ENABLED selama pengembangan agar tidak memanggil situs target dan proxy setiap kali pengujian. Dalam operasional, pertahankan penyaringan alamat duplikat (default aktif), dan gunakan dont_filter hanya untuk permintaan yang benar-benar perlu diterima kembali.
Penting juga untuk membatasi jangkauan mengikuti tautan ke halaman turunan yang tidak perlu. Menentukan cakupan pengumpulan dengan jelas akan menghemat waktu, bandwidth, dan beban situs target.
Bagaimana cara menyelesaikan masalah yang sering terjadi?
Jika muncul respon 407, periksa username dan password dalam alamat. Jika password mengandung karakter khusus, gunakan percent encoding. TunnelError terjadi saat proxy tidak menerima permintaan CONNECT, pastikan port yang digunakan adalah port HTTP.
Jika semua permintaan keluar dari IP yang sama, mungkin middleware Anda berada setelah HttpProxyMiddleware atau spider Anda secara langsung menambahkan meta proxy. Periksa urutan di settings.py dan kode spider Anda.