Зміна response.request.meta змінює об'єкт Python. Щоб виконати ще одне завантаження, треба дати Scrapy інший Request для планування.

Для GET, який ваш callback явно вирішує повторити, публічний помічник повторних спроб Scrapy може зберегти облік спроб у новому запиті:

from scrapy.downloadermiddlewares.retry import get_retry_request

def retry_through(self, response, proxy_url):
    retry = get_retry_request(
        response.request,
        spider=self,
        reason='choose_another_proxy',
    )
    if retry is None:
        return None
    retry.meta['proxy'] = proxy_url
    retry.headers.pop('Proxy-Authorization', None)
    return retry

Це помічник павука. Викликач має повернути або зробити yield отриманого Request, коли той доступний. None означає, що помічник відмовився від ще однієї спроби в межах чинного ліміту.

Помічник повторних спроб копіює запит, оновлює лічильник спроб і задає поведінку планувальника, доречну для повтору. Якщо просто зробити yield того самого URL як звичайного нового запиту, можна натомість натрапити на фільтрацію дублікатів.

Використовуйте URL проксі, який підтримує ввімкнений HttpProxyMiddleware. Для повторів дозволених публічних GET-запитів неавтентифікований HTTP-кандидат зі списку HTTP-проксі може надати proxy_url. Очищення раніше прикріпленого поля proxy-authorization не дає заголовку старого посередника потрапити в цей вибір; дозвольте middleware вивести новий обліковий запис із нового URL проксі, коли це застосовно.

Тримайте цей вибір на рівні callback окремо від автоматичної обробки налаштованих збоїв у RetryMiddleware. Вирішіть, який шар володіє повторною спробою, щоб операція не витрачала два незалежні бюджети. Приклад стосується відтворюваної роботи GET, а не обіцянки, що повтор довільної надісланої транзакції безпечний.

Схожі статті