Обложка: Мой pet-проект: сервис по сбору и категоризации объявлений о продаже телефонов

Мой pet-проект: сервис по сбору и категоризации объявлений о продаже телефонов

Михаил Альфа

Михаил Альфа

ведущий разработчик в «Россельхозбанке» («РСХБ-ИНТЕХ»)

Добрый день! Меня зовут Михаил Альфа, я являюсь ведущим разработчиком. Сам себя определяю как Fullstack-разработчик, т. к. писал и пишу практически все, что сейчас популярно писать — Frontend, Backend и Mobile. Мой технологический стек, возможно, не слишком обширен:

  • Frontend на Vue или React;
  • Backend: Node.js, особенно нравится в сочетании с Nest.js;
  • Mobile: Flutter — one love;
  • Ну и, конечно, все это (кроме mobile) — обмазано TypeScript, без него точно никуда​.

Еще я посматриваю на таких кракенов, как Rust, но глаза пока боятся нырять в эту нору. Когда-то раньше я писал и на PHP. Это было на Symfony 3 и 4 версий (даже и 2 иногда). И эта история будет об одном моем pet-проекте, написанном, в основном, на PHP. Прежде, чем начать выкладывать сей опус я пытался найти его исходники в своих репозиториях. К сожалению — безуспешно. Вероятно, в очередном приступе синдрома самозванца, ночью, после трудового будня я решил, что пора избавиться от гнетущего наследия, взглянуть на которое без слез было бы нельзя. И удалил все, что мне казалось когда-то важным, перспективным, на что я тратил время, огромное количество времени, возможно, и душу.​ Но хватит лирики, едва ли эта статья будет интересной, если в ней и будет, что только моя рефлексия. Давайте сменим настроение (я сменю) и помчимся вперед!​

Предыстория

​Путь к данной истории начался в 2014-м году, я учился в вузе и был вынужден уйти в академический отпуск из-за финансовых трудностей, появившихся в моей семье. Устроившись на неплохую работу, я начал зарабатывать первые в своей жизни существенные суммы (существенные, разумеется, для вчерашнего студента, единственным заработком которого до этого была стипендия и редкие подработки, да помощь с выполнением различных задач из вуза одногруппникам — за 💵, разумеется). Работа спорилась, время шло и наступил долгожданный момент, когда можно было снова вернуться к учебе.​

Было очень тяжело терять то, к чему успел привыкнуть, привязаться, что стало таким родным и близким. И нет, я говорю не о радушных и прекрасных коллегах, я говорю — о денежках.​ Так повелось, что я всю жизнь интересовался мобильными телефонами / смартфонами, эдакий техно-гик. И разбирался я в них отлично, пользовался, конечно, далеко не флагманскими моделями, но самым лучшим, что только можно было купить за те финансы, которые у меня пели романсы. Тут-то и появилась идея — применить свои знания на практике. Кто-то задастся вопросом — как применить такие знания на практике? Идти в какой-нибудь магазин электроники, да продавать телефоны? А вот и нет! Идея, действительно, была в том, чтобы продавать телефоны, да только не чьи-то, где-то, генерируя чью-то прибыль, а продавать свои. ​Неосознанно я занимался этим и раньше, только не придавал этому какого-то особенного значения. Например, мне удалось через цепочку обменов, продаж и покупок, без дополнительных денежных вливаний превратить свой старенький Sony Xperia Neo в Sony Xperia Z1.​

