Бот для Авито на Python — это не одна функция с языковой моделью, а небольшой сервис из четырёх частей: приёмник событий, очередь, генератор ответа и правила эскалации. Разберём скелет так, чтобы его можно было собрать за несколько вечеров и не переписывать заново на первой сотне диалогов.
Сразу оговорка про код ниже: это структура и псевдокод. Точные имена методов API площадки берите из официальной документации Авито — они уточняются, и вставлять их по памяти в статью бессмысленно. Ценность здесь в том, как разложены обязанности между модулями, а не в конкретных строчках запросов.
Структура проекта
bot/ config.py # чтение переменных окружения, никаких секретов в коде avito_client.py # обёртка над API: токен, повтор, разбор ответов webhook.py # приём событий: проверил, записал, ответил 200 worker.py # фоновый обработчик очереди brain.py # сборка ответа: факты о товаре + шаблоны + модель escalate.py # правила передачи диалога человеку storage.py # диалоги, обработанные события, очередь задач poller.py # страховочный опрос непрочитанных диалогов
Разделение на webhook.py и worker.py — не эстетика. Приёмник обязан отвечать быстро, иначе площадка сочтёт доставку неудачной и повторит событие, а вы получите два ответа на одно сообщение.
Слой доступа к площадке
Один модуль, который знает про токены, и больше никто. Внутри — получение токена, хранение срока жизни, обновление заранее, один повтор при отказе по авторизации и вежливая пауза при ответе «слишком часто».
class AvitoClient:
def _token(self): ... # отдаёт свежий, обновляет при необходимости
def list_chats(self): ... # непрочитанные диалоги
def get_messages(self, chat): ...
def send_message(self, chat, text): ...
Методы названы по смыслу: «получить список диалогов», «прочитать сообщения», «отправить сообщение». Как именно они называются в API — вопрос к документации; ваш код всё равно должен прятать это за своим интерфейсом, чтобы при изменении на стороне площадки правка была в одном файле.
Приёмник и очередь
@app.post("/hook")
def hook(payload):
if storage.seen(payload.event_id):
return 200
storage.mark_seen(payload.event_id)
storage.enqueue(payload)
return 200
Три строчки, и в них два важных решения. Первое — таблица обработанных событий в базе, а не множество в памяти: множество обнулится при перезапуске, и утренний поток обработается повторно. Второе — очередь как таблица со статусом. На старте этого достаточно, отдельный брокер понадобится тысячами диалогов позже.
Воркер берёт задачу, ставит блокировку по идентификатору диалога и работает. Блокировка нужна ровно затем, чтобы три сообщения подряд от одного покупателя не превратились в три параллельных ответа вразнобой.
Пауза и склейка
Перед генерацией имеет смысл подождать несколько секунд и перечитать диалог. Покупатели часто дописывают: «Здравствуйте», потом «Ещё актуально?», потом «Торг есть?». Ответ на всё сразу читается как живой разговор, три реплики подряд — как автомат.
Побочная польза: мгновенный ответ выдаёт бота сильнее любых формулировок. Небольшая задержка стоит дёшево и делает переписку естественной. Про то, почему при этом важно всё же не тянуть, — в разборе как отвечать быстрее конкурентов.
База фактов и генерация
Главная ошибка первого прототипа — отдать модели голое сообщение покупателя. Она ответит уверенно и придумает наличие, доставку и скидку. Поэтому в brain.py собирается контекст:
- карточка товара: что это, цена, состояние, комплектность;
- условия: торг, доставка, самовывоз, оплата;
- ваши формулировки — как вы обычно отвечаете на типовые вопросы;
- явный список запретов: не обещать сроки, не называть чужие цены, не подтверждать то, чего нет в фактах.
И жёсткое правило: если ответа нет в фактах — не выдумывать, а звать человека. Для типовых вопросов дешевле держать шаблоны ответов и отдавать модели только то, что под шаблоны не подошло.
Готовый вариант той же логики выглядит так: «Папа БУ» отвечает словами продавца по его же карточкам, отсеивает нецелевых и передаёт человеку тех, кто готов к сделке.
Эскалация
Отдельный модуль с понятными правилами, а не условия, размазанные по коду. Типичный набор: покупатель назвал сумму, спросил про оплату или доставку конкретной датой, попросил человека, написал третий раз подряд без движения, начал раздражаться. Плюс страховка: после N сообщений подряд от бота диалог передаётся в любом случае.
Уведомление должно приходить туда, куда вы смотрите. Письмо на почту в среднем не работает. Отдельно полезен фильтр нецелевых обращений — часть диалогов не нужно ни вести, ни эскалировать, их достаточно вежливо закрыть.
Что ломается первым
Опыт живых диалогов даёт довольно предсказуемый список.
Дубли ответов. Причина всегда одна: долгий обработчик вебхука и повторная доставка. Лечится выносом работы в очередь.
Молчание после ночи. Истёк токен, обновления по факту отказа нет, процесс жив и в логах тишина. Нужен мониторинг времени с последнего успешного ответа.
Бот отвечает сам себе. В выборке сообщений не отфильтрованы собственные реплики. Проверяется на первом же тесте, но забывается регулярно.
Упор в лимиты. Список объявлений тянется перед каждым сообщением. Кеш на час решает.
Ответы не на том языке фактов. Цена в карточке одна, в описании другая, бот выбирает случайную. Источник правды должен быть один.
Когда не стоит писать своего бота
- Меньше десятка диалогов в день. Стоимость поддержки выше пользы.
- Некому дежурить. Своя система требует владельца: она ломается тихо, а покупатель об этом не сообщит.
- Нужны автопостинг, парсинг или интеграция с маркетплейсами. Через официальный доступ это не решается, а обходные пути стоят аккаунта.
- Вы ждёте, что бот будет продавать сам. Он снимает первую линию вопросов и доводит до человека, но сделку закрывает человек. Разница разобрана в статье про ботов для Авито.
Коротко
Бот для Авито на Python собирается из понятных частей, и ни одна из них не требует редких навыков. Скелет такой: тонкий приёмник вебхуков, очередь с блокировкой по диалогу, отдельный клиент API со всей логикой токенов, генератор ответа поверх базы фактов и явные правила эскалации. Начинайте в режиме черновика — пусть неделю бот пишет ответы вам, а не покупателям. Сроки и объёмы здесь для примера: они зависят от того, сколько у вас категорий и насколько стабильны условия продажи.
Если интересен результат, а не устройство, — тот же набор возможностей можно подключить к магазину без кода и посмотреть на своих диалогах в готовом сервисе.
Если решение под свой бизнес нужно, а разбираться самому некогда — напишите мне в Telegram: @artem_sergeevic. Я делаю такие сервисы на заказ: обсудим задачу и честно разберём, что в ней действительно нужно, а что можно не делать вовсе.