Socks5Proxy

Konfiguracja proxy w Scrapy, używanie różnych IP dla każdego żądania z meta proxy

Ten przewodnik pokazuje, jak podłączyć HTTP proxy Socks5Proxy w Scrapy przez meta proxy, middleware rotujące listę z API oraz ustawienia prędkości dla danej strony.

Jak Scrapy obsługuje proxy?

Scrapy ma domyślnie włączone HttpProxyMiddleware. Jeśli dodasz adres proxy do słownika meta żądania, żądanie zostanie wysłane przez to proxy, a nazwa użytkownika i hasło z adresu zostaną przekonwertowane na nagłówek Proxy-Authorization przez middleware. Adresy HTTPS przechodzą przez tunel CONNECT.

Domyślny handler pobierania w Scrapy obsługuje proxy HTTP. Jeśli potrzebujesz SOCKS5, wymagany jest osobny handler, dlatego zalecamy używanie portu HTTP tego samego IP w Scrapy. IP widoczne dla strony docelowej jest takie samo.

Przykładowe dane: IP 198.51.100.23, port HTTP 8000, nazwa użytkownika spx_user, hasło spx_pass.

pip install scrapy
scrapy startproject shop
cd shop

Jak dodać proxy do pojedynczego żądania?

Wystarczy dodać proxy do meta podczas tworzenia Request w start_requests. W callbacku dla kolejnych żądań użyj tej samej metody. Aby utrzymać tę samą sesję, przekaż wartość proxy z meta poprzedniej odpowiedzi, co zapewni utrzymanie tego samego 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"])

Jak rotować IP dla każdego żądania?

Tworząc middleware pobierający, możesz dodać kolejne proxy do wszystkich żądań bez zmiany kodu pająka. Poniższy middleware pobiera listę przez API przy starcie i pozostawia istniejące proxy w meta, umożliwiając jednoczesne użycie stałych sesji i rotacji.

Klucz API należy umieścić w settings.py lub odczytać ze zmiennych środowiskowych. Zarejestruj go z numerem niższym niż domyślny HttpProxyMiddleware(750), aby middleware przetworzył adres wprowadzony przez podstawowe 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)

Jak dostosować prędkość i ponowne próby?

CONCURRENT_REQUESTS_PER_DOMAIN to liczba równoczesnych żądań do tej samej domeny. Im więcej IP proxy, tym bardziej możesz zwiększyć tę wartość bez zwiększania obciążenia na jedno IP. Na przykład, wysyłając 50 równoczesnych żądań przez 500 IP, każde IP będzie używane średnio raz na 10 żądań.

Włączając AUTOTHROTTLE, automatycznie dostosowujesz odstępy żądań do szybkości odpowiedzi. Jeśli odpowiedzi 429 się zwiększają, spróbuj ponownie z RETRY_HTTP_CODES, ale usuń proxy z meta przy ponownych próbach, aby middleware użyło następnego proxy.

Dodaj do pipeline’a sprawdzanie, czy zebrane wyniki to rzeczywiste strony, a nie potwierdzenia. Jeśli odpowiedź nie zawiera wymaganych elementów, ponów żądanie z innym IP.

  • Dostosuj liczbę równoczesnych żądań na domenę do liczby IP
  • AUTOTHROTTLE dostosowuje odstępy do szybkości odpowiedzi
  • 429 i 5xx: Spróbuj ponownie z innym IP
  • Filtrowanie CAPTCHA przez sprawdzanie treści odpowiedzi

Co się zmienia przy połączeniu z uwierzytelnianiem IP?

Zarejestruj IPv4 serwera z Scrapy w panelu, aby używać proxy HTTP jak http://198.51.100.23:8000 bez loginu. Możesz też pobierać listę w formacie ip:port. Jeśli uruchamiasz pająki na wielu serwerach, zarejestruj wszystkie ich IP (maksymalnie 10).

Jak grupować żądania wymagające sesji pod tym samym IP?

W przepływach wymagających ciągłości ciasteczek, takich jak logowanie lub koszyk zakupowy, należy używać tego samego IP. W pierwszym żądaniu dodaj meta proxy bezpośrednio, a w callbacku przekaż wartość proxy z response.meta do następnego żądania, aby middleware rotacyjny go nie zmienił. Używając klucza meta cookiejar w Scrapy, ciasteczka również będą oddzielone dla każdej sesji.

Jeśli przypiszesz jeden proxy i jeden zestaw ciasteczek do jednej sesji, możesz uruchomić wiele sesji jednocześnie bez mieszania ich ze sobą.

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"])

Jak tymczasowo wyłączyć nieudane proxy?

Jeśli middleware process_response otrzyma odpowiedź 403 lub 429, możesz dać temu proxy kilka minut przerwy i wysłać to samo żądanie przez inne proxy. Skopiuj żądanie, usuń proxy z meta, włącz dont_filter i zwróć je, aby kolejne proxy mogło je przejąć.

Proste zarządzanie listą proxy do odpoczynku i czasem ponownego użycia. Unikaj natychmiastowego ponownego użycia tego samego IP, aby strony docelowe miały czas na zdjęcie ograniczeń.

Jak oszczędzać przepustowość w Scrapy?

Scrapy domyślnie pobiera tylko HTML, więc zużywa znacznie mniej przepustowości niż narzędzia przeglądarkowe. Dodatkowo HttpCompressionMiddleware jest domyślnie włączony, co zmniejsza ilość przesyłanych danych. Dlatego można zbierać wiele stron w ramach miesięcznego limitu przepustowości współdzielonego planu.

Aby uniknąć ponownego pobierania tej samej strony, włącz HTTPCACHE_ENABLED podczas rozwoju, aby nie odpytywać strony docelowej i proxy przy każdym teście. W produkcji utrzymuj filtrowanie zduplikowanych adresów (domyślnie włączone) i używaj dont_filter tylko dla żądań, które naprawdę muszą być ponownie pobrane.

Ważne jest też ograniczenie zakresu podążania za linkami, aby uniknąć rozpraszania się po niepotrzebnych podstronach. Jasne określenie zakresu zbierania danych skraca czas, zmniejsza obciążenie przepustowości i odciąża strony docelowe.

Jak rozwiązać częste problemy?

Jeśli otrzymasz odpowiedź 407, sprawdź nazwę użytkownika i hasło w adresie. Jeśli hasło zawiera znaki specjalne, musisz je zakodować procentowo. TunnelError oznacza, że proxy nie otrzymało żądania CONNECT, więc upewnij się, że używasz portu HTTP.

Jeśli wszystkie żądania wychodzą z tego samego IP, może to oznaczać, że middleware jest ustawiony po HttpProxyMiddleware lub spider bezpośrednio ustawia meta proxy. Sprawdź kolejność w settings.py i kod spidera.

Konfiguracja proxy w Scrapy, meta proxy i middleware rotacyjne | Socks5Proxy