​​​​​​Провернуть эти операции я смог за пару месяцев, и был несказанно счастлив, хоть в тот момент, когда это и произошло, флагманом был Sony Xperia Z2, а вот-вот должен был выйти и Z3, но я утешал себя тем, что и Z3 будет практически таким же, как мой Z1, да и вообще, до этого у меня был Neo.​ Так вот, вполне простая идея начала воплощаться в реальность. В народе таких людей принято называть перекупщиками. И мне пришлось стать таким. Алгоритм данной деятельности был довольно простым — ищешь телефон с лучшими на данный момент характеристиками, как можно дешевле покупаешь (нередко еще и неплохо сбивая цену), затем выставляешь объявление и продаешь. Разницу — в карман. Безусловно, есть и риски и весьма немаленькие. Я покупал и дефектные смартфоны, и такие, которые становились дефектными спустя буквально пару дней, и это все приносило существенные убытки.​ Скажу честно, однажды я даже купил по почте топорную подделку iPhone 5S, поведясь на красивую историю о том, что человеку срочно были нужны деньги на какое-то важное дело (на самом деле я повелся на низкую цену, а алчность просто застилала мои глаза). И каково же было мое удивление, когда я прямо на почте, дрожащими, мокрыми от волнения и страха ладошками открывал коробку с посылкой, и увидел внутри … не iPhone 5S 😂. Посылка была с наложенным платежом и почтальон лишь сочувственно пожала плечами.​

Мы ничего не можем сделать. Посылка получена, деньги мы вернуть не можем. А ведь я «подстраховался» — попросил продавца отправить посылку с описью. Ну, опись действительно была:

  • телефон;
  • кабель для зарядки;
  • коробка;
  • зарядка​.

Не прикопаешься в общем.​Что было дальше — история на еще один рассказ, но кратко — я приобрел опыт. Как известно, опыт — это то, что мы получаем вместо того, что хотели получить.​

Ближе к делу

​Дни летели, я учился. Кодил учебные проекты на самые разные темы, совершенно никак не связанные с тем, что предстоит делать в реальном мире на реальной работе. По-прежнему перепродавал телефоны, еще и ноутбуки пошли в копилку. И что-то у меня в голове щелкнуло:​ надо автоматизировать свою деятельность.​ По крайней мере настолько, насколько это возможно. Идея была такой — весь алгоритм, который мне нужно было реализовывать, чтобы называть эту деятельность успешной, был весьма прост. Нашел лучшее по минимальной цене, сторговался, продал дороже. Нюансы начинаются в том, как понять — что есть лучшее за эту цену? К примеру, когда на рынке iPhone 5S уже не являлся «крутым» телефоном, его ценник на рынке досок объявлений был, условно, 15 000₽ за версию на 16Gb. Соответственно, мне было нужно найти эту модель за сумму, меньшую, чем 15 000₽. При этом средний срок продажи телефона составлял от недели до двух (это сильно зависело от модели, производителя, хайпа вокруг марки). А за это время, особенно в преддверии анонсов новых моделей, цена конкретного устройства могла упасть настолько, что ни о какой прибыльности и речи идти не могло.​

Проект

​Что я сделал? Первым делом было нужно собрать данные, которые были необходимы для анализа. Для этого я начал писать grabber — некоего паука, который ходил по доскам объявлений и искал интересующие меня категории продаваемых товаров, а именно: смартфоны и ноутбуки. Забегу вперед и скажу, что все, что я делал — использовал только в личных целях, никому эти данные не передавал, да и не захотел бы этого никогда делать, уж сильно они казались мне ценными.​

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

У другого источника информации API вообще было открытым, чему я был несказанно рад — намного приятнее работать с JSON, чем вычленять нечто селекторами из HTML, да еще и на PHP. А верстка, как оказывается, менялась с завидной регулярностью, но обычный пользователь этого не увидит.​ Дальше больше — вот у меня есть свое злато, а что с ним делать? Нужно же как-то понять, что из этого мне может быть полезно, а что — совершенно точно нет. Для начала предстояло решить новые задачи.​

Новые задачи

​Как оказалось, пользователи, выкладывающие свои объявления на площадках, могут называть свои устройства абсолютно как угодно. К примеру, вот вариации того же злополучного iPhone 5S:

  • Продается iphone 5s;
  • IPHONE 5S;
  • Айфон 5с;
  • Продается телефон;
  • 5S на 32​;

