Парсинг фото из VK по геолокации

GeoPhotos — агрегатор фотографий по городам, один из проектов нашей команды Revolt Lab, в которой маркетологи и дизайнеры проверяют различные гипотезы, а разработчики тестируют новые технологии. Это история win-win: если гипотеза выстрелит, получим интересный и прибыльный проект, если нет, то, как минимум, участники приобретут новые навыки и расширят текущие компетенции.

В данном проекте на разных стадиях были задействованы 5 человек:

  • Денис — идея и менторство,
  • Паша — код,
  • Артем — SEO,
  • Софья — дизайн,
  • Миша — помощь по разработке и частичное ревью кода.

Хочешь участвовать в разработке без долгих согласований, пробовать новые технологии или другие роли в команде? Есть идея, которую хотелось бы реализовать? В Revolt Lab такое приветствуется — вливайся в команду.

От идеи до реализации

Этот путь занял чуть более двух месяцев. Долго, но, так как это pet-проект, занимались им в свободные от основной работы часы. В копилку трудозатрат внес лепту и «синдром перфекционизма» — желание сделать сразу хорошо и больше — привычка, приобретенная за годы работы над клиентскими проектами.

Начнем с идеи. Слово Денису:

Иногда нужно найти фотографии в определенной геолокации, например, перед туристической поездкой. Инста помогает, но в ней нет просмотра фото на карте. В Яндекс Картах эта фича есть, но фотографии пользователи добавляют редко. Решили совместить это: в MVP без карты, но с актуальными фотографиями из ВКонтакте по популярным геоточкам.

Запросов в поисковиках достаточно, чтобы проект можно было в будущем монетизировать и развивать. Для MVP цель — 100 000 посетителей в месяц через год после запуска. Пробуем.

Если MVP «выстрелит», монетизировать планируем через партнерские программы. Хватает и планов по дальнейшему развитию проекта, повышению его полезности для пользователей.

Итак, что предметно было сделано за два месяца, — погнали.

Проверка возможностей API ВКонтакте

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

Парсинг фото из VK по геолокации
Запрос в API и что получаем.

Что узнали по итогу:

  1. VK без проблем дает получать фото (изображение). Параметры, которые можно указать в запросе, описаны в документации для разработчиков.
  2. Также достаются описание изображения и текст из поста с изображением, на основе которых можно отсекать ненужные фотографии.
  3. Для Python есть готовая библиотека по распознаванию лиц на изображении. Работает не очень быстро, примерно по одному FullHD фото в секунду, поэтому решили делать фронт не в realtime, а по заранее обработанной базе.

Комментарий Паши:

Основная проблема контентных проектов — это контент. В данном случае все звучало как приключение на 20 минут: вот есть VK API, оно умеет по координатам и ключевым словам возвращать фотографии, дело осталось за малым — взять центры городов, написать «Достопримечательность» и вот у тебя качественные и неподкупные фото в достаточном количестве. Ну, так-то оно так, только вместе с ними еще получались фотографии других городов, обнаженка, запрещенные символы и горы продаваемых товаров от детских вещей до, прошу прощения, самотыков.

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

Выбор стека

За разработку также целиком отвечал Паша. В прошлом разработчик, сейчас работает бизнес-технологом. Паша комментирует это так:

Несколько раз мы с нашим арт-директором Машей говорили о том, что есть смысл меня повкатывать в что-нибудь, например, во фронт, но я отнекивался — это не совпадало с моими жизненными интересами. А в этом году мне  внезапно стало интересно ML, и я начал потихоньку вкатываться в Python, плюсом к моим базовым знаниям React и баз данных. Full stack получился 😀

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

Это и предопределило стек проекта, он следующий:

Фронт

  • Flask,
  • Sass,
  • JQuery.

Бэк

  • Python,
  • MySQL.

Для реализации MVP достаточно инструментов, которые понимают остальные разработчики команды (или могут разобраться за вменяемое время), а также то, с чем мне не пришлось бы долго разбираться.

Я неплохо знал Python — он имеет в наличии большую базу библиотек и готовых решений — взяли его. Сайт по большому счету статичный, на 98% для фронта достаточно было любого шаблонизатора, потому взяли Flask как самое простое и доступное. База MySQL, но тут не принципиально. Остальное — Sass, JQuery — пришло по ходу проекта.

Как стало понятно потом, возможно, имело смысл сразу завести Vue в качестве фронта — некоторые вещи было бы сделать проще. Но и Flask пока вполне достаточно.

Паша, бизнес-технолог
Парсинг фото из VK по геолокации
Пашин код отличают ёмкие комментарии и использование одинарных кавычек.

Проектирование структуры

После оценки возможностей API взялись за структуру ресурса.

Начали по классике — с детального анализа конкурентов: ядра, структуры, интересных решений и способов монетизации. Проектов, продвигающихся по схожей семантике, много, но крупных всего 2–3. Причем некоторые сайты ограничили свою работу на территории РФ после 24 февраля, а это значит, что Яндекс их со временем выкинет из ТОПа выдачи (что в итоге и произошло).

Артем, маркетолог

После анализа решили для проверки гипотезы в MVP взять в работу кластеры формата «фото +город», «город +фото +летом», «город +фото +зимой» и подобные. По последним ниже частотность и, соответственно, слабее конкуренция. Это значит, что страницам под эти запросы легче выбраться в ТОП, что в свою очередь даст буст в ранжировании страниц с более частотными запросами за счет перераспределения веса от грамотной перелинковки.

Что сделали:

  1. Собрали и кластеризовали ядро запросов с ключевыми словами «город» + «фото», «фотографии» и т. п.
  2. По основе данных частотности отобрали список городов и их подкатегорий, под которые будем делать посадочные страницы.

