
Всем привет! Помню, как в начале пути я запустил свой первый масштабный парсер на ночь, а утром обнаружил, что он «умер» через пять минут после старта из-за банальной ошибки 404 на одной из страниц. Это чувство, когда тысячи строк кода проделали работу впустую, знакомо каждому разработчику. С тех пор я понял: главная характеристика хорошего парсера — это не скорость и не крутость используемой библиотеки, а его способность работать автономно, даже когда сайт «сопротивляется» или сеть дает сбой. Сегодня мы детально разберем, как сделать ваши скрипты «неубиваемыми» и почему обработка ошибок при парсинге в Python — это самый важный навык, который отличает новичка от профи.
Оглавление
Почему ваш парсер постоянно «падает»?
Когда мы пишем скрипт, мы обычно ожидаем идеального сценария: отправили запрос — получили данные — записали в файл. Однако в реальном интернете все иначе. Сайты могут быть временно недоступны, сервер может выдавать запрет доступа (ошибку 403), или страница, которую вы парсили вчера, сегодня может просто исчезнуть. Если ваш код не содержит блока обработки исключений, любая такая ситуация приведет к немедленной остановке программы. Изучая 10 ошибок новичков в Python, многие забывают, что главная ошибка — это излишняя самоуверенность в стабильности внешних ресурсов.
Ловим исключения: try-except
Основа любого надежного кода — конструкция try-except. Она позволяет программе не падать при возникновении ошибки, а перехватить её и выполнить альтернативный сценарий. Например, вместо того чтобы завершить работу при ошибке сети, вы можете просто логировать её в файл, подождать 60 секунд и попробовать еще раз. Это превращает ваш скрипт из «хрупкого» изделия в отказоустойчивый инструмент автоматизации.
import requests
def fetch_data(url):
try:
response = requests.get(url, timeout=10)
# Этот метод автоматически выбросит исключение для ошибок 4xx и 5xx
response.raise_for_status()
return response.text
except requests.exceptions.HTTPError as err:
print(f"HTTP ошибка: {err}")
except requests.exceptions.ConnectionError:
print("Ошибка соединения: проверьте интернет или прокси")
except requests.exceptions.Timeout:
print("Тайм-аут: сайт отвечает слишком долго")
return None
Этот подход позволяет локализовать проблему. Важно понимать, что raise_for_status() — это магический метод библиотеки requests, который сам проверяет, вернул ли сервер успешный статус 200, и если нет, то «поднимает» исключение, которое мы потом аккуратно ловим.
📚 Документация:requests.exceptions — HTTP Exceptions «Этот модуль содержит все исключения, которые могут возникнуть при работе с библиотекой requests, позволяя точно определять тип сбоя.»
Работа с кодами состояний HTTP: 403, 404 и 500
Когда мы говорим про обработку ошибок парсинга в Python, важно понимать, что означает каждый код ответа сервера. Ошибка 404 означает, что страница не найдена — здесь нет смысла пробовать снова, нужно просто пропустить этот URL. Ошибка 403 Forbidden говорит, что сервер вас «увидел» и заблокировал — тут поможет смена User-Agent или использование прокси. А вот ошибка 500 — это проблема на стороне сервера, и она часто лечится простым повторным запросом через пару секунд.
Стратегия повторных попыток (Retry)
Никогда не сдавайтесь после первой попытки. Использование механики Retry позволяет автоматически повторять запрос, если он завершился с кодом 5xx. Если вы хотите автоматизировать парсинг на профессиональном уровне, посмотрите, как реализована логика в других сложных проектах, например, при создании API на FastAPI, там тоже важна обработка ответов.
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
# Настройка стратегии повторных попыток
retry = Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
# Теперь запросы через session будут автоматически повторяться при 5xx ошибках
response = session.get("https://example.com")
Логирование: как понять, что пошло не так?
Когда скрипт работает в фоновом режиме, вы не видите консоль. Если произошла ошибка, вам нужно иметь «черный ящик», который запишет причину сбоя. Использование модуля logging — это стандарт индустрии. Писать ошибки через print() — плохая практика, ведь logging позволяет записывать не только текст ошибки, но и время, уровень важности (INFO, ERROR, CRITICAL) и даже трассировку стека.
Настройка логгера
Правильное логирование поможет вам анализировать, в какое время чаще всего «отваливается» сайт, чтобы писать чистый и читаемый код на Python, который будет легко поддерживать и развивать в дальнейшем.
import logging
logging.basicConfig(filename='parser.log', level=logging.ERROR,
format='%(asctime)s - %(levelname)s - %(message)s')
def safe_parse(url):
try:
# ... логика запроса ...
pass
except Exception as e:
logging.error(f"Не удалось спарсить {url}: {e}")
📚 Документация:logging — Logging facility for Python «Стандартный модуль Python для ведения журналов событий, который позволяет гибко настраивать вывод сообщений в файлы или консоль.»
Полный код отказоустойчивого парсера
Давайте соберем все знания вместе. Этот скрипт умеет пропускать битые страницы, повторять запросы при временных сбоях и записывать все ошибки в лог-файл.
import requests
import logging
import time
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# Настройка логов
logging.basicConfig(level=logging.INFO, filename='parser_errors.log')
def get_session():
session = requests.Session()
retry = Retry(total=3, backoff_factor=1, status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
return session
def robust_parser(urls):
session = get_session()
results = []
for url in urls:
try:
resp = session.get(url, timeout=5)
resp.raise_for_status()
results.append(resp.text)
except requests.exceptions.RequestException as e:
logging.error(f"Ошибка при работе с {url}: {e}")
continue
return results
# Пример использования
target_urls = ["https://site1.com", "https://site2.com"]
data = robust_parser(target_urls)
Заключение
Обработка ошибок при парсинге в Python — это то, что превращает вашего «бота-однодневку» в серьезное решение для автоматизации. Не бойтесь ошибок — они неизбежны в работе с сетью. Бойтесь кода, который не умеет на них реагировать. Используя стратегии повторных попыток (Retry), логирование событий и грамотную обработку исключений try-except, вы сможете создать инструмент, способный работать неделями без вмешательства человека. Начните применять эти принципы уже сегодня, и вы заметите, как ваши отчеты стали собираться стабильно и без «дырок» в данных.
• Как в Python извлечь все ссылки на веб-странице — надежный сбор данных начинается с поиска правильных целей
• Как писать чистый и читаемый код на Python — структурируйте обработку ошибок, чтобы скрипт был понятен вам спустя полгода
• 10 ошибок новичков в Python — узнайте, какие еще проблемы могут остановить ваш автоматизированный проект
📢 В своем Telegram-канале я публикую полезные разборы кода каждый день, плюс эксклюзивные фишки, которых нет на сайте. Подпишитесь, чтобы ускорить свою разработку: Telegram-канал
👉 Ваш интерес — лучшая мотивация для новых статей!