И так далее…​ Вариаций — великое множество, но и это еще не все. В примере выше проскользнула еще одна деталь: 32. 32, Карл! Оказывается, что iPhone 5S может быть как на 16Gb, так и на 32, а еще и на 64Gb! Есть, конечно, и цвета, но они, к счастью, не слишком влияют на цену. Но памяти оказалось достаточно. И она влияет сильно. Как вы понимаете — второй задачей после сбора информации стала категоризация всего собранного каталога. Площадки предоставляли малую толику информации, например, я мог быть почти уверен, что если телефон был получен из категории устройств iPhone — то это, скорее всего, iPhone. Конечно, не всегда, некоторые люди отчаянно запихивали свои товары в чужие категории, видимо, очень не хотели расставаться со своими любимыми игрушками, но в большинстве случаев на эту кроху полезности можно было положиться.​

Тут, возможно, найдутся люди, которые закидают меня тряпками (а я буду рад, т. к. в данный момент у меня решается такая же проблема, но в другой предметной области), и скажут — что так как я, делать не стоило, а стоило вот так! (Как, кстати? А кроме нейронок?) ​Ну а я решил эту задачу таким способом: сначала было необходимо полностью очистить названия от всех посторонних символов — специальные знаки, эмодзи, пробелы, кириллица. Был составлен словарь, который постоянно пополнялся, благодаря которому можно было преобразовывать «афон» в «iPhone». Затем эта очищенная строка сравнивалась со всеми остальными имеющимися строками в базе, которые еще не были в сравнении с текущий, так же очищенными от всякого… ну вы поняли.

Сравнение было не простым, а с использованием алгоритма схожести строк — расчетом расстояния Левенштейна. Это было весьма долго и неэффективно. ​​Данных было очень много (для моего домашнего компа) — сотни тысяч записей, и все их нужно было кластеризировать. Но в итоге у меня начали образовываться группы объявлений, которые были похожи друг на друга. Точность на этом моменте была относительно невысокой — порядка 60–70%, но и это было неплохо. Затем в ход пошли не только заголовки объявлений, но и описания. Довольно часто «Айфоны на 32 гига» в описании назывались нормальным именем (в основном благодаря тому, что люди могли просто копировать описания телефонов из магазинов и использовать в своих объявлениях), благодаря этому точность удалось повысить до стабильных 70–75%. Но мало, мааало!

Дальше пошли эксперименты (за утерю которых мне сейчас очень обидно) — я разбивал эти строки на некие токены определенной длины, с перекрытием в несколько символов, и сравнивал уже их, считал количество совпадений, выделял определенные токены и назначал им веса, ведь важность совпадения «ipho» в двух строках выше, чем какой-нибудь «e32gb», время обработки росло все быстрее и быстрее, но росла и точность. Насколько я помню, у самого успешного варианта была точность > 85% в среднем!​ После этого качеством категоризации можно было гордиться и у данного проекта появилась хоть какая-то практическая ценность — можно было находить интересные модели смартфонов и сравнивать их по ценам, по прежнему вычитывая описания и просматривая фотографии. Ведь наш айфон может стоить на 10% ниже рынка не только потому, что продавцу срочно нужны деньги, но и потому, что в описании указано «пару раз падал, но выглядит как новый», ага.​

Следующая задача — нужно как-то понять, стоящий ли перед нами аппарат — вернее, стоит ли он своих денег в конкретный момент времени. Тут начинается полное безумие — нейронные сети на PHP.​​ Я даже помню имя этого безумия — FANN. Решение было таким: сначала я, как представитель экспертной группы «людей, разбирающихся в том, стоит ли данный телефон своих денег», прочитал несколько тысяч описаний к самым разным телефонам, оценив, насколько хорошим является данный экземпляр. Для этого была даже создана специальная мини-страничка с оцениванием — там было название телефона, описание и 10 кнопок от 1 до 10. Нажал кнопку — оценка записана, читай следующее объявление. Заняло это около недели. Чтиво было занятным 😑. А затем, я просил своих товарищей, одногруппников (про толоку я тогда не знал, или ее еще даже не было, не помню), чтобы и они оценили то, что оценил я. Для этого им в случайном порядке предлагалось оценить по той же шкале те объявления, что и оценивал я. Задача звучала примерно так: «Насколько бы вам захотелось купить этот телефон, если бы у вас точно были на него деньги?».​ Каким-то образом удалось собрать более-менее приемлемое количество дополнительных оценок, после чего была благополучно написана и обучена нейронка (я специально опускаю технические подробности сего аспекта, т.к. мои воспоминания об этом примерно такие: «Боже, что за чушь я тогда писал»).

