Scrapy proxy ayarları, meta proxy ile her istekte farklı IP kullanma
Bu rehber, Scrapy'ye Socks5Proxy'nin HTTP proxy'sini meta proxy olarak bağlama yöntemini, API ile alınan listeyi her istekte döndüren downloader middleware'ini ve hedef siteye uygun hız ayarlarını açıklar.
Scrapy proxy'leri nasıl işler?
Scrapy'de varsayılan olarak HttpProxyMiddleware etkindir. İsteklerin meta sözlüğüne proxy anahtarı ile adres eklediğinizde o istek ilgili proxy üzerinden gönderilir ve adresteki kullanıcı adı/şifre middleware tarafından Proxy-Authorization başlığına dönüştürülür. HTTPS adresleri CONNECT tüneli üzerinden iletilir.
Scrapy'nin varsayılan downloader handler'ı HTTP proxy'lerini destekler. SOCKS5 kesinlikle gerekiyorsa özel bir handler gerekir, bu nedenle Scrapy'de aynı IP'nin HTTP portunu kullanmanızı öneririz. Hedef sitede görünen IP aynı olacaktır.
Örnekte IP 198.51.100.23, HTTP port 8000, kullanıcı adı spx_user ve şifre spx_pass kullanılmaktadır.
pip install scrapy
scrapy startproject shop
cd shopBir isteğe proxy nasıl eklenir?
start_requests'te Request oluştururken meta'ya proxy ekleyin. Geri çağırma sırasında bir sonraki sayfayı isterken de aynı şekilde ekleyin. Aynı oturumu sürdürmeniz gerekiyorsa, önceki yanıtın meta'sından proxy değerini aynen geçirin, böylece aynı IP korunur.
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"])Her istekte IP nasıl değiştirilir?
Bir indirici ara katmanı oluşturarak tüm isteklere bir sonraki proxy'yi ekleyebilir ve örümcek kodunu değiştirmeden döngü yapabilirsiniz. Aşağıdaki ara katman başlangıçta API ile listeyi alır ve meta'da proxy zaten varsa olduğu gibi bırakarak oturum sabitleme ve döngüyü birlikte kullanmanızı sağlar.
API anahtarını settings.py'da saklayın veya ortam değişkenlerinden okuyun. Sıralama, temel HttpProxyMiddleware(750)'den önce bir sayı ile kaydedilmelidir ki, middleware'in eklediği adres temel middleware tarafından işlensin.
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 = 30Hız ve yeniden deneme ayarları nasıl yapılır?
CONCURRENT_REQUESTS_PER_DOMAIN, aynı alan adına aynı anda gönderilecek istek sayısıdır. Proxy IP'leri arttıkça bu değeri artırabilirsiniz, böylece tek bir IP'ye düşen yük aynı kalır. Örneğin, 500 IP ile 50 eş zamanlı istek gönderirseniz, bir IP ortalama 10 istekte bir kullanılır.
AUTOTHROTTLE açıkken, yanıt hızına göre istek aralığını otomatik ayarlar. 429 yanıtları artarsa, RETRY_HTTP_CODES ile yeniden deneyebilirsiniz, ancak yeniden deneme sırasında middleware'in bir sonraki proxy'yi eklemesi için meta'daki proxy'yi silme yöntemi de vardır.
Toplanan sonuçların onay sayfası değil gerçek sayfa olduğunu kontrol eden bir adım eklemek veri kalitesini artırır. İstenen öğelerin eksik olduğu yanıtlar için farklı bir IP ile yeniden istek göndermek yeterlidir.
- IP sayısına göre alan adı başına eşzamanlı istek sayısını ayarlama
- AUTOTHROTTLE ile yanıt hızına göre aralık
- 429 ve 5xx hatalarında farklı bir IP ile yeniden deneyin
- Yanıt içeriği kontrolü ile doğrulama ekranını filtreleme
IP yetkilendirme ile bağlanınca ne değişir?
Scrapy sunucunuzun IPv4 adresini kontrol paneline eklediğinizde, meta proxy'ye http://198.51.100.23:8000 gibi kullanıcı adı ve şifre olmadan ekleyebilirsiniz. Listeyi format=ip:port şeklinde de alabilirsiniz. Birden fazla sunucuda örümcek çalıştırıyorsanız, her sunucunun IP'sini ekleyin. En fazla 10 IP ekleyebilirsiniz.
Oturum gerektiren istekleri aynı IP'ye nasıl bağlarım?
Giriş veya alışveriş sepeti gibi çerezlerin devam ettiği akışlar için aynı IP kullanılmalıdır. İlk isteğe meta proxy'yi doğrudan ekleyin ve geri çağrıda bir sonraki isteği oluştururken response.meta'daki proxy değerini aynen aktarın, böylece döngüsel ara yazılım değiştirmez. Scrapy'nin cookiejar meta anahtarını birlikte kullanırsanız çerezler de oturum başına ayrılır.
Bir oturuma bir proxy ve bir çerez grubu atarsanız, birden fazla oturumu aynı anda çalıştırsanız bile birbirine karışmaz.
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"])Başarısız proxy'leri geçici olarak devre dışı bırakmak için ne yapmalı?
Middleware'ın process_response'unda 403 veya 429 yanıtı alırsanız, bu proxy'yi birkaç dakika dinlendirebilir ve aynı isteği başka bir proxy ile tekrar gönderebilirsiniz. İsteği kopyalayıp meta'daki proxy'yi silerek ve dont_filter'ı açarak geri döndürürseniz, bir sonraki proxy devreye girer.
Dinlenen proxy listesini ve yeniden kullanım zamanını sözlük şeklinde yönetmek basittir. Aynı IP'yi hemen yeniden kullanmamak hedef sitenin kısıtlamalarını aşmanıza yardımcı olur.
Scrapy'de bant genişliğinden tasarruf etmek için ne yapmalı?
Scrapy varsayılan olarak yalnızca HTML alır ve tarayıcı araçlarından çok daha az bant genişliği kullanır. HttpCompressionMiddleware varsayılan olarak etkin olduğu için sıkıştırılmış yanıtlar alınır ve aktarım miktarı daha da azalır. Paylaşımlı planların aylık bant genişliği sınırları içinde çok sayıda sayfa toplayabilmenizin nedeni budur.
Aynı sayfayı tekrar almamak için geliştirme sırasında HTTPCACHE_ENABLED'i açık tutun, böylece her testte hedef siteyi ve proxy'leri tekrar çağırmazsınız. Üretimde yinelenen adres filtrelemesini (varsayılan olarak açık) koruyun ve yalnızca gerçekten yeniden alınması gereken istekler için dont_filter kullanın.
Gereksiz alt sayfalara dağılmamak için bağlantı takip aralığını daraltmak da önemlidir. Toplama kapsamını net belirlemek, zaman, bant genişliği ve hedef sitenin yükünü azaltır.
Sık karşılaşılan sorunlar nasıl çözülür?
407 yanıtı alırsanız, adresteki kullanıcı adı ve şifreyi kontrol edin. Şifrede özel karakterler varsa, yüzde kodlaması yaparak eklemelisiniz. TunnelError, proxy'nin CONNECT isteğini alamadığı durumlarda olur, portun HTTP portu olduğunu kontrol edin.
Tüm istekler aynı IP'den çıkıyorsa, middleware sıra numarası HttpProxyMiddleware'den sonra olabilir veya örümcek doğrudan meta proxy ekliyor olabilir. settings.py sırasını ve örümcek kodunu birlikte kontrol edin.