Налаштування проксі в Scrapy: використання meta proxy для зміни IP для кожного запиту
Цей посібник пояснює, як підключити HTTP-проксі Socks5Proxy через meta proxy у Scrapy, як ротувати IP через API у завантажувальному middleware та налаштувати швидкість для цільового сайту.
Як Scrapy обробляє проксі?
У Scrapy за замовчуванням активовано HttpProxyMiddleware. Якщо вказати адресу проксі у meta-словнику запиту через ключ proxy, цей запит буде відправлено через вказаний проксі, а логін і пароль із адреси middleware автоматично перетворить на заголовок Proxy-Authorization. Для HTTPS використовується CONNECT-тунель.
Стандартний завантажувач Scrapy підтримує HTTP-проксі. Якщо вам обов’язково потрібен SOCKS5, знадобиться додатковий обробник, тому в Scrapy рекомендуємо використовувати HTTP-порт того самого IP. Цільовий сайт бачитиме ту саму IP-адресу.
У прикладі використовується IP 198.51.100.23, HTTP порт 8000, ім'я користувача spx_user, пароль spx_pass.
pip install scrapy
scrapy startproject shop
cd shopЯк додати проксі до одного запиту?
Додайте проксі до meta при створенні Request у start_requests. Для наступних сторінок у callback використовуйте той самий спосіб. Щоб зберегти сесію, передавайте значення proxy з meta попередньої відповіді.
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"])Як ротація IP для кожного запиту?
Створіть проміжну програмну прослойку для завантажувача, яка додаватиме наступний проксі до кожного запиту, щоб обходитися без зміни коду павука. Наведена нижче прослойка отримує список через API при запуску та залишає проксі в meta, якщо він уже є, що дозволяє використовувати фіксацію сесії та циклічний обмін одночасно.
Зберігайте API-ключі у settings.py або читайте їх зі змінних середовища. Реєструйте їх з числом, меншим за HttpProxyMiddleware(750), щоб базовий middleware обробляв адреси, вставлені 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 = 30Як налаштувати швидкість і повторні спроби?
CONCURRENT_REQUESTS_PER_DOMAIN - це кількість одночасних запитів до одного домену. Чим більше IP проксі, тим вище можна встановити це значення без збільшення навантаження на окремий IP. Наприклад, при 500 IP та 50 одночасних запитах кожен IP використовуватиметься в середньому лише раз на 10 запитів.
Увімкнувши AUTOTHROTTLE, ви автоматично регулюєте інтервал запитів залежно від швидкості відповіді. Якщо збільшується кількість відповідей 429, використовуйте RETRY_HTTP_CODES для повторних спроб, але видаляйте proxy з meta при повторних спробах, щоб middleware вставляв наступний проксі.
Додайте перевірку, чи є результат реальною сторінкою, а не сторінкою підтвердження, щоб покращити якість даних. Якщо відповідь не містить потрібних елементів, повторіть запит через інший IP.
- Налаштування кількості одночасних запитів на домен відповідно до кількості IP
- AUTOTHROTTLE: автоматичний інтервал залежно від швидкості відповіді
- 429 та 5xx: спробуйте з іншого IP
- Перевірка вмісту відповіді для фільтрації капчі
Що змінюється при підключенні через IP-авторизацію?
Якщо зареєструвати IPv4 сервера, де запущено Scrapy, на панелі керування, можна використовувати meta proxy без логіна та пароля, наприклад http://198.51.100.23:8000. Список також можна отримати у форматі ip:port. Якщо ви запускаєте павуків на кількох серверах, зареєструйте IP кожного сервера. Максимум можна зареєструвати 10 IP.
Як зв’язати запити, що потребують сесії, з одним IP?
Для потоків, де важлива послідовність кукі, наприклад, входу або кошика, використовуйте той самий IP. Додайте meta proxy безпосередньо до першого запиту, а в callback передайте значення proxy з response.meta до наступного запиту, щоб циклічний middleware не змінив його. Використання cookiejar meta ключа в Scrapy також дозволяє розділити кукі для кожної сесії.
Якщо зв’язати один проксі з одним набором cookies у сесії, ви можете запускати кілька сесій одночасно без змішування даних.
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"])Як тимчасово виключити невдалий проксі?
Якщо middleware process_response отримує відповіді 403 або 429, ви можете дати проксі-серверу кілька хвилин відпочинку та повторити запит через інший проксі. Скопіюйте запит, видаліть проксі з meta, увімкніть dont_filter і поверніть його - тоді буде використано наступний проксі.
Список проксі для відпочинку та час повторного використання можна керувати словником. Уникайте повторного використання IP, щоб дати сайтам час зняти обмеження.
Які налаштування допомагають економити пропускну здатність у Scrapy?
Scrapy за замовчуванням завантажує лише HTML, тому використовує значно менше пропускної здатності, ніж браузерні інструменти. Додатково він підтримує стиснення відповідей (HttpCompressionMiddleware), що ще більше зменшує обсяг переданих даних. Саме тому на спільних тарифах можна збирати багато сторінок у межах місячного ліміту.
Щоб уникнути повторного отримання однієї й тієї ж сторінки, увімкніть HTTPCACHE_ENABLED під час розробки. Це дозволить уникнути повторних викликів цільового сайту та проксі під час тестування. У робочому режимі зберігайте фільтрацію дублікатів адрес (увімкнена за замовчуванням) і використовуйте dont_filter лише для тих запитів, які дійсно потрібно повторити.
Важливо обмежити глибину парсингу, щоб уникнути переходу на непотрібні сторінки. Чіткі межі збору даних економлять час, трафік та навантаження на цільовий сайт.
Як вирішити поширені проблеми?
Якщо отримуєте відповідь 407, перевірте ім'я користувача та пароль у URL. Якщо пароль містить спеціальні символи, використовуйте процентне кодування. TunnelError означає, що проксі не приймає CONNECT-запити - перевірте, чи використовуєте HTTP-порт.
Якщо всі запити йдуть з одного IP, це може бути через те, що порядковий номер middleware знаходиться після HttpProxyMiddleware або spider безпосередньо використовує meta proxy. Перевірте порядок у settings.py та код spider.