Полагаю, все мы однажды искали себе жилье. Кто-то — в собственность, большинство, вероятно, в аренду. Все, кто хоть раз пытался найти реальные предложения на досках объявлений, знают — это нереально. Такого количества спама нет, пожалуй, ни в одной другой сфере. После того, как окунешься в этот ад, обычно руки начинают чесаться применить свою IT-шность на благо ближнему. Результатом для меня стал проект Sobnik, о котором я и хочу рассказать.
Sobnik — это плагин для Chrome, который помечает посредников на досках объявлений. Пока работает только с Avito.ru, в ближайшем будущем я добавлю Irr.ru и другие крупные доски. Всех, кто сидит на чемоданах и кому не терпится попробовать, прошу в Google Web Store. Под катом я расскажу о технической стороне проекта, о его перспективах и о моих наблюдениях за противником посредниками. Любители критиковать чужой JS-код также велкам, исходник клиентской части плагина доступен на github.
Для любителей точности уточняю: формально, Sobnik это «расширение», а не плагин, но уж больно я к последнему термину привык.
Зачем все это?
«Польза обществу», надеюсь, очевидна, поэтому сразу перейду к вопросу «зачем это лично мне». Столкнувшись в последний раз с поиском жилья, наплевавшись на спам, которым заполнен Интернет, насмотревшись на изобретательных риэлторов, я ощутил прямо таки укол совести. Как никак корабли уже бороздят просторы 21-го века, неужели мы, Программисты, не способны справиться с жалкими спамерами?
Поразмыслив, я рискнул предположить, что способны. Просмотра нескольких сотен объявлений было достаточно, чтобы понять — посредников выявить легко. Либо по содержанию объявления, слишком подозрительному или очевидно агентскому, либо по наличию множества предложений с одним и тем же номером телефона. Оставалось выбрать технологии, на основе которых эту идею можно было проверить — объявления нужно было распарсить, куда-то сохранить, и проанализировать. В качестве парсера я выбрал Google Chrome — для доступа ко всей нужной информации на досках объявлений требуется полноценный браузерный движок с работающим JavaScript-ом. Для серверных дел решил попробовать Go и MongoDB. Все три вещи были для меня в новинку, так что это была отличная возможность расширить горизонты и освоить что-то новое. В итоге получился Sobnik.
Как выявить агентов?
На первый взгляд — довольно просто. Доступным и достоверным индикатором служит номер телефона, на который дано множество объявлений. Ведь не станет же агент покупать под каждое объявление новую сим-карту! Кроме того, некоторые объявления содержат прямые упоминания что автор риэлтор и хочет комиссию. В теории оно конечно просто, на практике пришлось решать множество мелких вопросов:
- Авито и многие другие доски публикуют номер телефона в виде изображения, соответственно — номер приходится распознавать.
- Агенты активно прячут свои реальные телефоны. Телефон указывают в тексте объявления, словами, буквами, спецсимволами. Всю эту маскировку приходится выявлять и вскрывать.
- Некоторые собственники дают много объявлений на одну и ту же квартиру. Чтобы не зачислить их в риэлторы, приходится выяснять, о разных объектах идет речь в разных объявлениях, или об одном и том же. Связываться с распознаванием адресов я не стал, использую готовые географические координаты, доступные на многих досках.
- Самые продвинутые посредники рисуют свои реальные номера телефонов на фотографиях квартир. Таких товарищей сложнее всего выявить. Я не нашел надежного и легкого в применении OCR решения, способного распознавать номера на фотках. Пришлось покумекать и родить простой алгоритм, определяющий, есть ли на фото какой-либо текст, и такие объявления считать агентскими.
- В тексте объявления часто есть прямое упоминание о том, что автор — агент. Однако, поскольку компьютеры пока не научились понимать речь, надежного метода для полноценного использования этой информации я не придумал. Пока обошелся обнаружением некоторых наиболее распространенных и недвусмысленных фраз, благо этот критерий лишь дополняет основной детектор по номерам телефонов.
Использование этих приемов позволяет автоматически выявлять большую часть посредников. Вот так выглядит Авито во время активности спамеров (красные и зеленые кружочки — результат работы Sobnik-а):
Техническая сторона проекта
Плагин написан на JavaScript, поскольку функционала API Хрома вполне достаточно для поставленных целей. Единственная сложность была с получением изображения номера телефона. Дело в том, что Avito отдает его только для запросов с правильным Referer-ом. В браузере подделать этот заголовок возможности нет, а получить данные изображения, загруженного страницей Avito, не дает Cross-Origin Policy. Оказалось, что эту защиту легко обойти — я сохраняю страницу в формате MHTML через соответствующий API, а затем из полученной строки вырезаю нужный мне кусок, содержащий изображение в base64-кодировке. Таким же методом получаю доступ и к фотографиям квартир.
Далее, информация отправляется на сервер, где работает программа на Go. На самом деле две программы — все запросы выполняются асинхронно, одна программа пишет все запросы в очередь, вторая программа эти запросы обрабатывает. В клиентскую часть встроена логика по замедлению потока обращений к серверу в случае, если тот не успевает выполнять запросы вовремя. Такой подход позволит сгладить скачки нагрузки (очень надеюсь, что сегодня они возникнут). Данные хранятся в MongoDB.
Все это хозяйство я разместил на Amazon AWS (еще одна штука, которую хотел попробовать). Пока «Free Tier» вполне хватает, так что за
Серверный API доступен публично, никакой авторизации. Подозреваю, что найдутся желающие побаловаться и напакостить, так что в ближайших планах — внедрить кое-какую защиту. В конечном счете почти наверняка приду к регистрации пользователей плагина, но пока не хочу добавлять лишних барьеров для желающих попробовать.
Исходный текст плагина открыт. Во-первых, все равно его не скроешь. Во-вторых, сразу видно какую именно информацию собирает плагин, так что у понимающих людей не будет вопросов касаемо приватности. Ну и, наконец, вдруг однажды появятся энтузиасты, желающие поучаствовать в разработке.
Централизованного краулера для сбора данных нет. Во-первых, Авито отрубает IP-шники, которые открывают порядка пары сотен страниц в час. Во-вторых, я надеюсь, что когда пользователей станет много, получится распределенный краулер — каждый откроет по паре объявлений, вот и наполнилась база. Однако, пока активных пользователей нет — база пуста. Основная польза от плагина в том, что не надо открывать агентские объявления, а если в базе пусто — то открывать придется все подряд. В общем, чтобы придать системе хоть какое-то ускорение, я сделал еще один плагин для внутреннего использования, который тихонько, примерно по страничке в минуту, сканирует на Авито предложения о сдаче квартир в Москве. Успевать за спамерами в пиковые часы не получается, но все же у вас, уважаемый читатель, будет возможность оценить как работает Sobnik: установили, открывайте на Авито вышеуказанный раздел и наслаждайтесь. Буду рад предложениям о том, как наладить сканирование Авито в более серьезных масштабах. Желающим могу выдать плагин для краулинга, если вдруг хотите помочь проекту или посканировать другой город или раздел.
Наблюдения за риэлторами
Запустив сканирование аренды в Москве, я сделал несколько полезных наблюдений. Все они довольно логичны и кажутся очевидными, однако Sobnik позволил их наглядно проверить и подтвердить:
- В рабочие дни порядка 80% объявлений принадлежат агентам. Авито, кстати, активно банит очень много объявлений, так что из 30 объявлений в минуту через час остается от силы 10. Однако, из этих десяти все равно подавляющее большинство — посредники.
- Поздно вечером (после 10-11 часов), и в выходные — агентов почти нет. Отдыхают видать от тяжелых спамерских будней.
- Платные объявления (на Авито они выделены желтоватым цветом) — почти всегда собственники. Пока я видел только одного агента, не пожалевшего сотню рублей на рекламу элитной квартиры. Есть вероятность, что это был собственник, решивший сделать вид что он агент с эксклюзивом и срубить лишних денег (бывают такие, судя по слухам).
- Если в объявлении всего одна или две фотографии, это почти наверняка агент. Три фотки — 50 на 50. Собственники либо пишут вообще без фото, либо уж если напряглись — делают хотя бы пяток.
- Если телефон указан на фотографии, либо «зашифрован» в тексте объявления — это почти наверняка агент. Шифроваться подобным образом их заставляет Авито, который требует денег за размещение большого количества объявлений на один и тот же номер телефона.
Этот список, в целом, позволяет глазами отфильтровать почти весь мусор, так что если вам лень ставить Sobnik — пользуйтесь.
Disclaimer: Я ни сколько не против риэлторов. Для них на Авито если специальная галочка, ставишь её — и всем сразу понятно что ты — агент. И конечно я в курсе, что во многих случаях агент просто необходим. Sobnik борется лишь с теми, кто спамит и пытается вас обмануть.
Перспективы
Развивать проект я планирую в двух направлениях:
- Добавлять новые доски (следующей, вероятно, будет «Из рук в руки»).
- Повышать точность и надежность детектора.
Теоретически, когда будет активно сканироваться много досок, Sobnik сможет находить исходное объявление собственника по его копиям, опубликованным агентами на других досках. Удастся ли достигнуть этих высот покажет время, и конечно же ваши ценные комментарии.
Публиковать собираемую базу объявлений я не планирую, слишком уж нагло было бы красть и распространять эту информацию. Однако, раз уж финансовый план Авито не позволяет им самим фильтровать спамеров, этим займется Sobnik.
Вашим пожеланиям и предложениям буду очень рад.
Автор: cerber