Библиотека Aiogram: создание Telegram ботов с асинхронностью Python

Раздел: Боты -> Telegram боты

Библиотека 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 и настроить ключ.

Библиотека Aiogram для Telegram ботов - comments

En
библиотека aiogram python (python)