Статья Автор: Деникина Н.В., Деникин А.В.

Работа с API

Python · СправочникРабота с API и модуль requests
SilverTests.ruapi · requests · json · http
Работа с API

Как программы получают данные из интернета — и как разобрать то, что пришло в ответ


1Что такое API

API (Application Programming Interface) — это способ, которым одна программа просит данные у другой. Ты не лезешь в чужую базу данных — ты отправляешь запрос по определённому адресу и получаешь ответ в стандартном формате.

Аналогия: ты в ресторане. Не идёшь на кухню сам, а говоришь официанту «пиццу, пожалуйста». Он передаёт заказ повару и приносит результат. API — это официант. URL — это адрес ресторана (расположение кухни в ресторане). Параметры запроса — это заказ. JSON в ответе — это блюдо.

Термин Что значит Аналогия
Сервер компьютер с данными кухня
Клиент твоя программа посетитель
Запрос (request) что хочешь получить заказ
Ответ (response) данные от сервера блюдо
URL + параметры адрес и детали запроса адрес ресторана + меню
JSON формат данных в ответе как блюдо упаковано
status_code успешен ли запрос принесли или уронили
Чего API не делает. Не даёт прямой доступ к базе данных сервера. Не работает без интернета. Не отвечает мгновенно — нужно ждать ответ. Бесплатные API ограничивают количество запросов в день.

2Библиотека requests

В Python для HTTP-запросов используют библиотеку requests. Она не встроена — нужно установить:

pip install requests

Простейший запрос — три строки:

import requests

response = requests.get("https://catfact.ninja/fact")
data = response.json()     # JSON -> словарь Python
print(data["fact"])        # текст факта
Что здесь происходит

requests.get(url) отправляет GET-запрос по адресу и возвращает объект Response. У этого объекта есть метод .json(), который превращает текст ответа в обычный словарь Python. Дальше работаем со словарём как обычно — по ключам.


3Параметры запроса

Большинство API принимают параметры — уточнения того, что именно ты хочешь. Параметры передаются через аргумент params:

import requests

url = "https://api.open-meteo.com/v1/forecast"
params = {
    "latitude": 55.75,
    "longitude": 37.62,
    "current": "temperature_2m,wind_speed_10m"
}

response = requests.get(url, params=params)
data = response.json()

Библиотека requests сама склеит URL и параметры в одну строку: url?latitude=55.75&longitude=37.62&current=.... Тебе не нужно делать это руками.

Кроме params у requests.get() есть аргумент headers — словарь с HTTP-заголовками. Некоторые API (например, Wikipedia) требуют заголовок User-Agent, иначе возвращают ошибку 403. Подробнее — в разделе 9.

Конструктор запроса — выбери параметры и посмотри, как собирается код
город
поля
 
 

4JSON — это словарь, записанный текстом

Ответ API почти всегда приходит в формате JSON. Хорошая новость: ты уже знаешь JSON, потому что это тот же самый словарь Python — ключи, значения, вложенные структуры. Метод .json() превращает текст в настоящий словарь.

# JSON-текст, который пришёл от сервера:
{
    "current": {
        "temperature_2m": 12.5,
        "wind_speed_10m": 3.4
    }
}

# После response.json() это обычный словарь:
data["current"]["temperature_2m"]   # -> 12.5

Словарь может быть вложенным: внутри одного словаря лежит другой, внутри того — список, внутри списка — ещё словари. Чтобы добраться до нужного значения, нужно пройти по цепочке ключей.

Навигатор — нажимай на ключи, чтобы увидеть путь в Python
 
Нажми на любой ключ или значение.
 
В реальных API ответы бывают гораздо глубже. Привычка читать JSON и мысленно строить цепочку ключей — один из главных навыков при работе с API.

5Коды ответа

Каждый ответ сервера содержит числовой код — status_code. По нему программа понимает, всё ли прошло успешно.