Но самое интересное — она работала! Работала на таком уровне, что я смог начать ее использовать. То есть я действительно мог, к примеру, отсортировать список телефонов по данной оценке, и те из них, что были с 8+ оценкой — можно было покупать хоть сейчас! Да, точность не всегда была на высоте, например: кто-то мог выставить на продажу какой-нибудь ZTE Axon, статистики по которому совсем немного, и продается данный аппарат раз в месяц. И вот человек, который его выставляет, решает, что можно было бы его не только продать за 12 000₽, но и поменять на iPhone 5S 32Gb Space Gray. Вау! К сожалению, таких всплесков тоже было немало, и отлавливать их приходилось вручную. Но, как вы понимаете, вместо заветного айфончика в топе мог быть и аксон, который купить-то можно быстро, но продавать его будешь полгода :)​ Но в целом система работала и очень сильно помогала!

Но и это еще не все, с учетом того, что работала она к этому моменту, как минимум в качестве сборщика информации, больше полугода — было накоплено и просто много информации для статистики. Например, теперь можно было строить примерные прогнозы того, как сильно и как часто опускается цена на каждый из имеющихся на рынке телефонов. Можно было иметь представление о том, как долго продается каждая конкретная модель. К слову, считалось это так: когда объявление впервые попадало в базу данных сервиса — это был день, с которого начинался отсчет времени, необходимого на продажу. Затем, когда это объявление исчезало из выдачи, происходила проверка — переход на страницу конкретного объявления, и если эта страница не была страницей активного объявления, значит устройство, скорее всего, продано. Вот эту дату мы и запишем как дату продажи, и сможем понять, что наш айфоша продается по такой цене — неделю, по такой — две, а вот по такой — 3 дня.

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

​Еще одним плюсом от использования данного сервиса являлось то, что информацию о таких товарах удавалось получать практически в реальном времени. После того как все группы товаров были созданы, для анализа одной (или нескольких) новых записей требовалось совсем немного времени, поэтому, как только объявление появлялось на площадке — оно в течение пары минут оказывалось и в аналитическом сервисе.​

Эта история — история пути, а не цели, к которой я стремился. А планы были грандиозными — хотелось сделать рекомендательный сервис по подбору устройств на б/у рынке, хотелось расширить технологический парк — анализировать не только смартфоны, но и множество других видов техники. К слову, в те же ноутбуки я пытался углубиться, но основной фокус был именно на телефонах. Но с течением времени, данная деятельность перестала помещаться в ограниченное время дня — даже для того, чтобы ездить за телефонами, нужно много времени, а если учесть, что действительно интересные варианты могут покупать в течение считаных часов и нужно быть всегда на подхвате, основная работа начинает немного мешать. Поэтому, перестав заниматься перепродажей телефонов я и потерял интерес к конкретному проекту, но тот опыт, что я получил, создавая его, останется со мной.​

Что же, кажется, пора подводить итоги. Делать выводы. Ну или нет 😄. Шутка. А вывод, собственно, такой — если разработчик имеет в своем арсенале некие домашние проекты, то он может обстреливать на них самые новые технологии, использовать самые смелые идеи, а также делать то, что в продакшене делать бы точно никогда не стал. Pet’ы позволяют существенно расширить кругозор, улучшить навыки, сменить стек, в конце концов, если ваш текущий вам надоел, а опыт на новом где-то набивать надо. Поэтому я однозначно советую всем писать код не только на работе, за деньги, но и дома — для себя! В итоге, новые навыки, знания и опыт только делают вас ценнее, а значит и дороже на рынке, а значит — домашние питомцы тоже приносят вам доход. Всем удачи!