Получение данных из интернета: requests и API

Курсы валют, погода, данные из CRM — многое живёт в вебе. Библиотека requests забирает страницы и ответы API, а данные чаще всего приходят в формате JSON, который Python разбирает встроенно.
Суть: requests.get(url) скачивает данные, response.json() превращает JSON-ответ в словари и списки Python. API — это URL, который отдаёт данные машине, а не человеку.

Часто источник данных для отчёта — не файл, а внешний сервис: API банка с курсом валют, погодный сервис, ваша же CRM. requests — стандартная библиотека-де-факто для HTTP-запросов (ставится как pip install requests). Вы делаете get по адресу — и получаете ответ.

Большинство API отдают данные в JSON — текстовом формате, который один в один ложится на словари и списки Python. И вот разбор JSON — это уже встроенный модуль json, полностью исполнимый в браузере. Отработаем именно его, ведь это сердце работы с API.

Попробуй сам ▶

import json

# Так выглядит типичный JSON-ответ API (как строка)
response_text = '''{
  "base": "RUB",
  "date": "2026-06-22",
  "rates": [
    {"code": "USD", "value": 78.4},
    {"code": "EUR", "value": 91.2},
    {"code": "CNY", "value": 10.7}
  ]
}'''

# json.loads: текст -> словари и списки Python
data = json.loads(response_text)
print('Дата курса:', data['date'])
for rate in data['rates']:
    print(f"  1 {rate['code']} = {rate['value']} {data['base']}")

# Найдём самый дорогой к рублю
top = max(data['rates'], key=lambda r: r['value'])
print('Дороже всего:', top['code'])

Метод response.json() в requests делает ровно то же, что json.loads здесь: превращает текст ответа во вложенные словари и списки. Дальше вы ходите по ним обычными ключами. Сам сетевой запрос показан как нерабочая в браузере врезка.

import requests

url = 'https://api.example.com/rates'
resp = requests.get(url, params={'base': 'RUB'}, timeout=10)
resp.raise_for_status()      # бросит ошибку при коде 4xx/5xx

data = resp.json()           # то же, что json.loads(resp.text)
for rate in data['rates']:
    print(rate['code'], rate['value'])

# Заголовки, например токен авторизации:
headers = {'Authorization': 'Bearer ' + token}
resp = requests.get(url, headers=headers, timeout=10)
ЗАПРОС К API

  скрипт
    |  requests.get(url, params, timeout)
    v
  HTTP-запрос  -->  сервер API
    ^                  |
    |   JSON-ответ <---+
    v
  resp.json() -> dict/list -> в отчёт

Реальные API почти всегда защищены от перегрузки лимитом частоты (rate limit) и могут временно отказывать из-за сетевых сбоев. Поэтому промышленный код оборачивает запрос в логику повторов: при ошибке подождать секунду и попробовать снова, увеличивая паузу с каждой неудачей (это называют экспоненциальной выдержкой). А чтобы уважать лимиты, между запросами вставляют паузу и кэшируют ответы, которые меняются редко: незачем дёргать курс валют сто раз в минуту, если он обновляется раз в день. Эти приёмы превращают хрупкий скрипт, который ломается от первого же сбоя сети, в надёжный сборщик данных.

Как работает под капотом

Запрос requests.get открывает HTTP-соединение, отправляет серверу строку запроса с адресом и заголовками и ждёт ответ. Ответ содержит код состояния (200 — успех, 404 — не найдено, 500 — ошибка сервера) и тело. raise_for_status() проверяет код и бросает исключение, если что-то пошло не так — без этой проверки скрипт молча обработает страницу ошибки как данные.

Параметр timeout критичен: без него запрос может зависнуть навсегда, если сервер не отвечает, и весь скрипт автоматизации встанет. Заголовки (headers) несут метаданные — чаще всего токен авторизации, который доказывает серверу, что вы имеете право на данные.

Частые ошибки

  • Не ставить timeout. Зависший сервер заморозит весь скрипт навсегда.
  • Не проверять код ответа. Без raise_for_status ошибку 500 легко принять за валидные данные.
  • Долбить API без пауз. Сервисы ограничивают частоту запросов (rate limit) и забанят слишком назойливый скрипт.

Best practices

  • Всегда задавайте timeout и вызывайте raise_for_status().
  • Уважайте лимиты API: делайте паузы и читайте документацию по частоте.
  • Секреты-токены берите из окружения, как и пароли почты.

Итоги. requests забирает данные из веба, response.json() превращает JSON в словари Python, а timeout и проверка кода делают это надёжным. У нас есть все источники и приёмники данных — пора научиться запускать пайплайны по расписанию.

Проверьте себя
1. Что делает response.json() после запроса requests?
AСкачивает файл json с диска
BПревращает JSON-текст ответа во вложенные словари и списки Python
CОтправляет данные на сервер
DПроверяет код состояния
2. Зачем у запроса requests.get указывать timeout?
AЧтобы ускорить запрос
BЧтобы скрипт не завис навсегда, если сервер не отвечает
CЧтобы обойти rate limit
DЭто обязательный аргумент