Код Имя Что значит
200 OK всё хорошо, данные пришли
400 Bad Request неправильные параметры
401 Unauthorized нужен API-ключ, а ты его не передал
403 Forbidden доступ запрещён — чаще всего не передан заголовок User-Agent
404 Not Found такого адреса нет
429 Too Many Requests слишком частые запросы, подожди
500 Server Error проблема на стороне сервера
Проверка перед использованием
response = requests.get(url, params=params)

if response.status_code == 200:
    data = response.json()
    print("Температура:", data["current"]["temperature_2m"])
else:
    print("Ошибка:", response.status_code)
Без проверки программа упадёт, если сервер вернёт ошибку: .json() попытается разобрать текст ошибки как JSON и получит исключение. Всегда проверяй status_code перед .json().

6Обработка ошибок

Кроме кодов ответа есть ситуация хуже: сервер вообще не отвечает (нет интернета, сервер лежит, DNS не резолвится). В этом случае requests.get() бросит исключение. Чтобы программа не упала, оборачиваем в try/except:

try:
    response = requests.get(url, params=params, timeout=10)
    if response.status_code == 200:
        data = response.json()
        # работаем с данными
    else:
        print("Сервер вернул ошибку:", response.status_code)
except requests.RequestException:
    print("Нет связи с сервером")

Параметр timeout=10 — сколько секунд ждать ответа. Без него программа может зависнуть навсегда, если сервер не отвечает.

Типичные ошибки при работе с API

Ниже — ошибки, которые встречаются при запросах к API и разборе JSON. Запомни их — они будут в задачах и на контрольной.

Ошибка Когда возникает Пример
KeyError Обращение к несуществующему ключу в словаре. Чаще всего — пропущен промежуточный ключ. data["temperature_2m"] вместо data["current"]["temperature_2m"]
IndexError Обращение к элементу пустого списка. API вернул [], а код пишет data[0]. data[0]["localName"] при data = [] — нужна проверка if data:
JSONDecodeError Вызов .json() когда сервер вернул не JSON (например, HTML-страницу с ошибкой 404 или 503). Нужно сначала проверить status_code == 200, а только потом вызывать .json()
403 Forbidden Сервер отказал в доступе. Чаще всего — не передан заголовок User-Agent (Wikipedia) или нужен API-ключ. Добавить headers={"User-Agent": "MyApp/1.0 (email)"}
ConnectionError Нет интернета, DNS не найден, сервер не отвечает. Возникает в requests.get() — объект response даже не создаётся. Проверка status_code не поможет — нужен try/except requests.RequestException
Зависание Сервер принял соединение, но не отвечает. Без timeout программа ждёт бесконечно. requests.get(url) — нужен requests.get(url, timeout=10)

7Массивы в ответе API

Некоторые API возвращают не одиночные значения, а массивы (списки). Например, почасовой прогноз — это два параллельных списка по 24 элемента: время и температура.

# Запрос почасового прогноза
params = {
    "latitude": 55.75,
    "longitude": 37.62,
    "hourly": "temperature_2m"
}
data = requests.get(url, params=params).json()

temps = data["hourly"]["temperature_2m"]  # список из 24 чисел
times = data["hourly"]["time"]            # список из 24 строк

print("Максимум:", max(temps))
print("Минимум:", min(temps))
print("Среднее:", round(sum(temps) / len(temps), 1))

Массивы идут параллельно: температура с индексом 12 соответствует времени с индексом 12. Обходить их можно через range(len(...)) или через zip:

for time, temp in zip(times, temps):
    if temp >= 15:
        hour = time.split("T")[1]
        print(f"{hour} -- {temp}C")

8Тренажёр — напиши путь к значению

Тебе показан JSON-ответ от API и вопрос: каким выражением достать нужное значение? Напиши путь, начиная с data.

Тренажёр — извлечение данных из JSON
 
 
data
 
 
 

