Сегодняшние социальные сети предоставляют практически неисчерпаемый источник информации. Эта информация может носить разный характер, но ни для кого не секрет, что основной частью этой самой информации являются данные о пользователях. Помимо злободневного вопроса анонимности (а точнее прозрачности) пользователя, коварных спецслужб и маркетологов, эти данные вполне могут быть использованы и в “мирных” целях.
Нам стало интересно, насколько с помощью социальных сетей можно оценить привлекательность городской среды, узнать какие места популярны, где горожане активны утром, а где вечером, куда ходят по выходным и что влияет на их поведение.
Для выяснения этого вопроса, мы запустили небольшой проект по анализу геометок (“ckeck-in”-ы), публикуемых в Москве. Данные собираются за последние 24 часа и отображаются в наглядной форме на карте в режиме реального времени. Кому интересно, что же у нас получилось из этой затеи — добро пожаловать под кат.
Почему именно ВК? Его выбор, конечно же, был неслучайным — на сегодня это самая популярная российская соцсеть, и столько данных, сколько там, нет больше нигде. ВКонтакте имеет порядка 36 млн. ежедневных посетителей, проживающих в России. Из них около 9 млн. приходится на столицу. А это значит, что по меньшей мере половина москвичей ежедневно посещают свою страничку. Лучшей площадки для анализа, пожалуй, найти невозможно.
Итак, проблем с поиском аудитории для анализа была решена. Оставалась лишь пара вопросов:
- А сможем ли мы с технической точки зрения собирать из ВКонтакте необходимые нам данные по гео-меткам? Иными словами, позволяет ли публичное API ВКонтакте “доставать” сведения по чекинам пользователей? Да не просто доставать, а доставать регулярно, в режиме реального времени и для ВСЕЙ Москвы.
- Насколько эти данные будут укладываться в идею нашего эксперимента?
Совместными усилиями с тех-поддержкой ВК, на первый вопрос удалось получить утвердительный ответ (бинго! но об этом чуть ниже). А что на счет второго? Не будет ли наша карта целиком состоять из малоинтересных данных, собранных с домашних или рабочих стационарных ПК? Снова обратимся к статистике: по данным LiveInternet, по меньшей мере 20-25% посещений приходится на Android и iOS, а Opera Mini, хоть и теряет свои позиции, но все еще удерживает место 4-ого по популярности браузера. Мобильный бум не обошел стороной и аудиторию ВКонакте и все более значительная часть ее посетителей приходится на портативные гаджеты. Стоит учесть и то, что “чекины” обычно все-таки делаются не в гостиной и на кухне, а в различных публичных местах, во время досуга. А значит, что сведения, которые мы получаем, вполне позволяют судить об общегородской тенденции активности.
Реализация
А теперь перейдем к самому интересному — к технической части! Нельзя сказать, что были использованы какие-то революционные технологии, но, возможно, некоторые из представленных ниже приемов будут любопытны хабра-общественности.
Непродолжительный анализ документации к API ВК позволил обнаружить метод places.getCheckins, который возвращает все посты с геометками поблизости от исходной точки поиска. Здорово? Конечно! Но количество запросов к API ограничивается 5-ью в секунду, а это не наш масштаб, в какой-то момент мы обязательно упремся в этот лимит. На помощь пришел метод execute (спасибо техподдержке ВК за оперативный совет), который позволил уместить 20 обращений в одно единственное; главное — уложиться в ограниченное время выполнения вложенных в execute подзапросов. Еще одним бонусом этого подхода стала и возможность перенести часть обработки информации на сервера ВК.
Итак, теперь все было готово для непосредственного обращения за необходимыми данными в ВК. Казалось бы, дело за малым — нам нужно передать координаты центра столицы методу places.getCheckins и вуаля! Но не тут то было. При таком подходе объекты, возвращаемые API, кучковались в правом верхнем углу, а вот левая часть города пустовала. Пришлось прибегнуть к небольшой хитрости: мы разбили карту Москвы на участки (картинка ниже), и начали опрашивать несколько областей меньшего размера вместо одной большой:
Теперь дела пошли куда лучше, но API не всегда возвращал необходимые нам координаты. Насколько удалось выяснить, это происходило в том случае, если ВК не смог распознать место по своей базе. Здесь единственным способом вытащить широту и долготу стало прямое обращение за ними на стену пользователя, используя метод wall.getById. Учитывая, что places.getCheckins передает 'wall_id' в поле 'id', провернуть такую операцию не составило труда.
Для беспрерывного сбора данных был написан небольшой демон, регулярно выполняющий обращение за новой партией гео-меток путем постоянного вызова метода execute со следующим содержимым:
var COUNT_CHEKING = 18;
var LAST_TIME = %time_replace%;
var max_time = 0;
var cordinatesPonint = [
[55.91843, 37.379394],
[55.908424, 37.541442],
[55.895336, 37.682891],
[55.822116, 37.821593],
[55.742574, 37.839446],
[55.658996, 37.836699],
[55.579897, 37.687011],
[55.583002, 37.551055],
[55.646599, 37.387633],
[55.72943, 37.38214],
[55.829059, 37.399993],
[55.827516, 37.541442],
[55.816715, 37.680144],
[55.730977, 37.680144],
[55.66132, 37.677398],
[55.66132, 37.537322],
[55.740255, 37.535949],
[55.754071, 37.617504],
[55.989164, 37.184386],
[55.519302, 37.520843],
];
var placesMoscow = [];
var iCordinatesPonint = 0;
while(iCordinatesPonint < cordinatesPonint.length) {
placesMoscow = placesMoscow + [API.places.getCheckins({
"latitude":cordinatesPonint[iCordinatesPonint][0],
"longitude":cordinatesPonint[iCordinatesPonint][1],
"count":COUNT_CHEKING,
"timestamp": LAST_TIME
})];
iCordinatesPonint = iCordinatesPonint + 1;
}
var walls;
var iMoscow = 0;
var returnObj = [];
var wallsIds = [];
var returnObj2 = [];
var i;
while(iMoscow < placesMoscow.length) {
var getWallId = placesMoscow[iMoscow]@.latitude;
var i = 1;
while(i < getWallId.length) {
if(getWallId[i] == 0) {
wallsIds = wallsIds + [placesMoscow[iMoscow][i].id];
} else {
if(max_time < placesMoscow[iMoscow][i].date) {
max_time = placesMoscow[iMoscow][i].date;
}
returnObj = returnObj + [{
"lat": placesMoscow[iMoscow][i].latitude,
"lng": placesMoscow[iMoscow][i].longitude,
"id": placesMoscow[iMoscow][i].id,
"time": placesMoscow[iMoscow][i].date
}];
}
i = i + 1;
}
iMoscow = iMoscow + 1;
}
if(wallsIds.length > 0) {
walls = API.wall.getById({"posts": wallsIds});
i = 0;
while(i < walls.length) {
if(max_time < walls[i].date) {
max_time = walls[i].date;
}
returnObj2 = returnObj2 + [{
"coordinates": walls[i].geo.coordinates,
"time": walls[i].date,
"id": wallsIds[i]
}];
i = i + 1;
}
}
var moscow = {
"checkins": returnObj,
"wals": returnObj2
};
return {
"max_time" : max_time,
"spb": {
"checkins": [],
"wals": []
},
"moscow" : moscow};
Демон (написан на Python) производит опрос сервера ВК примерно раз в 3 секунды. Благодаря параметру 'timestamp' можно легко получать только новые данные, не заботясь о фильтрации старых.
Результат, который был получен от ВК, разбирается — координаты и время записываются в бинарный файл и в MongoDB. Первоначально планировалось использовать Mongo для создания кластеров, но позже от этой идеи решено было отказаться, так что теперь бинарный файл осуществляет своего рода бэкап данных.
Как только демон обрабатывает новый чекин, по протоколу http на localhost хост посылаются координаты точек второму демону, который держит websoket соединения. После получения вторым демоном координат он незамедлительно отправляет их пользователю в браузер (и да, браузер у нас открывает websocket и ждет ответа).
Ну а чтобы придать всему этому немножко динамики, мы решили прикрутить красивую анимацию к каждой появляющейся на карте гео-метке:
В качестве картографический основы использовались стандартные Google Maps с небольшой кастомизацией: инверсия цвета + корректировка гаммы и яркости для создания оптимального контраста с метками.
Клиентская часть написана на PHP, который забирает данные из MongoDB за последние 24 часа.
Старт дан
Итак, все приготовления были закончены и мы благополучно запустились на отдельной машине. Вопрос, который откладывался до последнего, стал актуален как никогда: а как много чекинов совершается за день в Москве? Достаточно ли их для того, чтобы заполнить карту? К счастью, все опасения на этот счет были довольно быстро развеяны — за первые же сутки наш сервер вытянул и обработал порядка 10.000 публикаций с гео-метками! День #2 только подтвердил, что эта цифра не была ошибкой или случайным всплеском активности.
Первые результаты
Из интересных наблюдений: оказывается, креативный кластер на месте бывшей фабрики “Красного Октября” действительно стал важным культурным центром Москвы и сегодня не менее популярен, чем Красная площадь.
Самая любимая улица москвичей — это Арбат, а открытая столичными властями в 2012 пешеходная зона от Столешникова переулка и до Кузнецкого Моста буквально за год стала одной из самых востребованных в столице!
Такие исследования городского пространства можно проводить для любого места или события в городе. Так, на этих выходных мы совместно с фестивалем “Лучший город Зимы” мониторили активность во время запуска световых инсталляций. Было жутко захватывающе наблюдать как каждые 10-30 секунд вспыхивала новая метка. Инсталляции явно не оставили равнодушными никого.
Пощупать все это дело вживую можно тут — whatsupmoscow.ru
Весь исходный код проекта доступен на GitHub
Автор: fraggjkee