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¤t=.... Тебе не нужно делать это руками.
Кроме 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 имеют лимиты — не запускай циклы из сотен запросов.