9Каталог API — готовый код для каждого сервиса

Четыре сервиса, которые стабильно работают без регистрации и без ключа. Для каждого — URL, параметры, код и какие поля доставать.

1. Open-Meteo — погода
url = "https://api.open-meteo.com/v1/forecast"
params = {
    "latitude": 55.75,          # Москва
    "longitude": 37.62,
    "current": "temperature_2m,wind_speed_10m,weather_code"
}
data = requests.get(url, params=params, timeout=10).json()

temp = data["current"]["temperature_2m"]       # 12.5
wind = data["current"]["wind_speed_10m"]      # 3.4
code = data["current"]["weather_code"]        # 0=ясно, 1-3=облачно, 61=дождь, 71=снег

Координаты других городов: Питер (59.93, 30.31), Казань (55.79, 49.12), Сочи (43.60, 39.73), Новосибирск (55.03, 82.92). Для почасового прогноза замените current на hourly — получите массив из 24 значений.

2. ЦБ РФ — курсы валют
url = "https://www.cbr-xml-daily.ru/daily_json.js"
data = requests.get(url, timeout=10).json()

usd = data["Valute"]["USD"]["Value"]        # 92.5 (курс сегодня)
usd_prev = data["Valute"]["USD"]["Previous"] # 92.1 (курс вчера)
eur = data["Valute"]["EUR"]["Value"]        # 100.3

Параметров нет — URL фиксированный. Есть Value (сегодня) и Previous (вчера) — можно показать тренд: если Value > Previous, курс вырос.

3. Nager.Date — праздники
url = "https://date.nager.at/api/v3/NextPublicHolidays/RU"
data = requests.get(url, timeout=10).json()   # это список!

if data:
    name = data[0]["localName"]   # "День труда"
    date = data[0]["date"]        # "2026-05-01"

Возвращает список, а не словарь — первый элемент это ближайший праздник. Обязательно if data: — список может быть пустым. Можно посчитать, сколько дней до праздника.

4. Cat Facts — факты о кошках
url = "https://catfact.ninja/fact"
data = requests.get(url, timeout=10).json()

fact = data["fact"]     # "Cats sleep 12-16 hours per day."

Параметров нет. Каждый запрос — новый случайный факт. Текст на английском. Самый простой API для первого подключения.


Ещё варианты (менее стабильные или с нюансами)

Эти API тоже работают, но с оговорками. Если хотите их использовать — будьте готовы к тому, что они могут быть временно недоступны.

Сервис Нюанс URL
JokeAPI анекдоты, но только на английском (русского нет) v2.jokeapi.dev/joke/Any?safe-mode
REST Countries все страны мира; бывает медленный, запрашивайте одну страну: /v3.1/alpha/ru restcountries.com
Wikipedia требует заголовок User-Agent, без него — 403 ru.wikipedia.org/api/rest_v1/page/random/summary
NASA APOD ключ DEMO_KEY, лимит 30 запросов/час, бывает медленный api.nasa.gov/planetary/apod?api_key=DEMO_KEY
Useless Facts случайный факт на английском (замена Numbers API) uselessfacts.jsph.pl/api/v2/facts/random
Ищите своё API. Найдите что-то интересное самостоятельно. Ищите и тестируйте: free public api no key или github.com/public-apis/public-apis

10Что запомнить
Главное об API. API — способ получить данные с чужого сервера по стандартному адресу. Запрос делается через requests.get(url, params=...). Ответ приходит в формате JSON — метод .json() превращает его в словарь Python. Данные достаём по цепочке ключей: data["current"]["temperature_2m"]. Перед использованием проверяй status_code == 200. Оборачивай запрос в try/except на случай, если нет интернета. Параметр timeout защищает от зависания. Бесплатные API имеют лимиты — не запускай циклы из сотен запросов.
© SilverTests.ru · Справочник · Работа с API и модуль requests
Печать