Почему я написал собственный поиск по Telegram вместо готовых сервисов
Все началось с простой проблемы
В рабочих Telegram-каналах ежедневно публикуется огромное количество информации.
Через неделю найти нужное сообщение становится непросто.
Можно воспользоваться встроенным поиском.
Можно использовать сторонние сервисы.
Но ни один из вариантов полностью меня не устраивал.
В какой-то момент стало понятно: проще написать собственную систему.
Основные требования
Проект должен был решать несколько задач.
Во-первых, работать только с нужными каналами.
Во-вторых, хранить сообщения локально.
В-третьих, обеспечивать быстрый поиск без зависимости от Telegram.
Почему именно Telethon
После изучения нескольких библиотек выбор остановился на Telethon.
Она позволяет официально работать через Telegram API и получать историю сообщений без использования неофициальных методов.
Авторизация выполняется один раз, после чего можно регулярно синхронизировать новые публикации.
Архитектура проекта
Со временем структура проекта стала выглядеть так:
Telegram
│
▼
Telethon
│
▼
Collector
│
▼
SQLite
│
▼
FastAPI
│
▼
Web-интерфейсКаждый компонент отвечает только за свою задачу.
Collector получает сообщения.
SQLite хранит их.
API предоставляет поиск.
TGSearch — как мы построили систему поиска объявлений в Telegram и с какими проблемами столкнулись
Telegram давно перестал быть обычным мессенджером. Для многих он стал полноценной площадкой для торговли, поиска сотрудников, аренды жилья, продажи автомобилей и множества других задач. Проблема заключается в том, что поиск внутри Telegram работает только по одному каналу одновременно. Если объявление опубликовано в сотнях различных каналов, найти его становится практически невозможно.
Именно поэтому возникла идея проекта TGSearch — системы, которая автоматически собирает сообщения из большого количества Telegram-каналов, индексирует их и позволяет искать объявления как в единой базе данных.
Однако на практике всё оказалось значительно сложнее, чем казалось в начале разработки.
Архитектура проекта
Основой проекта стал Python.
В качестве клиента Telegram используется Telethon, так как именно MTProto позволяет получать историю сообщений каналов без использования Bot API.
Архитектура проекта разделена на несколько независимых модулей:
- модуль подключения к Telegram;
- синхронизация каналов;
- хранение данных;
- REST API;
- сервис поиска;
- веб-интерфейс.
Такое разделение позволило независимо развивать каждый компонент без нарушения общей архитектуры.
Первая проблема - Telegram не является базой данных
Первой ошибкой было предположение, что достаточно периодически читать последние сообщения.
На практике это не работает.
Пользователи:
- удаляют объявления;
- редактируют текст;
- меняют фотографии;
- закрепляют сообщения;
- публикуют одно и то же объявление повторно.
Поэтому простая загрузка последних сообщений очень быстро приводит к рассинхронизации базы.
В итоге была реализована полноценная система синхронизации.
Для каждого канала хранится:
- ID канала;
- access_hash;
- последний обработанный message_id;
- время последней синхронизации.
Благодаря этому повторные обходы читают только новые сообщения, а не всю историю заново.
Это позволило сократить время обновления базы в десятки раз.
Парсинг даты объявления оказался неожиданно сложной задачей
На первый взгляд кажется, что Telegram уже содержит дату публикации сообщения.
Это действительно так.
Но проблема в другом.
Дата публикации сообщения далеко не всегда является датой самого объявления.
Например:
Продам квартиру.
Размещено 12 июля.
или
Автомобиль продаётся с января.
или
Объявление актуально до 15 августа.
Если использовать только дату Telegram, поиск становится практически бесполезным.
Поэтому было принято решение извлекать дату непосредственно из текста объявления.
Во время разработки пришлось обработать множество вариантов записи:
12.05.2025
12/05/2025
12 мая
12 мая 2025
Сегодня
Вчера
Позавчера
5 часов назад
2 дня назад
Размещено сегодня
Обновлено вчераДополнительную сложность представляли разные языки.
Например:
Сегодня
Today
Сегодняшнее
Bugun
KechaВ результате был реализован отдельный модуль нормализации дат.
Он сначала пытается определить абсолютную дату.
Если это невозможно - вычисляет её относительно текущего времени.
После чего все значения приводятся к единому формату UTC.
Это позволило одинаково работать как со свежими объявлениями, так и с архивными сообщениями.
Телефонные номера - ещё одна неожиданная проблема
Казалось бы, номер телефона можно найти обычным регулярным выражением.
На практике оказалось иначе.
Пользователи записывают телефоны абсолютно по-разному.
Например:
+998901234567
+998 90 123-45-67
998901234567
90 1234567
(90)1234567
90-123-45-67Но это ещё не всё.
Очень часто номера намеренно "ломают", чтобы избежать автоматического сбора данных.
Например:
девяносто девять
90*123*45*67
9O1234567
+998(90)I23-45-67где вместо цифры "0" используется буква O, а вместо единицы - латинская I.
Встречались даже варианты:
девять восемь восемь девяносто...Обычная регулярка здесь уже бессильна.
Поэтому процесс поиска телефона был разделён на несколько этапов.
Сначала текст очищается.
Затем заменяются похожие символы.
Удаляются разделители.
После этого выполняется нормализация номера.
Например:
+998 (90) 123-45-67становится
998901234567Благодаря этому один и тот же номер всегда хранится в базе в едином формате независимо от того, как он был написан пользователем.
Дубликаты сообщений
Очень быстро выяснилось, что огромное количество объявлений публикуется сразу в нескольких каналах.
Иногда одно и то же сообщение встречалось более чем в пятидесяти источниках.
Если сохранять каждое сообщение отдельно, база начинает разрастаться очень быстро.
Было принято решение хранить каждое сообщение отдельно (так как у него уникальный channel_id и message_id), но дополнительно рассчитывать "отпечаток" текста после нормализации.
Для этого:
- удаляются лишние пробелы;
- приводится регистр;
- убираются служебные символы;
- нормализуются телефонные номера;
- очищаются ссылки.
Это позволяет в дальнейшем группировать практически одинаковые объявления и показывать пользователю один результат вместо десятков копий.
Производительность
Изначально синхронизация выполнялась последовательно.
При десятках каналов это было приемлемо.
После подключения нескольких сотен источников время обновления стало исчисляться десятками минут.
Решением стал переход на асинхронную модель.
Telethon отлично работает поверх asyncio.
Это позволило одновременно выполнять синхронизацию нескольких каналов без создания большого количества потоков.
В результате скорость обновления увеличилась в несколько раз при практически неизменном потреблении памяти.
Почему не Bot API
Этот вопрос возникает практически у всех.
Ответ простой.
Bot API не позволяет читать историю произвольных каналов.
Поэтому единственным вариантом оказался MTProto через Telethon.
Да, это требует авторизации обычного пользовательского аккаунта.
Но взамен появляется полный доступ к истории сообщений тех каналов, на которые подписан аккаунт.
Что получилось в итоге
Сегодня TGSearch представляет собой не просто парсер Telegram.
Это полноценная поисковая система, которая:
- автоматически синхронизирует сотни каналов;
- сохраняет сообщения в собственной базе данных;
- нормализует даты;
- извлекает телефонные номера независимо от формата записи;
- определяет дубликаты;
- предоставляет REST API для поиска;
- легко масштабируется за счёт модульной архитектуры.
Главный вывод, который мы сделали во время разработки, оказался довольно простым.
Самая сложная часть подобных проектов — не подключение к Telegram.
Настоящая сложность начинается после получения сообщения.
Именно очистка данных, нормализация, борьба с неоднозначными форматами, обработка исключений и обеспечение высокой производительности превращают обычный парсер в надёжную систему, пригодную для реального использования.