Результат этого вылился в таблицу:

Частотность запросов по городам
Справа — ячейки со значениями общей частотности по кластеру за год, слева (ячейки с плюсами) — ответ: будем делать страницу или нет.

Далее Артем подготовил список требований по SEO, шаблоны для генерации мета-тегов, заголовков, URL, хлебных крошек и контента страниц. Затем взялся за структуру страниц.

Чтобы на этом шаге не загружать дизайнера, я быстро накидал прототипы со структурой страниц в Miro. Так и разработчик сможет примерно оценить свои трудозатраты, и дизайнер отчетливей понять мое видение.

Артем, маркетолог
Прототипы страниц проекта в Miro
Прототипы страниц в Miro: как видно на изображении, структура сайта достаточно простая.

Подключаем дизайн

Для наведения дальнейшей красоты пригласили Софью. Она подготовила макеты в Zeplin, частично переиспользовав компоненты из нашей внутренней дизайн-системы.

Парсинг фото из VK по геолокации
«Цеплин» используем и в заказных, и в собственных проектах.

Я подключилась к проекту, когда уже был готов черновой вариант интерфейса. Артём и Паша собрали сайт, а моей задачей была визуальная часть созданной ими структуры. 

С одной стороны, Артём здорово сэкономил моё время, когда набросал макеты страниц в Miro. С другой — у Паши возникли вопросы к адаптивности некоторых блоков, которая не была предусмотрена изначально, а когда проект дошёл до меня, что-то править и переделывать было долго или больно. Решили, что включать дизайнера в работу над проектом нужно как можно раньше.

С Пашей в качестве разработчика мы работали в первый раз. Обычно я работаю с ребятами, которые уже знают все принципы и нюансы, что я закладываю в макетах. Было немного волнительно перед стартом работ: вдруг возникнут недопонимания, не случится мэтча. В результате получилось быстро найти общий язык, и мои волнения не оправдались. А ещё Паша собирал некоторые кусочки интерфейса без моего участия, это крутой скил для разработчика, когда можешь сделать сам на основе имеющихся стилей.

Софья, UX/UI-дизайнер

Эволюция дизайна наглядно:

Парсинг фото из VK по геолокации
До.
Парсинг фото из VK по геолокации
После.

Релиз: итоги и первые проблемы

В бой проект вылили в середине августа 2022 года. Сразу отправили страницы на индексацию роботам Яндекса и Google, через IndexNow и Indexing API, соответственно. Прошлись краулерами Screaming Frog SEO Spider и SiteAnalyzer для проверки кодов ответа у страниц и поиска других возможных ошибок после деплоя.

На этом моменте активную часть работ по проекту приостановили, оставалось мониторить результаты индексации и ранжирования.

Личные итоги

От Артема:

По структуре и сеошке сайт достаточно простой, поэтому не скажу, что приобрел здесь какие-то новые навыки. Однако это был первый проект, который я в одиночку курировал от начала и до релиза, поэтому мне он был интересен и полезен именно в плане командной работы и менеджмента.

В своей голове всегда рисуешь идеальную картину, но в реальности далеко не все из этого возможно и нужно воплощать в жизнь. Надо уметь идти на компромиссы и слушать мнение коллег, чтобы в итоге найти какую-то золотую середину. Вроде, простые истины, но к этому тоже нужно прийти.

Еще один момент, который нужно контролировать, когда ты выступаешь в роли лида — перфекционизм vs трудозатраты. Для MVP, и особенно при проверке гипотез, стремиться к идеалу во всем — избыточно. Кажется, с этим пунктом мы немного прокололись. Опять же, если учитывать, что у Паши и у меня это частично был первый опыт на ведущих позициях в проекте, то желание сразу сделать конфетку оно в целом понятно.

От Паши:

Самыми важными двумя итогами для себя считаю:

1. Совершенно по-другому начал смотреть на взаимодействие с нашим дизайнером — работать как менеджер и как разработчик это совершенно две разных истории. Именно в роли разработчика удалось лучше понять, как вообще происходит работа по макетам, что считается важным, что нет, где какие компромиссы можно допустить и так далее. Ну то есть то, что не всегда возможно увидеть из высокого менеджерского кресла, но что важно для понимания ситуации в целом и лучшего управления как следствие.

2. Обновил свой опыт разработчика в команде — на какое-то время лучше буду понимать команду, что важно, потому что работая только как менеджер становишься все дальше и дальше от как все устроено на практике, потому теряется объективность.
Ну и конечно же, это множество практического опыта по Python, Flask, MySQL и верстке как бонус.

Очевидно результат не идеальный, но он приемлемый. Сложно было не только сделать, но и остановиться вовремя и сказать «Вот теперь нормально». Можно было сделать лучше — пойти в ML не только по пути определения лиц, но и людей, объектов и так далее, но это уже не MVP и железо там требуется дай бог каждому, так что пока так.

Не всё так гладко оказалось

Через две недели после релиза Яндекс начал выкидывать страницы из индекса по причине малополезного контента. К середине сентября были удалены все, кроме главной.

Индексация страниц сайта в Яндексе
Количество страниц в поиске Яндекса: быстрое добавление в индекс и потом такое же быстрое удаление.

При этом в Google ресурс чувствовал себя отлично и уже начал приносить первые клики.

Эффективность ресурса в поиске Google
Динамика на увеличение количества показов и кликов в поиске Google.

Конечно, в случае Яндекса можно было списать всё на сбои алгоритма, что ресурс еще новый и ему надо просто «отлежаться». Однако рисковать не хотелось.

Что предприняли для исправления ситуации, расскажем в следующих выпусках.