Изменение 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, а не обещания, что повтор произвольной отправленной транзакции безопасен.

Похожие статьи