La version la plus simple#
Classez la réponse avant de réessayer. Un 403 peut indiquer une règle d'accès qu'une autre IP ne résoudra pas. Pour 429, respectez Retry-After et réduisez le taux de requêtes ; utilisez une interruption limitée en cas de connexion temporaire ou de pannes de serveur. Réessayez les opérations de changement d'état uniquement lorsque vous pouvez empêcher les actions en double.
import scrapy
PROXY = "http://USER-cc-us:PASS@res.proxy-cyber.com:9000"
class PricesSpider(scrapy.Spider):
name = "prices"
start_urls = ["https://example.com/catalog"]
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(url, meta={"proxy": PROXY})
def parse(self, response):
for href in response.css("a.product::attr(href)").getall():
yield response.follow(href, callback=self.parse_product, meta={"proxy": PROXY})
def parse_product(self, response):
yield {"url": response.url, "price": response.css(".price::text").get()}Un middleware pour les sessions collantes par élément#
import hashlib
class Proxy CyberMiddleware:
GATEWAY = "res.proxy-cyber.com:9000"
def __init__(self, user, password, country):
self.user, self.password, self.country = user, password, country
@classmethod
def from_crawler(cls, crawler):
s = crawler.settings
return cls(s.get("KEY_PROXY_USER"), s.get("KEY_PROXY_PASS"), s.get("KEY_PROXY_COUNTRY", "us"))
def process_request(self, request, spider):
# Sticky when the request carries a session key (e.g. one per product flow), rotating otherwise
key = request.meta.get("session_key")
user = f"{self.user}-cc-{self.country}"
if key:
sid = hashlib.sha1(key.encode()).hexdigest()[:12]
user += f"-sid-{sid}-ttl-10m"
request.meta["proxy"] = f"http://{user}:{self.password}@{self.GATEWAY}"DOWNLOADER_MIDDLEWARES = {
"myproject.middlewares.Proxy CyberMiddleware": 350, # before HttpProxyMiddleware (750)
}
KEY_PROXY_USER = "USER"
KEY_PROXY_PASS = "PASS"
KEY_PROXY_COUNTRY = "de"
CONCURRENT_REQUESTS = 32
CONCURRENT_REQUESTS_PER_DOMAIN = 8
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_TARGET_CONCURRENCY = 4.0
DOWNLOAD_TIMEOUT = 45
RETRY_ENABLED = True
RETRY_TIMES = 2
RETRY_HTTP_CODES = [408, 429, 500, 502, 503, 504, 522, 524]
COMPRESSION_ENABLED = TrueLa réutilisation des connexions et l'attribution des adresses IP sont des contrôles différents. Une session client réutilise les sockets ; seule la passerelle attribuée détermine le comportement de rotation et de session persistante. Utilisez les paramètres de session fournis avec votre service et vérifiez la sortie sur plusieurs requêtes. La fermeture d'un socket ou l'envoi de Connection: close ne garantit pas une IP différente.
Réduire la facture#
- Scrapy ne charge pas d'images ou de scripts ; HTML et JSON uniquement, donc une page coûte sa taille HTML.
- Activer la compression (par défaut) et éviter
Splashou le rendu du navigateur, sauf si les données en ont besoin. - Cacher avec
HTTPCACHE_ENABLED = Truependant le développement afin que vous ne payiez pas pour récupérer les mêmes pages lors du débogage des sélecteurs.
Politesse par domaine#
Une piscine est un moyen d’attirer de nombreux visiteurs polis, et non un seul impoli. CONCURRENT_REQUESTS_PER_DOMAIN et AutoThrottle maintiennent chaque cible à un taux plausible par l'homme par sortie ; le politique d'utilisation acceptable interdit tout ce qui ressemble à une attaque.
Les questions que les gens posent#
Ai-je besoin de proxys rotatifs Scrapy ?
Pas avec une passerelle : la rotation se produit côté Proxy Cyber à chaque nouvelle connexion. Ce package gère des listes de proxys statiques ; avec res.proxy-cyber.com, il y a un proxy à configurer.
Comment puis-je utiliser un pays différent par demande ?
Définissez request.meta["country"] dans le spider et lisez-le dans le middleware pour créer le paramètre -cc- ; l'exemple utilise un seul paramètre par souci de concision.