Многие разработчики предпочитают использовать библиотеку Requests в Python для веб-скрапинга, благодаря ее простоте и эффективности. Однако, несмотря на все ее преимущества, библиотека Requests имеет ограничения, особенно когда речь идет о неудачных запросах, которые могут серьезно повлиять на стабильность процесса извлечения данных. В этой статье мы рассмотрим, как реализовать повторные запросы в Python, что позволит более эффективно обрабатывать HTTP-ошибки и значительно повысить надежность выполняемых скриптов веб-скрапинга.
Перед началом работы убедитесь, что у вас установлен Python и выбранная среда разработки. После этого установите библиотеку Requests, если она еще не установлена.
pip install requests
Далее, попробуем отправить запрос к сайту example.com, используя модуль Requests в Python. Ниже представлена простая функция, которая выполняет это действие:
import requests
def send_request(url):
"""
Отправляет HTTP GET запрос на указанный URL и выводит код состояния ответа.
Parameters:
url (str): URL для отправки запроса.
"""
response = requests.get(url)
print('Response Status Code: ', response.status_code)
send_request('https://example.com')
Результат выполнения кода показан ниже:
Рассмотрим подробнее, что представляют собой HTTP-статус коды.
Серверы используют HTTP-статус коды для информирования о результате обработки запросов. Вот краткий обзор различных кодов состояния:
В нашем примере статус код 200 свидетельствует о том, что запрос к https://example.com был успешно обработан.
Статус коды могут также помочь в обнаружении активности ботов и указывать на ограничения доступа, вызванные схожей с действиями ботов активностью.
Ниже представлен краткий обзор таких кодов:
При работе с сетевыми запросами неизбежны случаи, когда запросы не удаются из-за временных сетевых сбоев или перегрузки сервера. Для повышения стабильности скрапинга, можно реализовать механизм повторных попыток.
Функция “send_request_with_basic_retry_mechanism” выполняет HTTP GET-запросы по заданному URL с базовым механизмом повторных попыток, который срабатывает только в случае возникновения исключений, связанных с сетью или запросом, таких как ошибка подключения. Она повторяет запрос количество раз, определяемое параметром “max_retries”. Если все попытки завершаются неудачей с таким исключением, функция генерирует последнее встреченное исключение.
import requests
import time
def send_request_with_basic_retry_mechanism(url, max_retries=2):
"""
Отправляет HTTP GET-запрос на URL с базовым механизмом повторных попыток.
Parameters:
url (str): URL для отправки запроса.
max_retries (int): Максимальное количество попыток повторного запроса.
Raises:
requests.RequestException: Генерирует последнее исключение, если все попытки неудачны.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
print('Response status: ', response.status_code)
break # Выйти из цикла, если запрос выполнен успешно
except requests.RequestException as error:
print(f"Attempt {attempt+1} failed:", error)
if attempt < max_retries - 1:
print(f"Retrying...")
time.sleep(delay) # Подождите перед повторной попыткой
else:
print("Max retries exceeded.")
# Сгенерируйте последнее исключение, если достигнуто максимальное количество попыток
raise
send_request_with_basic_retry_mechanism('https://example.com')
Для более надёжного скрапинга данных с веб-сайтов, использующих механизмы обнаружения ботов, необходимо адаптировать наш подход к реализации повторных попыток. В случаях, когда запросы могут быть заблокированы из-за подозрений в бот-активности или из-за временных проблем с сетью или сервером, полезно иметь механизм, который позволяет адаптивно управлять повторными попытками.
Функция “send_request_with_advance_retry_mechanism” реализует такой подход, отправляя HTTP GET-запросы на заданный URL с возможностью настройки количества повторных попыток и задержки между ними. Эта функция не только повторяет запросы при возникновении ошибок, но и учитывает необходимость снижения частоты запросов, чтобы избежать обнаружения анти-ботовыми системами безопасности.
Параметр задержки играет ключевую роль в механизме повторных попыток, поскольку он предотвращает чрезмерную нагрузку на сервер путем отправки множественных запросов в короткие временные промежутки. Вместо этого задержка между попытками дает серверу достаточно времени для обработки запросов, создавая впечатление, что за запросами стоит человек, а не автоматизированная система.
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1):
"""
Отправляет HTTP GET-запрос на указанный URL с продвинутым механизмом повторных попыток.
Parameters:
url (str): URL, на который отправляется запрос.
max_retries (int): Максимальное количество повторных попыток запроса. По умолчанию - 3.
delay (int): Задержка (в секундах) между попытками. По умолчанию - 1.
Raises:
requests.RequestException: Генерирует последнее исключение, если все попытки неудачны.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
# Сгенерировать исключение для статус-кодов 4xx или 5xx
response.raise_for_status()
print('Response Status Code:', response.status_code)
except requests.RequestException as e:
# Вывести сообщение об ошибке и номер попытки, если запрос не удался
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
# Вывести сообщение о повторной попытке и подождать перед повторным запросом
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
# Если превышено максимальное количество попыток, вывести сообщение и снова сгенерировать исключение
print("Max retries exceeded.")
raise
# Пример использования
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Ниже представлен корректный код, устраняющий эти недостатки:
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
"""
Отправляет HTTP GET-запрос на указанный URL с продвинутым механизмом повторных попыток.
Parameters:
url (str): URL, на который отправляется запрос.
max_retries (int): Максимальное количество раз, которое запрос может быть повторен. По умолчанию 3.
delay (int): Задержка (в секундах) между попытками. По умолчанию 1.
min_content_length (int): Минимальная длина содержимого ответа, чтобы считать его действительным. По умолчанию 10.
Raises:
requests.RequestException: Генерирует последнее исключение, если все попытки неудачны.
"""
for attempt in range(max_retries):
try:
response = requests.get(url)
# Сгенерировать исключение для статус-кодов 4xx или 5xx
response.raise_for_status()
# Проверить, равен ли статус-код ответа 404
if response.status_code == 404:
print("404 Error: Not Found")
break # Выход из цикла при ошибках 404
# Проверить, меньше ли длина текста ответа указанной минимальной длины содержимого
if len(response.text) < min_content_length:
print("Response text length is less than specified minimum. Retrying...")
time.sleep(delay)
continue # Повторить запрос
print('Response Status Code:', response.status_code)
# Если условия выполнены, выйти из цикла
break
except requests.RequestException as e:
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
print("Max retries exceeded.")
# Сгенерировать последнее исключение, если достигнуто максимальное количество попыток
raise
# Пример использования
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
В случае с такими ошибками 429 too many requests, использование прокси с ротацией может помочь распределить ваши запросы и избежать ограничений по частоте запросов.
Ниже приведен код, реализующий продвинутую стратегию повторных попыток вместе с использованием прокси. Важно использовать резидентские или мобильные прокси для веб-скрапинга, поскольку они позволяют гибко настраивать алгоритм ротации и предоставляют обширный пул адресов.
import requests
import time
def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
"""
Отправляет HTTP GET-запрос на указанный URL с продвинутым механизмом повторных попыток.
Parameters:
url (str): URL, на который отправляется запрос.
max_retries (int): Максимальное количество раз, которое запрос может быть повторен. По умолчанию 3.
delay (int): Задержка (в секундах) между попытками. По умолчанию 1.
Raises:
requests.RequestException: Генерирует последнее исключение, если все попытки неудачны.
"""
proxies = {
"http": "http://USER:PASS@HOST:PORT",
"https": "https://USER:PASS@HOST:PORT"
}
for attempt in range(max_retries):
try:
response = requests.get(url, proxies=proxies, verify=False)
# Сгенерировать исключение для статус-кодов 4xx или 5xx
response.raise_for_status()
# Проверить, равен ли статус-код ответа 404
if response.status_code == 404:
print("404 Error: Not Found")
break # Выход из цикла при ошибках 404
# Проверить, меньше ли 10 символов длина текста ответа
if len(response.text) < min_content_length:
print("Response text length is less than 10 characters. Retrying...")
time.sleep(delay)
continue # Повторить запрос
print('Response Status Code:', response.status_code)
# Если условия выполнены, выйти из цикла
break
except requests.RequestException as e:
print(f"Attempt {attempt+1} failed:", e)
if attempt < max_retries - 1:
print(f"Retrying in {delay} seconds...")
time.sleep(delay)
else:
print("Max retries exceeded.")
# Сгенерировать последнее исключение, если достигнуто максимальное количество попыток
raise
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')
Повторные попытки запросов в Python — ключевой элемент успешного веб-скрапинга. Рассмотренные способы управления повторными попыткамипомогают избежать блокировок и обеспечивают более эффективный и надежный сбор данных. Применение этих техник делает ваши скрипты веб-скрапинга более эффективными и устойчивыми перед системами обнаружения ботов.
Мы получили вашу заявку!
Ответ будет отправлен на почту в ближайшее время.
С уважением proxy-seller.ru!
Комментарии: 0