Повтор GET-запроса в Scrapy через другой прокси
Используйте помощник повторных попыток Scrapy, чтобы запланировать новый запрос с новым прокси, соблюдая бюджет повторных попыток.
Изменение 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, а не обещания, что повтор произвольной отправленной транзакции безопасен.