Разработка приложений, использующих API сторонних сервисов
Основы работы с API на Python
Как получить данные от внешнего сервиса с минимальными усилиями?
Наиболее эффективным решением для взаимодействия с REST API в Python является библиотека requests. Она предоставляет удобный интерфейс для отправки HTTP запросов и обработки ответов.
Пример базового GET запроса:
import requests
url = "https://api.github.com/users/octocat"
response = requests.get(url)
if response.status_code == 200:
user_data = response.json()
print(user_data['login'])
else:
print(f"Ошибка: {response.status_code}")Telegram python библиотека (библиотека python для telegram)
Пояснения:
- Функция requests.get отправляет HTTP GET запрос.
- Свойство status_code содержит код ответа сервера.
- Метод .json() парсит ответ как JSON.
Типичная ошибка: ConnectionError возникает при отсутствии сети или неверном домене. Решение: обернуть запрос в try/except и проверять таймауты.
Как выполнять запросы с более современной библиотекой httpx?
Библиотека httpx поддерживает как синхронные, так и асинхронные вызовы. Для установки: pip install httpx.
Синхронный пример:
import httpx
response = httpx.get('https://api.github.com/users/octocat')
data = response.json()
print(data['login'])Python api программа (программа с использованием api на python)
Асинхронный пример с async/await:
import httpx
import asyncio
async def fetch_user():
async with httpx.AsyncClient() as client:
response = await client.get('https://api.github.com/users/octocat')
data = response.json()
print(data['login'])
asyncio.run(fetch_user())
Пояснение: асинхронный клиент позволяет отправлять множество запросов параллельно без блокировки.
Проблема: при работе с httpx в асинхронном режиме необходимо управлять контекстным менеджером. Забытый async with вызовет ошибку времени выполнения.
Как организовать множество параллельных запросов с aiohttp?
Для высокопроизводительной асинхронной работы подходит библиотека aiohttp. Установка: pip install aiohttp.
Пример одновременного получения нескольких пользователей:
import aiohttp
import asyncio
async def fetch_user(session, url):
async with session.get(url) as response:
return await response.json()
async def main():
urls = [f'https://api.github.com/users/{i}' for i in range(1, 6)]
async with aiohttp.ClientSession() as session:
tasks = [fetch_user(session, url) for url in urls]
results = await asyncio.gather(*tasks)
for user in results:
print(user.get('login'))
asyncio.run(main())
Пояснение: asyncio.gather запускает все задачи параллельно, что значительно ускоряет сбор данных.
Ошибка: ClientConnectorError возникает при попытке подключения к несуществующему хосту. Рекомендуется добавлять таймауты и обработку исключений.
Как обойтись без установки дополнительных пакетов, используя urllib?
Встроенная библиотека urllib.request позволяет отправлять HTTP запросы без сторонних зависимостей.
Пример GET запроса:
from urllib.request import urlopen
import json
url = "https://api.github.com/users/octocat"
with urlopen(url) as response:
data = json.loads(response.read())
print(data['login'])
Пояснение: urlopen возвращает файлоподобный объект. Для JSON используется модуль json. Недостаток: более громоздкая обработка ошибок и заголовков.
Частая проблема: отсутствие обработки HTTP ошибок (например, 404). Решение: использовать urlopen внутри try/except и проверять код ответа через метод getcode().
Как аутентифицироваться в API с использованием токенов?
Многие API требуют авторизации через Bearer токен. Пример с библиотекой requests:
import requests
headers = {
'Authorization': 'Bearer YOUR_ACCESS_TOKEN'
}
response = requests.get('https://api.example.com/private', headers=headers)
if response.status_code == 200:
print(response.json())
else:
print(f"Авторизация не удалась: {response.status_code}")
Пояснение: токен передаётся в заголовке Authorization. Для безопасности токены не следует хранить в коде, лучше использовать переменные окружения.
Ошибка: 401 Unauthorized при неверном или просроченном токене. Решение: обновлять токен заранее и обрабатывать код 401 для автоматической переаутентификации.
Расширенные примеры работы с API
Асинхронный сбор данных с пагинацией
Следующий пример показывает, как собрать все страницы с результатами из API GitHub, используя aiohttp и asyncio:
import aiohttp
import asyncio
async def fetch_repos(session, page):
url = f"https://api.github.com/users/octocat/repos?page={page}&per_page=10"
async with session.get(url) as response:
data = await response.json()
return data
async def main():
async with aiohttp.ClientSession() as session:
# предположим, что на первой странице есть Link header для пагинации
first_page = await fetch_repos(session, 1)
all_repos = first_page
# Если есть Link header с rel="next", продолжаем
# Для простоты используем цикл по номерам страниц
for page in range(2, 5): # ограничим 4 страницами
repos = await fetch_repos(session, page)
if not repos:
break
all_repos.extend(repos)
print(f"Собрано {len(all_repos)} репозиториев")
asyncio.run(main())
Собрано 40 репозиториев
Пояснение: пагинация часто реализуется через query-параметры page и per_page. Результат показывает суммарное количество записей.
Обработка rate limiting с повторными попытками
API могут ограничивать частоту запросов. Используем библиотеку tenacity для автоматических повторов:
import requests
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
@retry(
stop=stop_after_attempt(5),
wait=wait_exponential(multiplier=1, min=2, max=30),
retry=retry_if_exception_type(requests.exceptions.HTTPError)
)
def fetch_with_retry(url):
response = requests.get(url)
if response.status_code == 429:
raise requests.exceptions.HTTPError("Rate limit exceeded")
response.raise_for_status()
return response.json()
data = fetch_with_retry('https://api.example.com/data')
print(data)
{'key': 'value'}
Пояснение: декоратор @retry перехватывает исключения, ждёт с экспоненциальной задержкой и повторяет запрос до 5 раз.
Загрузка файла на сервер через multipart/form-data
Отправка изображения на сервер:
import requests
url = 'https://httpbin.org/post'
files = {'file': ('photo.jpg', open('photo.jpg', 'rb'), 'image/jpeg')}
response = requests.post(url, files=files)
print(response.json()['files']['file'])
'... (содержимое файла в base64)'
Пояснение: параметр files принимает словарь, где ключ - имя поля, значение - кортеж (имя файла, объект файла, MIME-тип).
Работа с GraphQL API
GraphQL требует отправки POST запроса с телом, содержащим query:
import requests
url = 'https://api.github.com/graphql'
headers = {'Authorization': 'Bearer YOUR_TOKEN'}
query = """
{
user(login: "octocat") {
name
repositories(first: 3) {
nodes {
name
}
}
}
}
"""
response = requests.post(url, json={'query': query}, headers=headers)
data = response.json()
print(data['data']['user']['name'])
The Octocat
Пояснение: GraphQL эндпоинт принимает JSON с полем query. Ответ содержит вложенную структуру.
Подключение к WebSocket API
Для работы в реальном времени используется библиотека websockets:
import asyncio
import websockets
async def listen():
async with websockets.connect('wss://echo.websocket.org') as ws:
await ws.send('Привет, сервер!')
response = await ws.recv()
print(response)
asyncio.run(listen())
Привет, сервер!
Пояснение: WebSocket позволяет устанавливать двустороннее соединение. Пример использует эхо сервер для теста.