IT.
← Все проекты

Агрегатор объявлений

bazito

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

380+
телеграм-каналов в чтении
19+
стран на витрине
5
разделов: жильё, транспорт, вещи, работа, услуги

Задача

Объявления для переезжающих разбросаны по сотням телеграм-каналов и чатов, по одному на город и тему. В типичном чате аренды объявлением оказывается одно сообщение из пяти-десяти, остальное вопросы и благодарности. Один агент рассылает одну квартиру по десяти чатам, а одну только валюту в корпусе пишут 81 способом.

Что я сделал

Собрал это конвейером на небольшом VPS. Открытые каналы читаются обычным HTTP без аккаунта Telegram, чаты через MTProto. Каждый пост проходит дедупликацию по нормализованному тексту, дешёвый префильтр, разбор правилами в строгий JSON, проверку цены на правдоподобие, склейку с тем же объектом из других каналов и очистку от контактов. Витрина это статический PWA на Vercel с данными из Supabase. Вертикали размечает модель пакетами, а рабочий цикл обходится без ключа к какой-либо внешней модели.

Инженерные решения

  1. 01

    Деньги остаются за правилами

    Цена, период и валюта разбираются детерминированно: именно там ошибка модели видна читателю. Каждая правка этих правил сначала проходит по всему корпусу: выборка кандидатов плюс случайный контроль около 8 000 постов, в котором не должно измениться ничего. Правка про парковку изменила 62 из 3 409 кандидатов, все 62 оказались парковкой, прочитанной как аренда, а в контроле не изменилось ничего.

  2. 02

    Одна квартира, одна карточка

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

  3. 03

    Модель там, где решает смысл

    Услуга почти никогда не называет себя услугой, и правила ловили только около пятой части работы и услуг. Вертикали размечают подагенты Claude Code пакетами по 200 постов. Две независимые разметки одних и тех же 286 постов совпали на 98,6%, а сплошная разметка всего, что отсеяла сеть-кандидат, показала её настоящую полноту: 78%.

  4. 04

    Контакты не попадают на витрину

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

Экраны

Итог

Работает на bazito.app, по-русски и по-английски: жильё, транспорт, вещи, работа и услуги из сотен каналов больше чем в десятке стран, медиана по каждой выборке и каждому району, гайды по ценам аренды, посчитанные по живым объявлениям, и три статьи о том, как это устроено, в разделе «Статьи».

Построено на

  • Python
  • httpx
  • BeautifulSoup
  • Telethon (MTProto)
  • SQLite
  • Supabase
  • Vercel (static PWA)
  • Claude Code subagents