Агрегатор объявлений
bazito
Витрина объявлений для тех, кто переезжает: читает сотни открытых телеграм-каналов больше чем в десятке стран, разбирает цену, период и валюту правилами, вычищает личные контакты и показывает всё одной лентой с медианой по каждой выборке.
- 380+
- телеграм-каналов в чтении
- 19+
- стран на витрине
- 5
- разделов: жильё, транспорт, вещи, работа, услуги
Задача
Объявления для переезжающих разбросаны по сотням телеграм-каналов и чатов, по одному на город и тему. В типичном чате аренды объявлением оказывается одно сообщение из пяти-десяти, остальное вопросы и благодарности. Один агент рассылает одну квартиру по десяти чатам, а одну только валюту в корпусе пишут 81 способом.
Что я сделал
Собрал это конвейером на небольшом VPS. Открытые каналы читаются обычным HTTP без аккаунта Telegram, чаты через MTProto. Каждый пост проходит дедупликацию по нормализованному тексту, дешёвый префильтр, разбор правилами в строгий JSON, проверку цены на правдоподобие, склейку с тем же объектом из других каналов и очистку от контактов. Витрина это статический PWA на Vercel с данными из Supabase. Вертикали размечает модель пакетами, а рабочий цикл обходится без ключа к какой-либо внешней модели.
Инженерные решения
- 01
Деньги остаются за правилами
Цена, период и валюта разбираются детерминированно: именно там ошибка модели видна читателю. Каждая правка этих правил сначала проходит по всему корпусу: выборка кандидатов плюс случайный контроль около 8 000 постов, в котором не должно измениться ничего. Правка про парковку изменила 62 из 3 409 кандидатов, все 62 оказались парковкой, прочитанной как аренда, а в контроле не изменилось ничего.
- 02
Одна квартира, одна карточка
Пост, разосланный по десяти чатам, нормализуется и хешируется до разбора, поэтому десять копий стоят один разбор. Одну и ту же квартиру, по-разному описанную в разных каналах, склеивает отпечаток из региона, района, спален, цены и площади. Когда отпечаток научился различать регионы, карточек, смешивающих две страны, стало ноль, а крупнейшая склеенная группа сократилась с 973 постов до 239.
- 03
Модель там, где решает смысл
Услуга почти никогда не называет себя услугой, и правила ловили только около пятой части работы и услуг. Вертикали размечают подагенты Claude Code пакетами по 200 постов. Две независимые разметки одних и тех же 286 постов совпали на 98,6%, а сплошная разметка всего, что отсеяла сеть-кандидат, показала её настоящую полноту: 78%.
- 04
Контакты не попадают на витрину
Телефоны, ники и ссылки на личные профили вычищаются в конвейере до витрины. Кнопка на карточке ведёт в исходный канал, и автор получает ответ там, где сам опубликовал объявление. Счётчик посещений не загружается, пока посетитель не ответил на вопрос о куках.
Экраны
Итог
Работает на bazito.app, по-русски и по-английски: жильё, транспорт, вещи, работа и услуги из сотен каналов больше чем в десятке стран, медиана по каждой выборке и каждому району, гайды по ценам аренды, посчитанные по живым объявлениям, и три статьи о том, как это устроено, в разделе «Статьи».
Построено на
- Python
- httpx
- BeautifulSoup
- Telethon (MTProto)
- SQLite
- Supabase
- Vercel (static PWA)
- Claude Code subagents