Написал бота для поиска клиентов
Как из зависимости от одной площадки вырос конвейер лидов: две архитектуры, провал на Web Search, парсинг чатов, Telegram-бот поверх CLI, автозапуск по расписанию, дедупликация в PostgreSQL и грабли с asyncio.TL;DR: собрал систему на Python + LLM, которая парсит Telegram-чаты, находит людей с конкретными болями и генерирует персонализированные сообщения для аутрича. 7 чатов по 1000 сообщений — стоимость анализа $0.11.
1. Проблема одного канала продаж
Два года я зарабатываю на фрилансе — делаю Telegram-ботов, Mini Apps и автоматизации для бизнеса. За это время вырос с 40 до 270 тысяч в месяц. Неплохо, но была проблема, которая не давала масштабироваться: все заказы приходили с одной фриланс-площадки.
Это работало, пока работало. Но возникали независящие от меня проблемы — у клиентов замораживались счета или откладывались проекты, и я оставался без денег и без понимания, где брать новых заказчиков. Конечно, тут есть и мои ошибки: например, не защитил себя от подобных рисков договорами. Классическая зависимость от одного канала.
Я пробовал диверсифицироваться:
- Fiverr — 4 гига, ноль откликов за полгода (только мошенники писали). Хотя даже заграничную симку приобрёл для регистрации. Там неадекватная конкуренция с индусами и пакистанцами.
- Telegram-канал — 9 подписчиков (привет, мама. а не, мамы даже там нет).
Проблема была системной: мне нужен стабильный поток лидов, которых можно обрабатывать, передавать стажёрам, масштабировать. Можно, конечно, руками искать по чатам и каналам народ с болью, однако ручной поиск в чатах не масштабируется.
2. Идея: автоматизировать то, что делаю руками
Я и раньше находил клиентов в Telegram-чатах. Заходил в чаты селлеров, логистов, инфобиз. Искал сообщения типа «посоветуйте бота для…» или «как автоматизировать…». Но это занимало часы, это реально нужно анализировать, думать, вчитываться, смотреть, что за пользователь, — было непредсказуемо и не масштабировалось.
Я играл в Factorio — и оттуда вновь вдохновился идеей тотальной автоматизации. В игре ты не таскаешь руду руками — строишь конвейеры, которые делают это за тебя. Потом автоматизируешь производство конвейеров. Потом — производство фабрик, которые производят уже сами конвейеры.
чат ●────────▶ парсер
чат ─●───────▶ парсер
чат ───●─────▶ парсер
чат ─────●───▶ парсер
В разработке я стараюсь делать то же самое. Автоматизирую документацию, скиллы для LLM, пайплайны контейнеров, деплой. Поэтому каждый повторяющийся шаг — отличный кандидат на автоматизацию.
И тогда пришла такая мысль: а почему бы не автоматизировать основной входящий ресурс — потенциальных заказчиков? Нужен был конвейер. Так родилась концепция Lead Finder.
3. Архитектура v1: Web Search (спойлер: не сработало)
Первая идея была очевидной (ну для меня…):
ниша «селлеры wildberries» ↓ Web Search ищет каналы ↓ Telethon парсит каналы ↓ GPT ищет у авторов боли ↓ карточка лида
Посидел, помыслил, как я это хочу видеть, — ТЗ на 442 строчки. Расписал каждый модуль. Закинул в Claude Code, и спустя день итераций получил кое-какой MVP.
Результат первого запуска:
Входная ниша: "селлеры wildberries"
Сгенерировано запросов: 5
Найдено каналов: 2
Успешно распарсено: 1
Квалифицировано: 0
Ноль лидов.
Web Search находил статьи ПРО каналы («Топ-10 каналов для селлеров»), а не сами каналы. Google плохо индексирует Telegram и весь его контент. Ну а личные каналы мелких предпринимателей вообще не в поиске — у них там 500 подписчиков.
Можно было бы интегрировать TGStat API, но это усложнение и траты на стадии MVP. Да и главное: даже если найти канал, это ещё не лид с болью. Это просто канал.
4. Архитектура v2: парсинг участников чатов
Тут вспомнил: ведь в начальном ручном методе работа была в основном не с каналами, а с чатами. Поиск по их содержанию, по участникам чата — для самой простой ниши (селлеры маркетплейсов) это иногда по 10к участников и тысячи сообщений за короткий срез времени.
Короче, мысль: один чат = сотни потенциальных лидов.
seed-чаты: @marketplace_pro, … ↓ 1000 сообщений из чата ↓ только последние 10 дней ↓ LLM ищет болевые сообщения ↓ квалификация авторов ↓ карточки со ссылками на сообщения
Что изменилось концептуально:
| v1 | v2 |
|---|---|
| Ищем каналы через интернет | Парсим людей из известных чатов |
| Надеемся найти владельца бизнеса | Видим реальные сообщения с болями |
| Холодный контакт в личку | Можем ответить на конкретное сообщение в чате |
| Масштаб: единицы каналов | Масштаб: сотни участников |
чат 1000 сообщений
● ● ● ● ● ● ● ● ●
фильтр по боли
● ○ ○ ● ○ ○ ● ○ ○
карточки лидов
[1] [2] [3]
Результат: 7 чатов по 1000 сообщений. Стоимость анализа — $0.11. На выходе — список людей с конкретными болями, которые они сами написали за последние 10 дней.
5. Как выглядит результат
Карточка лида в Markdown-отчёте:
## Лид #1 — Оценка: 4/5
**Контакт:** @maxsmek
**Канал:** @max_seller_wb (1,240 подписчиков)
### Бизнес
Селлер Wildberries, ниша — товары для дома.
Судя по каналу, оборот 2-5 млн/мес. Ведёт канал сам, делится опытом.
### Болевые сообщения
**[2 дня назад]** в @marketplace_pro:
"Подскажите тг бота чтобы отслеживать остатки фактические
по складам... хоть как-нибудь, даже косвенно, чтобы успевать"
[Открыть сообщение →](https://t.me/marketplace_pro/8934)
**[5 дней назад]** в @wb_sellers:
"Кто автоматизировал ответы на отзывы? Трачу по 2 часа в день"
[Открыть сообщение →](https://t.me/wb_sellers/12847)
### Что предложить
Telegram-бот для мониторинга остатков по складам WB
с алертами при падении ниже порога.
### Готовое сообщение
"Макс, привет! Видел твой вопрос в чате про отслеживание
остатков по складам. Делаем как раз такие боты — мониторинг
в реальном времени + уведомления. Показать как работает?"
Ключевая фича — ссылки на сообщения
В итоге можно кликнуть на ссылку, перейти в чат и ответить прямо на вопрос человека. Это уже не холодный спам, а релевантный ответ на его публичный запрос. Так намного безопаснее, можно не так париться за блок аккаунта, хотя всё равно я создал отдельный аккаунт для этого дела.
Конверсия второго варианта выше на порядок. Ну, по идее. На практике пока только 1 из 6 ответил нормально, остальные просто проигнорировали. Но хотя бы не пожаловались.
6. Технические детали
Стек
- Python 3.11 — основа
- Telethon — Telegram API для парсинга
- gpt-5.1 — для квалификации (через CometAPI, прокси-площадку, доступную в России)
- Docker — для изоляции и Telegram-сессий
- Claude Code — для разработки (раньше сидел на Cursor, но понял, что каждый раз в восторге, когда выбираю Claude, поэтому переехал полностью)
Как основная IDE — NeoVim, привык со времён Arch (сейчас на Mac переехал). Cursor иногда использую, но только для быстрого чтения и редактирования файлов.
Почему gpt-5.1 через CometAPI
Для квалификации использую gpt-5.1 через CometAPI — это прокси для OpenAI API, доступный в России. Оптимально по соотношению цена/качество. Сначала ехал на gpt-4.1, но посмотрел: input у обеих моделей одинаковый, output у 5.1 дороже, но он меня не интересует — мне надо именно загружать в него большое количество сообщений для анализа. Пробовал Claude Sonnet — дороже при сопоставимом качестве для этой задачи. Экономия на масштабе ощутимая.
ЭТО НЕ РЕКЛАМА!
Telethon и авторизация
Как уже говорил, для Telethon использую дополнительный аккаунт — с него же потом и пишу лидам. Сначала хотел сделать бота более общедоступным: авторизацию Telethon пропустить через самого бота. Но Telegram заметил подмену и запретил так делать. Поэтому пока использую только для себя — код ввожу в терминале вручную при создании файла сессии. Сессии храню просто: локальный файл, который Docker забирает себе. Создаётся изолированно при помощи отдельного скрипта вне контейнера.
Логика обработки сообщений
- Берём 1000 сообщений из чата
- Отсекаем всё старше 10 дней
- Отправляем пачку в LLM для поиска болевых сообщений
- Запоминаем авторов болевых сообщений
- Квалифицируем каждого автора отдельно
Люди без личного канала тоже анализируются — просто у них ниже оценка, меньше гарантий, что это реально владелец бизнеса. Не отсекаю сразу.
Система оценок
Изначально делал 0–10, потом упростил до 0–5. Где 1 — уже потенциальный лид, но я работаю с оценкой от 2. Так проще фильтровать и меньше шума.
Web Search для обогащения
Изначально добавил поиск упоминаний в сети: username + ниша, имя + «отзывы». Но честно — пока не заметил конкретного буста в качестве квалификации. Траты есть, а выхлопа особого нет. Держу отключённым, может, потом докручу.
Защита от бана
Telegram банит за агрессивный парсинг. Реализовал три режима:
| Режим | Задержка между чатами | Между запросами |
|---|---|---|
| fast | 15-30 сек | 1-2 сек |
| normal | 30-60 сек | 2-3 сек |
| careful | 60-120 сек | 3-5 сек |
Плюс:
- рандомизация всех интервалов (не ровно 3 сек, а 2.3–3.7);
- лимит чатов за сессию;
- обработка
FloodWaitError— ждём, сколько сказали, плюс буфер.
За месяц использования — ни одного бана.
Структура проекта (v2)
lead_finder/ ├── config.py режимы безопасности ├── modules/ core-логика для CLI и бота │ ├── input_handler.py валидация входных данных │ ├── members_parser.py парсинг участников │ ├── qualifier.py LLM-квалификация │ ├── output.py форматирование │ └── enrichment/ │ ├── telegram.py парсинг каналов лидов │ └── web_search.py обогащение через поиск ├── bot/ появится в v3 ├── generate_session.py создание Telethon-сессии └── docker-compose.yml
7. Грабли и факапы
v1 с Web Search — главный провал
Потратил день на начальную архитектуру, которая не взлетела. Но это нормально: быстрые итерации важнее идеального плана. Переделал за день.
Claude Code уходит не туда
Конечно, это происходит постоянно. Самая частая проблема — забываешь прописать в инструкции, что нельзя трогать старый функционал. Начинает улучшать старые функции, которые работали. Откатываю через git, добавляю ограничение в промпт, еду дальше.
Ложноположительные
Система дала 4/5, а человек оказался не тем — конечно, бывает. Поэтому читаю карточки внимательно, а не спамлю всем подряд. LLM квалифицирует, но финальное решение — моё.
Авторизация через бота
Хотел красиво — чтобы пользователь авторизовывался прямо в боте. Telegram такое не пропустил. Пришлось откатиться к ручному вводу кода в терминале. Не масштабируется, но работает для личного использования.
8. Честные цифры
v2 (CLI)
| Метрика | Значение |
|---|---|
| Время разработки v2 | ~8 часов чистого времени |
| Строк кода (core-модули) | ~1500 (всё через Claude Code) |
| Стоимость анализа 7 чатов | $0.11 |
Использование
| Метрика | Значение |
|---|---|
| Seed-чатов в базе | ~30 (5 категорий по 4-8 чатов) |
| Активных программ в боте | 3 (селлеры, edtech, smm) |
| Написал лидам | 6 |
| Ответили | 1 (сказал «если потребуется — напишет») |
| Конверсия в заказ | пока 0, но и выборка маленькая |
Категории чатов: маркетплейсы, предприниматели, edtech, smm, риэлторы.
Честно — конверсия пока не впечатляет. Но система работает меньше месяца, выборка маленькая. Главное — процесс автоматизирован, я трачу минуты вместо часов на поиск.
9. v3: Telegram-бот
После того как CLI-версия заработала, захотелось полной автоматизации. Тратить время на ручные запуски — не масштабируется. За следующие несколько дней собрал полноценного Telegram-бота на aiogram 3.x.
Что получилось
Программы поиска — сохранённые конфигурации:
- Название + ниша («Селлеры WB», «Инфобизнес»)
- Список чатов для парсинга
- Настройки (min_score, max_leads, обогащение)
- Расписание автозапуска
Автозапуск по расписанию:
- APScheduler интегрирован в бота
- Каждая программа запускается в своё время
- После завершения бот присылает уведомление с результатами
Дедупликация:
- SQLAlchemy + PostgreSQL
- Лиды с одним username не дублируются
- История сохраняется, можно вернуться к старым
лид @maxsmek ──▶ уже в базе
лид @newlead ──▶ новый, в отчёт
Интерфейс через inline-кнопки:
- Никаких команд — только кнопки
- Создание программы — пошаговый диалог (FSM)
- Карточки лидов приходят прямо в бот
Пример работы
Утром в 09:00:
🔔 Автозапуск завершён
📁 Селлеры WB
⏰ Запуск в 09:00
📊 Результаты:
• Новых лидов: 5
[👀 Посмотреть лидов]
Нажимаю кнопку — получаю карточки:
🎯 Лид #1 из 5
Программа: Селлеры WB
━━━━━━━━━━━━━
👤 @username
⭐ Оценка: 4/5
💼 Бизнес: Селлер на WB...
😤 Боли: Теряет заявки между Excel и мессенджерами
💡 Что предложить: Бот для сбора заявок...
📝 Сообщение для @username:
━━━━━━━━━━━━━
Привет! Видел твой вопрос про потерю заявок.
У нас есть готовое решение...
[⏭ Следующий лид]
Стек бота
- aiogram 3.5 — асинхронный фреймворк для Telegram
- SQLAlchemy 2.0 — ORM для базы
- PostgreSQL — основная база на продакшене, SQLite для локальной разработки
- APScheduler — планировщик задач
- Docker — всё работает в контейнере
| Метрика | Значение |
|---|---|
| Время разработки v3 | ~1 неделя (поверх v2) |
| Строк кода (бот + БД) | ~1000 дополнительно |
Что изменилось архитектурно
APScheduler ─▶ парсинг ─▶ LLM
─▶ PostgreSQL ─▶ карточки в бот
CLI-модули (members_parser, qualifier, enrichment) стали библиотекой — бот их импортирует и использует как есть. Не пришлось переписывать логику. Разделение на CLI и бот позволило оставить оба интерфейса:
- CLI — для отладки, тестов, ручных прогонов
- Бот — для ежедневного использования
Грабли с ботом
APScheduler и asyncio. Scheduler хотел синхронные job-функции, а весь код — async. Решение: обернул async-функции в asyncio.create_task().
База заблокирована (SQLite). Несколько одновременных запусков программ — database locked. Перешёл на PostgreSQL для проды, проблема ушла.
FSM-состояния терялись. Использовал MemoryStorage — при перезапуске бота состояния сбрасывались. Для продакшена можно RedisStorage, но пока живу с этим.
Ошибка .get() на None. LLM иногда возвращал product_idea: None вместо {}. Код падал с AttributeError. Исправил все места на .get(key) or {} вместо .get(key, {}).
10. Что дальше
v3 работает, но есть что улучшить:
- Парсинг комментариев в каналах (сейчас только чаты)
- Мониторинг новых сообщений в чатах в реальном времени
- Скраппинг фриланс-площадок — Kwork, FL.ru
- A/B тестирование сообщений аутрича
Про сервис для других: хотелось бы открыть как сервис, но мешает авторизация Telethon. Каждому пользователю нужна своя сессия, а Telegram не пропускает автоматизацию через ботов. Варианты:
- Генерировать сессию вручную для каждого (не масштабируется)
- Использовать Telegram Login Widget (пока не разобрался, как подружить с Telethon)
- Ограничиться self-hosted версией с инструкцией
Пока использую только для себя. Если у кого есть идеи — пишите.
Реальный пример сообщения
🎯 Лид #14 из ??
Программа: Маркетплейсы
👤 @скроююзернейм
⭐ Оценка: 2/5
💭 С высокой вероятностью владелец или самостоятельно управляющий продавец на маркетплейсах. Есть явный запрос: отслеживать отзывы по кластерам на Ozon и WB. Боль формулируется как вопрос, без деталей объёма и последствий, поэтому глубина боли и формат решения пока неочевидны. Потенциально можно закрыть задачей по сбору и структурированию отзывов через парсер и дашборд, но нужно уточнение, что именно она хочет видеть под «кластерами».
💼 Бизнес:
Селлер на маркетплейсах Ozon и Wildberries (малый бизнес)
😤 Боли:
• «Подскажите, можно ли через какие либо программы отследить отзывы по кластерам ? На озон и вб»
💡 Что предложить:
Сервис/скрипт-парсер отзывов с Ozon и Wildberries с кластеризацией по темам и визуализацией в дашборде
✅ Решает: автоматический сбор и группировка отзывов по темам вместо ручного просмотра, что позволяет быстрее видеть типовые проблемы и запросы покупателей
💰 Ценность: экономия времени на ручной разбор отзывов, возможность оперативно видеть повторяющиеся проблемы и улучшать карточки/продукт по данным
📝 Сообщение для @тутимяпользователя:
ИМЯ, вы спрашивали в чате, можно ли отслеживать отзывы по кластерам на Ozon и WB. Это как раз можно сделать через парсер + небольшой дашборд: отзывы автоматически подтягиваются и группируются по темам (качество, доставка, размер и т.п.). Если интересно, могу показать, как это технически реализуется и что вы сможете видеть в отчётах, а вы поймёте, подходит ли это под ваши задачи.
11. Выводы
1. Автоматизируй свои процессы, а не только клиентские.
Вместо очередного бота для заказчика потратил 15 часов (8 на CLI + 7 на бота) на инструмент, который приносит заказчиков. ROI потенциально бесконечный.
2. LLM-first разработка работает.
Я не написал ни строчки кода руками — всё через Claude Code. От идеи до работающего MVP за 8 часов. От CLI до полноценного бота с базой и работой по расписанию — ещё неделя. Всем рекомендую. Кто читал статью про методологию — знает, о чём речь.
3. Провалы — часть процесса.
v1 с Web Search не сработала. Вместо того чтобы упираться, переделал архитектуру. v2 взлетела. Быстрые итерации важнее идеального плана. Провал — это информация, не приговор.
4. Документация — это контекст.
Каждую версию начинал с детального ТЗ. Это позволяло передавать контекст между сессиями Claude и не терять фокус. ТЗ — не бюрократия, это инструмент мышления. Особенно критично, когда разрабатываешь с LLM. Фиксирую все ошибки в отдельные ISSUES.md, каждая новая фича — новая документация, которая не должна конфликтовать с текущей реализацией. Каждый успешный запуск нового этапа — RESULT.md, в котором задокументирован пруф успеха.
5. Модульная архитектура окупается.
CLI-модули стали библиотекой для бота без переписывания. Разделение интерфейса (CLI/бот) и логики (парсинг/квалификация) позволило эволюционировать систему без заметных проблем. Хотя, возможно, есть незаметные.
Готов к гнилым помидорам. Как показывает практика — это только добавляет просмотров.