Библиотека Aiogram: создание Telegram ботов с асинхронностью Python
Библиотека Aiogram для создания Telegram ботов на Python
Aiogram - это асинхронная библиотека для разработки Telegram ботов. Она построена на asyncio и позволяет эффективно обрабатывать множество запросов одновременно. Современная версия 3.x предлагает модульную архитектуру с использованием роутеров, фильтров и FSM. Основное преимущество - высокая производительность и гибкость.
Как установить Aiogram и создать базового бота?
pip install aiogram==3.10.0библиотека aiogram python (библиотека aiogram для telegram ботов)
После установки требуется токен от BotFather. Бот создаётся через объект Bot и запускается диспетчером Dispatcher.
import asyncio
from aiogram import Bot, Dispatcher
from aiogram.filters import Command
from aiogram.types import Message
TOKEN = 'YOUR_BOT_TOKEN'
bot = Bot(token=TOKEN)
dp = Dispatcher()
@dp.message(Command('start'))
async def start_handler(message: Message):
await message.answer('Привет! Я бот на Aiogram.')
async def main():
await dp.start_polling(bot)
if __name__ == '__main__':
asyncio.run(main())Python telegram bot (создание telegram бота на python)
Этот код запускает бота, который отвечает на команду /start. Ошибки: отсутствие токена или неправильное имя команды (без /) приводят к игнорированию хендлера.
Типичная ошибка: забыть импортировать asyncio или использовать run(main()) без await. Решение: всегда использовать стандартную конструкцию asyncio.run().
Как организовать обработку разных команд и сообщений?
Лучший способ - использовать роутеры. Каждый роутер отвечает за свою группу хендлеров.
from aiogram import Router
router = Router()
@router.message(Command('help'))
async def help_handler(message: Message):
await message.answer('Справка: используйте /start')
# Подключение роутера к диспетчеру
dp.include_router(router)
Py telegram python (telegram боты на python (pytelegrambotapi))
Роутеры можно разделять по логике (админ-панель, пользовательские команды, игры). Фильтр Command гарантирует, что хендлер сработает только на точную команду.
Ошибка: регистрация роутера после запуска polling приводит к тому, что хендлеры не будут видны. Нужно включать роутеры до вызова start_polling().
Как добавить клавиатуры с кнопками?
Для простого меню используется ReplyKeyboardMarkup, для инлайн-кнопок - InlineKeyboardMarkup.
from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, InlineKeyboardMarkup, InlineKeyboardButton
# Reply клавиатура
reply_kb = ReplyKeyboardMarkup(
keyboard=[
[KeyboardButton(text='Кнопка 1')],
[KeyboardButton(text='Кнопка 2')]
],
resize_keyboard=True
)
# Inline клавиатура
inline_kb = InlineKeyboardMarkup(
inline_keyboard=[
[InlineKeyboardButton(text='Ссылка', url='https://example.com')],
[InlineKeyboardButton(text='Нажать', callback_data='press')]
]
)
@router.message(Command('menu'))
async def menu_handler(message: Message):
await message.answer('Выберите действие:', reply_markup=reply_kb)
@router.callback_query(lambda c: c.data == 'press')
async def press_handler(callback_query):
await callback_query.answer('Нажали!')
await callback_query.message.edit_text('Вы нажали инлайн кнопку.')Aiogram python боты (боты на aiogram python)
Ошибка: не обрабатывать callback_query ответом (answer). Без этого кнопка может зависнуть с часами. Всегда вызывайте await callback_query.answer().
Как реализовать диалог с состоянием (FSM)?
FSM (Finite State Machine) позволяет хранить состояние пользователя. Используется State и StatesGroup.
from aiogram.fsm.state import StatesGroup, State
from aiogram.fsm.context import FSMContext
class Form(StatesGroup):
name = State()
age = State()
@router.message(Command('form'))
async def form_start(message: Message, state: FSMContext):
await state.set_state(Form.name)
await message.answer('Введите ваше имя:')
@router.message(Form.name)
async def process_name(message: Message, state: FSMContext):
await state.update_data(name=message.text)
await state.set_state(Form.age)
await message.answer('Введите возраст:')
@router.message(Form.age)
async def process_age(message: Message, state: FSMContext):
data = await state.get_data()
age = int(message.text)
await message.answer(f'Спасибо, {data["name"]}, вам {age} лет.')
await state.clear()Python bot main py (основной файл бота python)
Частая ошибка: не очищать состояние после завершения диалога (state.clear()). Пользователь застрянет в последнем состоянии. Также нужно обрабатывать невалидный ввод (например, возраст не число) через try-except.
Как отправлять медиа (фото, видео, документы)?
from aiogram.types import FSInputFile
@router.message(Command('photo'))
async def send_photo(message: Message):
photo = FSInputFile('path/to/photo.jpg')
await message.answer_photo(photo=photo, caption='Фото из файла')
@router.message(Command('urlphoto'))
async def send_url_photo(message: Message):
await message.answer_photo(photo='https://example.com/photo.jpg')
библиотеки python telegram bot (библиотеки python для telegram ботов)
Ошибка: передача локального файла без FSInputFile. Если передать простую строку пути, Aiogram попытается считать это URL и вызовет ошибку. Всегда используйте FSInputFile для локальных файлов.
Как обрабатывать только текстовые сообщения?
@router.message(lambda m: m.text and not m.text.startswith('/'))
async def any_text(message: Message):
await message.answer(f'Вы написали: {message.text}')
Фильтр-лямбда позволяет гибко отбирать сообщения. Альтернатива - использовать F.text из магических фильтров.
Как использовать middleware для логирования?
from aiogram import BaseMiddleware
from typing import Callable, Any
class LoggerMiddleware(BaseMiddleware):
async def __call__(self, handler: Callable, event: Any, data: dict):
print(f'Получен апдейт: {event.__class__.__name__}')
result = await handler(event, data)
print('Обработано')
return result
dp.update.middleware(LoggerMiddleware())
Middleware выполняются до и после хендлера. Полезно для аудита, ограничения скорости, блокировки.
Как настроить webhook вместо polling?
import ssl
from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application
from aiohttp import web
async def on_startup(bot: Bot, base_url: str):
await bot.set_webhook(f'{base_url}/webhook')
def main():
bot = Bot(token=TOKEN)
dp = Dispatcher()
dp.startup.register(on_startup)
app = web.Application()
webhook_requests_handler = SimpleRequestHandler(
dispatcher=dp,
bot=bot,
)
webhook_requests_handler.register(app, path='/webhook')
setup_application(app, dp, bot=bot)
web.run_app(app, host='0.0.0.0', port=8080)
Webhook подходит для продакшена: бот не будет постоянно опрашивать Telegram, а получает апдейты по запросу. Требуется публичный HTTPS URL.
Как работать с callback данными в inline кнопках?
@router.callback_query(F.data.startswith('item_'))
async def item_callback(callback_query):
item_id = callback_query.data.split('_')[1]
await callback_query.message.answer(f'Вы выбрали товар номер {item_id}')
await callback_query.answer()
В callback_data можно кодировать идентификаторы. Важно не превышать лимит 64 байта. Для сложных данных используйте сериализацию (например, json).
Как запустить бота в контейнере Docker?
Пример Dockerfile для aiogram-бота:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "bot.py"]
requirements.txt содержит aiogram и aiohttp для вебхуков. Запуск: docker build -t mybot . && docker run mybot
Расширенные примеры использования Aiogram 3.x
Пример 1: Middleware для измерения времени обработки
import time
from aiogram import BaseMiddleware
from typing import Callable, Dict, Any
class TimingMiddleware(BaseMiddleware):
async def __call__(self, handler: Callable, event: Any, data: Dict[str, Any]) -> Any:
start = time.perf_counter()
result = await handler(event, data)
duration = time.perf_counter() - start
print(f'Обработка {event.__class__.__name__} заняла {duration:.3f} сек.')
return result
dp.update.middleware(TimingMiddleware())
Вывод в консоль при получении сообщения: Обработка Message заняла 0.021 сек.
Пример 2: FSM с валидацией и отменой
from aiogram.fsm.state import StatesGroup, State
from aiogram.fsm.context import FSMContext
from aiogram.types import Message
from aiogram.filters import Command
class Survey(StatesGroup):
name = State()
age = State()
city = State()
@router.message(Command('survey'))
async def start_survey(message: Message, state: FSMContext):
await state.set_state(Survey.name)
await message.answer('Как вас зовут?')
@router.message(Survey.name)
async def process_name(message: Message, state: FSMContext):
if len(message.text) < 2:
await message.answer('Имя должно содержать хотя бы 2 символа. Попробуйте ещё раз.')
return
await state.update_data(name=message.text)
await state.set_state(Survey.age)
await message.answer('Сколько вам лет?')
@router.message(Survey.age)
async def process_age(message: Message, state: FSMContext):
if not message.text.isdigit():
await message.answer('Возраст должен быть числом. Введите корректно.')
return
age = int(message.text)
if age < 1 or age > 150:
await message.answer('Некорректный возраст (1-150).')
return
await state.update_data(age=age)
await state.set_state(Survey.city)
await message.answer('Из какого вы города?')
@router.message(Survey.city)
async def process_city(message: Message, state: FSMContext):
data = await state.get_data()
await message.answer(f'Спасибо за участие! Ваши данные:\nИмя: {data["name"]}\nВозраст: {data["age"]}\nГород: {message.text}')
await state.clear()
# Хендлер для отмены
@router.message(Command('cancel'))
async def cancel(message: Message, state: FSMContext):
current_state = await state.get_state()
if current_state is None:
return
await state.clear()
await message.answer('Диалог отменён.')
Диалог: Пользователь: /survey Бот: Как вас зовут? Пользователь: А Бот: Имя должно содержать хотя бы 2 символа. Попробуйте ещё раз. Пользователь: Анна Бот: Сколько вам лет? Пользователь: 25 Бот: Из какого вы города? Пользователь: Москва Бот: Спасибо за участие! Ваши данные: ...
Пример 3: Отправка альбома (MediaGroup)
from aiogram.types import MediaGroup, InputMediaPhoto
@router.message(Command('album'))
async def send_album(message: Message):
album = MediaGroup(
media=[
InputMediaPhoto(media='https://picsum.photos/200/300?random=1'),
InputMediaPhoto(media='https://picsum.photos/200/300?random=2', caption='Второе фото'),
]
)
await message.answer_media_group(media=album)
Пользователь получает два фото в одном сообщении (альбом).
Пример 4: Использование Redis для хранения состояний (FSM Storage)
from aiogram.fsm.storage.redis import RedisStorage
import redis
redis_client = redis.Redis(host='localhost', port=6379, decode_responses=True)
storage = RedisStorage(redis_client)
dp = Dispatcher(storage=storage)
# Теперь FSM состояния сохраняются в Redis, что полезно при масштабировании.
RedisStorage позволяет хранить данные между перезапусками бота и в горизонтально масштабируемой среде.
Пример 5: Фильтры на основе пользовательских прав (админка)
from aiogram.filters import Filter
from aiogram.types import Message
ADMIN_IDS = [123456789] # ID администраторов
class AdminFilter(Filter):
async def __call__(self, message: Message) -> bool:
return message.from_user.id in ADMIN_IDS
@router.message(Command('admin'), AdminFilter())
async def admin_panel(message: Message):
await message.answer('Добро пожаловать в панель администратора.')
Команда /admin срабатывает только у пользователей с ID из списка ADMIN_IDS. Для остальных хендлер игнорируется.
Пример 6: Обработка ошибок через ErrorEvent
from aiogram.types import ErrorEvent
@dp.error()
async def error_handler(event: ErrorEvent):
print(f'Ошибка: {event.exception}')
await event.update.message.answer('Произошла внутренняя ошибка.')
Глобальный обработчик ошибок перехватывает все необработанные исключения в хендлерах. Бот не падает, а уведомляет пользователя.
Пример 7: Чат-бот с использованием GPT через Aiogram
import openai
from aiogram import types
@router.message(Command('ask'))
async def ask_gpt(message: types.Message):
user_text = message.text.replace('/ask ', '')
response = openai.ChatCompletion.create(
model='gpt-3.5-turbo',
messages=[{'role': 'user', 'content': user_text}]
)
reply = response.choices[0].message.content
await message.answer(reply)
Интеграция с внешними API - частое применение ботов. Важно установить отдельно библиотеку openai и настроить ключ.