Полагаю, все мы однажды искали себе жилье. Кто-то — в собственность, большинство, вероятно, в аренду. Все, кто хоть раз пытался найти реальные предложения на досках объявлений, знают — это нереально. Такого количества спама нет, пожалуй, ни в одной другой сфере. После того, как окунешься в этот ад, обычно руки начинают чесаться применить свою IT-шность на благо ближнему. Результатом для меня стал проект Sobnik, о котором я и хочу рассказать.
Sobnik — это плагин для Chrome, который помечает посредников на досках объявлений. Пока работает только с Avito.ru, в ближайшем будущем я добавлю Irr.ru и другие крупные доски. Всех, кто сидит на чемоданах и кому не терпится попробовать, прошу в Google Web Store. Под катом я расскажу о технической стороне проекта, о его перспективах и о моих наблюдениях запротивником посредниками. Любители критиковать чужой JS-код также велкам, исходник клиентской части плагина доступен на github.
Для любителей точности уточняю: формально, Sobnik это «расширение», а не плагин, но уж больно я к последнему термину привык.
«Польза обществу», надеюсь, очевидна, поэтому сразу перейду к вопросу «зачем это лично мне». Столкнувшись в последний раз с поиском жилья, наплевавшись на спам, которым заполнен Интернет, насмотревшись на изобретательных риэлторов, я ощутил прямо таки укол совести. Как никак корабли уже бороздят просторы 21-го века, неужели мы, Программисты, не способны справиться с жалкими спамерами?
Поразмыслив, я рискнул предположить, что способны. Просмотра нескольких сотен объявлений было достаточно, чтобы понять — посредников выявить легко. Либо по содержанию объявления, слишком подозрительному или очевидно агентскому, либо по наличию множества предложений с одним и тем же номером телефона. Оставалось выбрать технологии, на основе которых эту идею можно было проверить — объявления нужно было распарсить, куда-то сохранить, и проанализировать. В качестве парсера я выбрал Google Chrome — для доступа ко всей нужной информации на досках объявлений требуется полноценный браузерный движок с работающим JavaScript-ом. Для серверных дел решил попробовать Go и MongoDB. Все три вещи были для меня в новинку, так что это была отличная возможность расширить горизонты и освоить что-то новое. В итоге получился Sobnik.
На первый взгляд — довольно просто. Доступным и достоверным индикатором служит номер телефона, на который дано множество объявлений. Ведь не станет же агент покупать под каждое объявление новую сим-карту! Кроме того, некоторые объявления содержат прямые упоминания что автор риэлтор и хочет комиссию. В теории оно конечно просто, на практике пришлось решать множество мелких вопросов:
Использование этих приемов позволяет автоматически выявлять большую часть посредников. Вот так выглядит Авито во время активности спамеров (красные и зеленые кружочки — результат работы Sobnik-а):
![image](https://habrastorage.org/r/w1560/files/71f/dbd/163/71fdbd16356b479ead820da5df52bbfa.png)
Плагин написан на JavaScript, поскольку функционала API Хрома вполне достаточно для поставленных целей. Единственная сложность была с получением изображения номера телефона. Дело в том, что Avito отдает его только для запросов с правильным Referer-ом. В браузере подделать этот заголовок возможности нет, а получить данные изображения, загруженного страницей Avito, не дает Cross-Origin Policy. Оказалось, что эту защиту легко обойти — я сохраняю страницу в формате MHTML через соответствующий API, а затем из полученной строки вырезаю нужный мне кусок, содержащий изображение в base64-кодировке. Таким же методом получаю доступ и к фотографиям квартир.
Далее, информация отправляется на сервер, где работает программа на Go. На самом деле две программы — все запросы выполняются асинхронно, одна программа пишет все запросы в очередь, вторая программа эти запросы обрабатывает. В клиентскую часть встроена логика по замедлению потока обращений к серверу в случае, если тот не успевает выполнять запросы вовремя. Такой подход позволит сгладить скачки нагрузки (очень надеюсь, что сегодня они возникнут). Данные хранятся в MongoDB.
Все это хозяйство я разместил на Amazon AWS (еще одна штука, которую хотел попробовать). Пока «Free Tier» вполне хватает, так что за хостинг не плачу.
Серверный API доступен публично, никакой авторизации. Подозреваю, что найдутся желающие побаловаться и напакостить, так что в ближайших планах — внедрить кое-какую защиту. В конечном счете почти наверняка приду к регистрации пользователей плагина, но пока не хочу добавлять лишних барьеров для желающих попробовать.
Исходный текст плагина открыт. Во-первых, все равно его не скроешь. Во-вторых, сразу видно какую именно информацию собирает плагин, так что у понимающих людей не будет вопросов касаемо приватности. Ну и, наконец, вдруг однажды появятся энтузиасты, желающие поучаствовать в разработке.
Централизованного краулера для сбора данных нет. Во-первых, Авито отрубает IP-шники, которые открывают порядка пары сотен страниц в час. Во-вторых, я надеюсь, что когда пользователей станет много, получится распределенный краулер — каждый откроет по паре объявлений, вот и наполнилась база. Однако, пока активных пользователей нет — база пуста. Основная польза от плагина в том, что не надо открывать агентские объявления, а если в базе пусто — то открывать придется все подряд. В общем, чтобы придать системе хоть какое-то ускорение, я сделал еще один плагин для внутреннего использования, который тихонько, примерно по страничке в минуту, сканирует на Авито предложения о сдаче квартир в Москве. Успевать за спамерами в пиковые часы не получается, но все же у вас, уважаемый читатель, будет возможность оценить как работает Sobnik: установили, открывайте на Авито вышеуказанный раздел и наслаждайтесь. Буду рад предложениям о том, как наладить сканирование Авито в более серьезных масштабах. Желающим могу выдать плагин для краулинга, если вдруг хотите помочь проекту или посканировать другой город или раздел.
Запустив сканирование аренды в Москве, я сделал несколько полезных наблюдений. Все они довольно логичны и кажутся очевидными, однако Sobnik позволил их наглядно проверить и подтвердить:
Этот список, в целом, позволяет глазами отфильтровать почти весь мусор, так что если вам лень ставить Sobnik — пользуйтесь.
Disclaimer: Я ни сколько не против риэлторов. Для них на Авито если специальная галочка, ставишь её — и всем сразу понятно что ты — агент. И конечно я в курсе, что во многих случаях агент просто необходим. Sobnik борется лишь с теми, кто спамит и пытается вас обмануть.
Развивать проект я планирую в двух направлениях:
Теоретически, когда будет активно сканироваться много досок, Sobnik сможет находить исходное объявление собственника по его копиям, опубликованным агентами на других досках. Удастся ли достигнуть этих высот покажет время, и конечно же ваши ценные комментарии.
Публиковать собираемую базу объявлений я не планирую, слишком уж нагло было бы красть и распространять эту информацию. Однако, раз уж финансовый план Авито не позволяет им самим фильтровать спамеров, этим займется Sobnik.
Вашим пожеланиям и предложениям буду очень рад.
С 10 октября проблема наполнения базы решена — установленный плагин в отдельной вкладке автоматически сканирует объявления, которые в данный момент требуются пользователям. Фактически теперь Sobnik это крупная вычислительная сеть, где каждый узел работает на общее дело. Таким образом, любой чистый список объявлений для любого региона обрабатывается за пару минут. Спасибо всем, кто предлагал свою помощь, бесплатные сервера, IP и каналы в Интернет, ваше желание помочь несказанно меня радует. Однако, теперь Sobnik с этим справляется сам.
Sobnik — это плагин для Chrome, который помечает посредников на досках объявлений. Пока работает только с Avito.ru, в ближайшем будущем я добавлю Irr.ru и другие крупные доски. Всех, кто сидит на чемоданах и кому не терпится попробовать, прошу в Google Web Store. Под катом я расскажу о технической стороне проекта, о его перспективах и о моих наблюдениях за
Для любителей точности уточняю: формально, Sobnik это «расширение», а не плагин, но уж больно я к последнему термину привык.
Зачем все это?
«Польза обществу», надеюсь, очевидна, поэтому сразу перейду к вопросу «зачем это лично мне». Столкнувшись в последний раз с поиском жилья, наплевавшись на спам, которым заполнен Интернет, насмотревшись на изобретательных риэлторов, я ощутил прямо таки укол совести. Как никак корабли уже бороздят просторы 21-го века, неужели мы, Программисты, не способны справиться с жалкими спамерами?
Поразмыслив, я рискнул предположить, что способны. Просмотра нескольких сотен объявлений было достаточно, чтобы понять — посредников выявить легко. Либо по содержанию объявления, слишком подозрительному или очевидно агентскому, либо по наличию множества предложений с одним и тем же номером телефона. Оставалось выбрать технологии, на основе которых эту идею можно было проверить — объявления нужно было распарсить, куда-то сохранить, и проанализировать. В качестве парсера я выбрал Google Chrome — для доступа ко всей нужной информации на досках объявлений требуется полноценный браузерный движок с работающим JavaScript-ом. Для серверных дел решил попробовать Go и MongoDB. Все три вещи были для меня в новинку, так что это была отличная возможность расширить горизонты и освоить что-то новое. В итоге получился Sobnik.
Как выявить агентов?
На первый взгляд — довольно просто. Доступным и достоверным индикатором служит номер телефона, на который дано множество объявлений. Ведь не станет же агент покупать под каждое объявление новую сим-карту! Кроме того, некоторые объявления содержат прямые упоминания что автор риэлтор и хочет комиссию. В теории оно конечно просто, на практике пришлось решать множество мелких вопросов:
- Авито и многие другие доски публикуют номер телефона в виде изображения, соответственно — номер приходится распознавать.
- Агенты активно прячут свои реальные телефоны. Телефон указывают в тексте объявления, словами, буквами, спецсимволами. Всю эту маскировку приходится выявлять и вскрывать.
- Некоторые собственники дают много объявлений на одну и ту же квартиру. Чтобы не зачислить их в риэлторы, приходится выяснять, о разных объектах идет речь в разных объявлениях, или об одном и том же. Связываться с распознаванием адресов я не стал, использую готовые географические координаты, доступные на многих досках.
- Самые продвинутые посредники рисуют свои реальные номера телефонов на фотографиях квартир. Таких товарищей сложнее всего выявить. Я не нашел надежного и легкого в применении OCR решения, способного распознавать номера на фотках. Пришлось покумекать и родить простой алгоритм, определяющий, есть ли на фото какой-либо текст, и такие объявления считать агентскими.
- В тексте объявления часто есть прямое упоминание о том, что автор — агент. Однако, поскольку компьютеры пока не научились понимать речь, надежного метода для полноценного использования этой информации я не придумал. Пока обошелся обнаружением некоторых наиболее распространенных и недвусмысленных фраз, благо этот критерий лишь дополняет основной детектор по номерам телефонов.
Использование этих приемов позволяет автоматически выявлять большую часть посредников. Вот так выглядит Авито во время активности спамеров (красные и зеленые кружочки — результат работы Sobnik-а):
![image](https://habrastorage.org/files/71f/dbd/163/71fdbd16356b479ead820da5df52bbfa.png)
Техническая сторона проекта
Плагин написан на 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.
Вашим пожеланиям и предложениям буду очень рад.
UPDATE:
С 10 октября проблема наполнения базы решена — установленный плагин в отдельной вкладке автоматически сканирует объявления, которые в данный момент требуются пользователям. Фактически теперь Sobnik это крупная вычислительная сеть, где каждый узел работает на общее дело. Таким образом, любой чистый список объявлений для любого региона обрабатывается за пару минут. Спасибо всем, кто предлагал свою помощь, бесплатные сервера, IP и каналы в Интернет, ваше желание помочь несказанно меня радует. Однако, теперь Sobnik с этим справляется сам.