IT.
Все статьи

bazito: как устроен агрегатор объявлений из телеграм-каналов

Илья Трапезников Опубликовано

bazito.app собирает объявления о жилье, транспорте, вещах, работе и услугах из открытых телеграм-каналов и показывает их одной витриной. Сейчас в выдаче 26 762 объявления по 11 странам и 22 городам, от Белграда и Еревана до Пхукета, Бали и Дананга.

Дальше про то, где в такой системе тратятся деньги и где принимаются решения.

Витрина bazito: список объявлений об аренде в Сербии, слева фильтры по цене, спальням и району, у карточек цена в двух валютах
Раздел долгосрочной аренды по Сербии. Счётчики в шапке считаются по текущей выборке, а не по всей базе.

Дороже всего стоит полнота

Конвейер устроен вокруг одного вопроса: за какой пост имеет смысл платить. В типичном канале аренды объявлениями оказываются десять-двадцать процентов сообщений, остальное вопросы, благодарности и «сдал, всем спасибо», и прогонять это через модель значит жечь деньги на болтовне.

Поэтому перед разбором стоит дешёвый префильтр со взвешенными сигналами: цена и тип сделки весят по полтора, упоминание объекта единицу, детали вроде площади, депозита, этажа и бассейна по половине и не больше трёх штук в зачёт, а отрицательные признаки минус два. Сумма ниже порога, и сообщение до модели не доходит.

Существенно здесь другое: отброшенные сообщения не выбрасываются, а ложатся в базу вместе со своим счётом. Иначе порог двигают вслепую, а так видно поимённо, что именно фильтр съедает, и решение поднять или опустить планку принимается по списку потерь, а не по ощущению.

Дедупликация стоит там же, до разбора. Один и тот же пост, разосланный агентом по десяти чатам, приводится к общему виду и хешируется: снимается регистр, вырезаются ссылки и всё, что не буква и не пробел, схлопываются пробелы. Разметка и эмодзи, которыми пост украшают по-разному в разных каналах, до хеша не доживают, и десять копий превращаются в один разбор и один запрос к модели.

Граница между правилами и моделью

Первая версия разбирала посты только правилами, и на жилье этого хватало. На работе и услугах не хватило, и замер по корпусу показал, почему: правила дают точность около 92 процентов при полноте порядка 20.

Полнота проваливается не от небрежности регулярок, а потому, что услуга почти никогда не называет себя услугой. «Лечу 19.08 Москва-Дубай, возьму посылки», «ежедневно едем обновить визу», «кандидат наук, лингвокоуч, помогаю заговорить за месяц» это доставка, визаран и репетитор, и ни в одном нет слова, по которому их поймала бы регулярка.

Отсюда разделение труда, которое я считаю главным решением в проекте. Смысл поста, то есть намерение и вертикаль, определяет модель. Деньги остаются за правилами: периоды, вилки, нетто и брутто, валюта канала разбираются детерминированно, потому что здесь правила как раз сильны, а модель непредсказуема ровно в том месте, где цена ошибки видна пользователю.

Безопасность вердикту модели не подчиняется вообще. Проверка на вербовочные схемы работает до неё и независимо: заблокированный пост остаётся заблокированным, что бы модель ни ответила. Иначе вербовку протаскивают переформулировкой.

Сколько стоило признать, что замер был неверен

Модели показывают не весь корпус. Широкая сеть по словам сужает выборку: из 42 660 неповторных постов она забирает 17 339, а после отсева уверенно разобранного жилья и транспорта остаётся 8 526, то есть пятая часть корпуса. Половина запросов сэкономлена.

Дальше началась история, ради которой этот раздел и написан. Сеть расширили новыми словами, проверив полноту на трёхстах случайных отвергнутых постах. Прибавку затем проверили на свежих данных, и проверка её заметно урезала: на выборке, по которой слова подбирались, получалось 41,5 процента вертикалей, а без неё 38,3.

Честный итог тогда выглядел так: сеть теряла около восьмисот вертикалей, расширение возвращает около восьмидесяти, полнота растёт с 62 процентов до 66. Это совсем не то же самое, что «поймали половину пропущенного», и удерживаться от второй формулировки стоило усилий.

А потом разметили всё отвергнутое подряд, 10 894 поста, и нашли там 397 вертикалей. Значит настоящая полнота сети была не 62 процента, а 78, и прежняя оценка занижала её, потому что считалась по выборке до расширения. С этого дня сеть перестала быть отбором корпуса: размечается всё, что проходит условия ступени.

Два вывода я забрал в другие проекты. Оценка по выборке в триста штук уверенно врёт в обе стороны. И цифру, полученную на тех же данных, на которых подбирался метод, надо перемерять на свежих, иначе она красивая и неверная.

Медиана вместо чутья

Извлечённая цена сама по себе мало что говорит: 350 евро за квартиру это дорого или дёшево, зависит от города, площади и месяца. Поэтому по каждой выборке считается медиана, и карточка показывает, насколько объявление от неё отклоняется.

Карточка объявления: цена 408 долларов в месяц, отметка «на 32% ниже медианы», кнопка «Написать в @beograd_stan» и пометка «3 источника»
Одна карточка показывает сразу три вещи: отклонение от медианы, склейку из трёх каналов и то, что писать предлагается в канал.

Медиана, а не среднее, потому что одна вилла за десять тысяч не должна двигать ориентир для всей выборки. И считается она по той выборке, которую человек видит сейчас, поэтому после смены фильтров цифра меняется.

Что не попадает на витрину

Контакты. Ни телефонов, ни ников, ни ссылок на личные профили: очистка стоит в конвейере до витрины, и на самой витрине это написано прямым текстом, без посредника и комиссии.

Кнопка на карточке поэтому ведёт в исходный канал. Это на клик дольше, зато автор получает ответ там, где сам опубликовал объявление.

Есть страница жалоб и кнопка обращения на каждой карточке, к обращению автоматически прикрепляется, о каком объявлении речь. Счётчик посещений не загружается, пока посетитель не ответил на вопрос о куках.

География

Страны и города не заданы в коде, они следствие того, какие каналы читаются: список лежит в конфигурации, добавились каналы по Бали, появился Бали. Поэтому текущая карта выглядит так, как выглядит: ОАЭ, Армения, Болгария, Кипр, Грузия, Индонезия, Черногория, Сербия, Таиланд, Турция, Вьетнам. Она выросла по тому, где нашлись живые каналы, а не по плану развития.

Проект целиком, с архитектурой, решениями и цифрами, собран на странице кейса bazito.


Цифры витрины и скриншоты сняты 22 августа 2026 года, замеры полноты относятся к концу августа и названы в тексте. Витрина обновляется ежедневно.