Разное

Визуализация друзей вконтакте: Скажи мне, кто твой друг? / Хабр

26.06.2020

Содержание

Скажи мне, кто твой друг? / Хабр

Привет, Хабралюди!

У меня есть хобби. Я ночами (в нерабочее время) пишу библиотеку укладки графов: vivagraph.js. Хотел поделиться с вами, узнать что думаете. Визуализировал я сеть друзей своих на «В Контакте» с использованием WebGL. Но лучше один раз увидеть, чем читать, верно?

Это мои друзья. Каждая точка — человек, целый мир, с которым так или иначе мне повезло встретиться. Линия между точками обозначает дружбу. По этой сети можно, правда, сказать многое о человеке.

Как построить сеть своих друзей?

1. Проверьте что браузер поддерживает WebGL: get.webgl.org — должен быть кубик. Если кубика нет — попробуйте другой браузер. Часто хром/лис блокируют видеокарты с устаревшими драйверами. Увы, кубик — это ключ к успешной визуализации :).

2. Зайти на www.yasiv.com/vk — это визуализация ваших друзей на ВК.

3. (опционально) — поделиться своей картой с друзьями, рассказать о сайте. Я буду очень рад, т.к. в маркетинге, увы, ни бум бум (кто там?).

Почему синие квадраты вместо аватарок?

У WebGL есть очень строгие ограничения на картинки, используемые в текстурах. Если они приходят из другого домена, сервер с картинками должен разрешить их кросс-доменное использование. Исправляется добавлением в заголовок ответа с картинкой Access-Control-Allow-Origin:*
, но увы, ВКонтакте этого пока не поддерживает. Если вы, читатель, являетесь сотрудником ВКонтакте, и имеете доступ к коду — добавьте, пожалуйста хедер. Я вам спасибо огромное скажу, и визуализацию подправлю :).
Почему WebGL?

Ни CSS, ни SVG, ни даже простой canvas 2D не сравнятся с производительностью WebGL. vivagraph.js поддерживает SVG и CSS, но в обоих случаях основным тормозом визуализации является браузерный код отрисовки элементов. Лишь с использованием WebGL ботлнек перемещается в мой алгоритм укладки :).
Маленький Мир

Помните историю о шести рукопожатиях? Недавний анализ полной сети Фейсбука вывел число 4.7. Я забавы ради начал достраивать сеть от мало знакомого мне друга в неизвестность и такая картина наблюдалась очень часто:
Что скажете?

Мне очень-очень важны ваши отзывы и предложения. Это всего лишь мое хобби, но я очень люблю его. Понимаю, что все еще сыровато, и на огромных графах (больше 2000 узлов) все работает слишком медленно. Но вместо того, чтобы пытаться сделать все правильно с первого раза, я хотел бы спросить у вас, что бы вы посоветовали сделать лучше? Ну и буду очень рад, если присоединитесь к проекту и поможете сделать его еще лучше :).

stleon/vk_friends: Граф дружеских связей в vk.com. common friends

Граф дружеских связей в vk.com. Больше инфы можно прочитать здесь и здесь. Если вам нужен старый релиз, то он тут. Перед тем, как что-то делать, рекомендую прочесть всю документацию.

##Что нужно

##Первые шаги

Для начала необходимо создать Standalone-приложение в VK. Делается это там. В итоге попросят ввести код-подтверждения, высланный на мобильный, после чего мы попадаем на страницу управления приложением. На вкладке Настройки нам пригодится ID приложения для получения access_token.

Чтобы его получить необходимо сформировать url:

https://oauth.vk.com/authorize?client_id=IDприложения&scope=friends,offline&redirect_uri=https://oauth.vk.com/blank.html&display=page&v=5.21&response_type=token

Если адрес сформирован правильно, переходим по нему и получаем нечто вроде:

https://oauth.vk.com/blank.html#access_token=ACCESS_TOKEN&expires_in=0&user_id=USER_ID

После этого редактируем файл settings.py, вставляя туда полученные access_token и user_id.

Далее переходим по ссылке https://vk.com/editapp?id=IDприложения&section=functions и создаем хранимую процедуру getMutual.

Копируем содержимое execute_getMutual.js в форму и сохраняем.

Для получения глубинного списка друзей (друзья-друзей и т.д.) проделываем те же самые действия с execute_deepFriends.js, назвав хранимую процедуру deepFriends.

Ура!

##RabbitMQ & Celery

После их установки необходимо создать virtual host для RabbitMQ:

rabbitmqctl add_vhost vk_friends
rabbitmqctl add_user user password
rabbitmqctl set_permissions -p vk_friends user ".*" ".*" ".*"

Далее в конфигурационном файле RabbitMQ (у меня это /usr/local/etc/rabbitmq/rabbitmq-env.conf) указать ip, на котором он установлен:

NODE_IP_ADDRESS=192.168.1.14 // example

В settings.py заполнить:

broker/backend — словари, содержащие информацию для доступа к брокеру и бэкенду

в соответствии с данными, введенными выше.

##Что дальше

Запускаем RabbitMQ:

rabbitmq-server

Затем воркера (из папки проекта):

celery -A tasks worker --loglevel=info

Воркеров может быть несколько.

Если вы все настроили правильно и нет никаких сообщений об ошибках, то:

python call.py

1 — Общие друзья, 2 — Друзья-друзей и тд, в зависимости от глубины (deep — в settings.py).

После первого запуска результат сохраняется в файлах _dct. Теперь можно рисовать/анализировать графы. По-умолчанию, graph.py работает с «глубинными друзьями». После запуска

python graph.py

вы увидите некоторую информацию о графе, а в папке проекта появится файл .png. Для болиших графов рекомендую закомментировать строчку

deep_friends.draw_graph()

##Полезности В settings. py можете вбить id любого интересующего вас человека.

Создать веб сайт (Визуализация друзей в ВК) | API | JavaScript | PHP

Фабула:

Имеется проект ([url removed, login to view]) — не реклама, который производит визуализацию друзей в ВК.

Задача: Необходимо сделать аналогичный сайт, только, чтобы отображался аватар пользователей, имя и фамилия. А также, чтобы пользователи соединялись не только если есть общие друзья, но и если они состоят в одних группах(пабликах)

Skills: API, JavaScript, PHP

See more: 1с фриланс украина, 2d иллюстратор фриланс, 2d фриланс, anvaka amazon, amazon products visualization, amazon visualizer, amazon visualization, yasiv com graph, andrei kashcha, вконтакте, yasiv relative books, php, html, website design, wordpress, 3d аниматор фриланс, 3d визуализатор фрилансер, 3d графика фриланс, 3d дизайн интерьера фриланс, 3d дизайнер фрилансер

( 0 reviews ) Russian Federation

Project ID: #15125941

Что показывает социальный граф в ВКонтакте? H Анализ дружеских связей VK с помощью Python Из песочницы

Социальный граф VK June 22nd, 2012

Не так давно во всем известной российской соцсети появилось приложение, которое позволяет построить граф связей собственных друзей. Глобальной пользы в этом нет, но для личного исследования — довольно интересная штука. Процедура проста: устанавливаешь приложение — запускаешь — ждёшь — смотришь результат. После 10-15 минут приложение закончило обработку информации и я получил такой занятный граф:

Чтобы понять, какие области к чему относятся, я выделил основные из них:

Центральный и наиболее многочисленный кластер — это факультет математики Волгоградского Гос Университета, что логично, родной факультет ведь. Справа от него отдельно выделяется физический факультет, что обусловлено двумя причинами:

  • Часть моего первого факультета информационных технологий вошла в состав физфака (другая, соответственно, в состав матфака), и большинство связей — оттуда;
  • У нас с физфаком был общий отдельный учебный корпус.

Чуть ниже выделил группу Бизнес-Информатики в ВолГУ — свою родную группу. Интересный факт, что большинство одногруппников почти не заводили знакомств на новом факультете, так и оставшись в стороне.

Ещё ниже находится кластер, включающий в себя тех людей, с которыми я учился на переводчика на факультете лингвистики.

Слева от матфака находится кластер волгоградских ЧГКшников. На самом деле, границы кластеров здесь заданы очень грубо, и красный прямоугольник ЧГК должен захватывать и часть матфака. С ЧГКшниками пересекается кластер со всеми остальными студентами ВолГУ, преимущественно с теми, с кем я познакомился на ЧГК, будучи редактором и в разных университетских поездках.

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

Второй по размеру кластер после ВолГУ — это НИУ ВШЭ, в основном факультет Бизнес-Информатики, выделен жёлтым цветом. От него идёт два ответвления, которые я не выделял — это связи на работе (такое малое количество обусловлено тем, что большинство там не пользуется VK, предпочитая вместо него FB и LinkedIn). Два ответвления — это два отдела, в одном я работал раньше, в другом работаю сейчас. Как видно, в каждом из них есть один или два человека, так или иначе связанные с Вышкой.

Последний кластер — это ЧГКшники из Москвы и Ярославля. Изначально я думал, что кластер будет связан с Высшей Школой Экономики, ибо оттуда и пошли все знакомства. Но, как оказалось, московские чгкшники знают гораздо больше знатоков из Волгограда, нежели студенитов факультета БИ (что, наверное, логично).

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

В целом, факультет математики ВолГУ (включая Бизнес-Информатику) и Вышка составляют по 1/3 всех связей соответственно. Последняя треть связей приходится на оставшиеся 6 кластеров и пользователей, которых я не включил в какую-то выборку.

Конечно, это не все, кого я знаю, а только те, кто есть в VK и кто есть у меня в «друзьях». Так что выборка не совсем точная, но очень-очень приблизительная.

Если вам интересно, можете сами создать себе такую.

Совсем недавно на Хабре появилась о реализации дружеских связей в ВКонтакте с помощью Wolfram Mathematica. Идея мне понравилась, и, естественно, захотелось сделать такой же граф, используя Python и . Вот, что из этого получилось.

Внимание! В статье будут присутствовать части кода, описывая самые важные действия, но следует учесть, что проект претерпит еще не одно изменение в своей кодовой базе. Заинтересовавшиеся могут найти исходники на GitHub .

Разобьем задачу по элементам:

  • Создание и авторизация приложения.
  • Получение данных.
  • Визуализация графа.
Что для этого нам понадобится:
  • Python 3.4
  • Mozilla FireFox, так как в Chrome нельзя использовать XMLHttpRequest для загрузки локальных файлов (никто не мешает сделать python -m http.server 8000 )
Создание и авторизация приложения
Чтобы получить доступ к API ВКонтакте, нам необходимо создать Standalone-приложение , после чего мы сможем использовать нужные нам методы API, которые будут описаны далее. Приложение создается — выберем Standalone-приложение . Нас попросят ввести код-подтверждения, высланный на мобильный, после чего мы попадем на страницу управления приложением. На вкладке Настройки нам пригодится ID приложения для получения access_token .
Далее нам надо авторизовать наше приложение. Этот процесс состоит из 3х этапов.
Аутентификации пользователя на сайте ВКонтакте
Для этого сформируем url, как показано ниже:

Https://oauth.vk.com/authorize?client_id=IDприложения&scope=friends,offline&redirect_uri=https://oauth.vk.com/blank.html&display=page&v=5.21&response_type=token
Цитируя vk.com/dev/auth_mobile :

APP_ID – идентификатор Вашего приложения;
PERMISSIONS – запрашиваемые права доступа приложения;
DISPLAY – внешний вид окна авторизации, поддерживаются: page, popup и mobile.
REDIRECT_URI – адрес, на который будет передан access_token.
API_VERSION – версия API, которую Вы используете.

В нашем случае PERMISSIONS — это доступ к друзьям и к API в любое время со стороннего сервера (бессрочный токен). Если адрес сформирован правильно, нам предложат ввести логин и пароль.
Разрешение доступа к своим данным
Далее разрешаем приложению доступ к необходимой информации:

Получение access_token
После авторизации приложения клиент будет перенаправлен на REDIRECT_URI. Нужная нам информация будет заключена в ссылке.

Https://oauth.vk.com/blank.html#access_token=ACCESS_TOKEN&expires_in=0&user_id=USER_ID
Редактируем файл settings.py , вставляя туда полученные access_token и user_id . Теперь мы можем осуществлять запросы к API ВКонтакте.

Получение данных
Для начала разберем методы, которые будем использовать для данной цели.

Поскольку нужна хоть какая-то информация об id пользователя, по которому будет строиться граф, нам пригодиться users.get . Он принимает как один id, так и несколько, список полей, информация из которых нам необходима, а также падеж, в котором будет склоняться фамилия и имя. Мой метод base_info() получает список id и возвращает информацию о пользователе с фотографией.

Def base_info(self, ids): «»»read https://vk.com/dev/users.get»»» r = requests.get(self.request_url(«users.get», «user_ids=%s&fields=photo» % («,».join(map(str, ids))))).json() if «error» in r.keys(): raise VkException(«Error message: %s. Error code: %s» % (r[«error»][«error_msg»], r[«error»][«error_code»])) r = r[«response»] # Проверяем, если id из settings.py не деактивирован if «deactivated» in r.keys(): raise VkException(«User deactivated») return r
Это может быть важно для тех, кто захочет отправлять в него id из friends.getMutual , таким образом произведя на свет огромное число запросов. Об этом позже.
Теперь нам надо получить информацию о друзьях пользователя, в чем нам и поможет метод friends.get . Из всех его параметров, перечисленных в документации, используем user_id , который находится в нашем setting.py и fields . Дополнительными полями будут id друзей, их имена, фамилии и фотографии. Ведь хочется, чтобы в узлах были миниатюры их фотографий.

Def friends(self, id): «»» read https://vk.com/dev/friends.get Принимает идентификатор пользователя «»» r = requests.get(self.request_url(«friends.get», «user_id=%s&fields=uid,first_name,last_name,photo» % id)).json()[«response»] #self.count_friends = r[«count»] return {item[«id»]: item for item in r[«items»]}
Далее наступает самое интересное.
Список id общих друзей между двумя пользователями возвращает метод friends.getMutual . Это хорошо, потому что мы получаем только id, а более расширенная информация у нас уже есть, благодаря friends.get . Но никто не запрещает сделать вам лишнюю сотню-другую запросов, используя users.get . Схемы расположены чуть-чуть пониже.
Теперь определимся, как будем использовать friends.getMutual . Если у пользователя N-друзей, то надо сделать N-запросов, чтобы по каждому другу мы получили список общих друзей. К тому же нам надо будет делать задержки, чтобы у нас было допустимое количество запросов в секунду.
Предположим, что у сканируемого нами id есть 25 друзей.

Всего 52 запроса — это слишком многовато, поэтому вспомним, что users.get может принимать список id:

25 друзей — 28 запросов, но как писалось выше, информация у нас уже имеется, благодаря friends.get .


И тут нам пригодится execute , который позволит запустить последовательность методов. У него есть единственный параметр code , он может содержать до 25 обращений к методам API.
То есть в итоге код в VKScript будет примерно таким:

Return { “id»: API.friends.getMutual({«source_uid»:source, «target_uid»:target}), // * 25 … };
Найдитесь те, кто напишет, как сократить данный код, не используя все время API.friends.getMutual .
Теперь нам надо всего лишь отправлять партиями id друзей по 25 в каждой. На нашем примере схема будет выглядеть так:


А ведь мы могли с помощью for отправлять каждого друга в friends. getMutual , а потом еще узнавать более детальную информацию через users.get .
Далее составим человеко понятную структуру, где уже вместо id друга и списка id ваших общих друзей, будет информация из friends.get . В итоге получим нечто вроде:

[({Ваш друг}, [{общий друг}, {еще один общий друг}]),({Ваша подруга}, None)]
В словарях находится id, имя, фамилия, фото, в списках — словари общих друзей, если общих друзей нет, то None. Кортежами все это разделяется.

Def common_friends(self): «»» read https://vk.com/dev/friends.getMutual and read https://vk.com/dev/execute Возвращает в словаре кортежи с инфой о цели и списком общих друзей с инфой «»» def parts(lst, n=25): «»» разбиваем список на части — по 25 в каждой «»» return for i in iter(range(0, len(lst), n))] result = for i in parts(list(self.all_friends.keys())): # Формируем code (параметр execute) code = «return {» for id in i: code = «%s%s» % (code, «»%s»: API.friends.getMutual({«source_uid»:%s, «target_uid»:%s}),» % (id, self. my_id, id)) code = «%s%s» % (code, «};») for key, val in requests.get(self.request_url(«execute», «code=%s» % code)).json()[«response»].items(): if int(key) in list(self.all_friends.keys()): # берем инфу из уже полного списка result.append((self.all_friends, for i in val] if val else None)) return result
Итак, если хочется посмотреть свой список друзей и общих с ними друзей, запускаем:

Python main.py

Визуализация графа
Выбор пал на , а именно на Curved Links . Для этого надо сгенерировать json , который будет примерно такого содержания:

{ «nodes»: [ {«name»:»Myriel»,»group»:1, «photo»: «path»}, {«name»:»Napoleon»,»group»:1, «photo»: «path»}, {«name»:»Mlle.Baptistine»,»group»:1, «photo»: «path»} ], «links»:[ {«source»:1,»target»:0,»value»:1}, {«source»:2,»target»:0,»value»:8} ] }
Немного видоизменяя index.html , узлами становятся фотографии друзей.

Если хочется сразу визуализировать граф:

Python 2d3.py
В папке web появится файл miserables. json . Не забываем открывать index.html в Mozilla FireFox или используем python -m http.server 8000 и открываем в Chrome.

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

Так выглядит граф дружеских связей одного из моих друзей. Связи — это все.


Конечно, мне было интересно, у кого работает быстрее.

В , которая меня вдохновила, написано:

На моих 333 друзьях это заняло 119 секунд.


На момент написания этой статьи, у Himura в ВКонтакте был 321 друг. У меня это заняло 9 секунд (работа всей программы, а не одного friends.getMutual ).
В заключение
Всю необходимую информацию об использованных методах можно найти в щедро написанной документации ВКонтакте, однако мной была обнаружена пара ошибок: не была описана ошибка с кодом 15 («error_msg»: «Access denied: user deactivated», «error_code»: 15 ), догадаться можно, что она значит, и uid вместо user_id в документации к методу friends. get. Спустя 2 дня:
Как говорилось вначале, проект можно найти на GitHub , буду рад, если он понравится ещё кому-то и я получу много вкусных пулл реквестов…

UPD (27.05.2014):
Как мне WTFRU7 , я добавил возможность использования хранимых процедур. Для этого нужно перейти по

Привет, Хабралюди!

Это мои друзья. Каждая точка — человек, целый мир, с которым так или иначе мне повезло встретиться. Линия между точками обозначает дружбу. По этой сети можно, правда, сказать многое о человеке.

Как построить сеть своих друзей?
1. Проверьте что браузер поддерживает WebGL: get.webgl.org — должен быть кубик. Если кубика нет — попробуйте другой браузер. Часто хром/лис блокируют видеокарты с устаревшими драйверами. Увы, кубик — это ключ к успешной визуализации:).

2. Зайти на www.yasiv.com/vk — это визуализация ваших друзей на ВК.

Почему синие квадраты вместо аватарок?
У WebGL есть очень строгие ограничения на картинки, используемые в текстурах. Если они приходят из другого домена, сервер с картинками должен разрешить их кросс-доменное использование. Исправляется добавлением в заголовок ответа с картинкой Access-Control-Allow-Origin:* , но увы, ВКонтакте этого пока не поддерживает. Если вы, читатель, являетесь сотрудником ВКонтакте, и имеете доступ к коду — добавьте, пожалуйста хедер. Я вам спасибо огромное скажу, и визуализацию подправлю:).
Почему WebGL?
Ни CSS, ни SVG, ни даже простой canvas 2D не сравнятся с производительностью WebGL. vivagraph.js поддерживает SVG и CSS, но в обоих случаях основным тормозом визуализации является браузерный код отрисовки элементов. Лишь с использованием WebGL ботлнек перемещается в мой алгоритм укладки:).
Маленький Мир
Помните историю о шести рукопожатиях ? Недавний анализ полной сети Фейсбука вывел число 4.7. Я забавы ради начал достраивать сеть от мало знакомого мне друга в неизвестность и такая картина наблюдалась очень часто:
Что скажете?
Мне очень-очень важны ваши отзывы и предложения. Это всего лишь мое хобби, но я очень люблю его. Понимаю, что все еще сыровато, и на огромных графах (больше 2000 узлов) все работает слишком медленно. Но вместо того, чтобы пытаться сделать все правильно с первого раза, я хотел бы спросить у вас, что бы вы посоветовали сделать лучше? Ну и буду очень рад, если присоединитесь к

API Вконтакте + NetworkX = социальный граф!

Попалась мне тут когда-то интересная задача — быстро и максимально просто (с минимумом привлекаемых библиотек) нарисовать граф пересечения пользователей разных групп Вконтакте. И я ее даже сделал. Затем подумал — а вдруг кому-то еще нужно будет сделать что-то подобное?

Поэтому здесь я расскажу и покажу, как же всё-таки делать такие вещи:

1. Подключаться к веб-сайту вконтакте с помощью Python 2.7 (всегда можно переписать под 3.x, если что)

2. Создавать графы с помощью библиотеки NetworkX (здесь рассматриваем графы пересечений аудитории групп вконтакте)

3. Визуализировать эти графы (тут нам немного понадобится библиотека matplotlib)

Итак, дано:

Задание: нарисовать граф пересечений пользователей разных групп Вконтакте

Базовые инструменты: Python 2. 7, NetworkX, matplotlib, numpy

Поехали!

 

Подключаемся к API

Если хорошо поискать в безбрежной сети, то можно найти полезные ресурсы, которые сильно облегчают подключение к АPI вконтакте.

Для начала нужно скачать специальную библиотеку-обертку — vk.com (aka vkontakte.ru) API wrapper. 

Затем очень желательно скачать модуль для упрощения авторизации вконтакте вот тут (за этот скрипт большое спасибо хорошему человеку alexkutsan). Модуль мы будем звать vk_auth и всячески импортировать в дальнейшем, поэтому сохраняйте его в той же директории, где будут лежать основные скрипты. В случае, если ссылка нерабочая, то можно взять vk_auth у меня — напишите в комментариях или отправьте запрос мне на почту.

Итак, у нас есть все, чтобы просто и быстро подключиться к API вконтакте.  Проверим, что все сделали как надо, и контакт теперь пускает нас в свои недра.

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import vk_auth
import vkontakte
 
def test():
    #параметры для vk_auth. auth - ваш логин вконтакте, ваш пароль вконтакте, id приложения, 
    #и зона доступа, она же scope
    (token,user_id) = vk_auth.auth('your_login', 'your_password', '2951857', 'groups')
    vk = vkontakte.API(token=token)
    print "vk server time is ", vk.getServerTime()
    return 0
 

В этом скрипте нужно указать свой логин и пароль вконтакте (можете не беспокоиться — эта информация никуда не утечёт, можете проверить по коду скрипта vk_auth), в качестве id приложения нужно указать идентификационный номер своего приложения, которое предварительно нужно создать вконтакте вот таким, например, способом.

Если на видео не очень понятно, то на страничке vk.com/developers.php есть запрятанная кнопка «создать приложение» в верхнем правом углу. Сразу в глаза она не бросается — располагается чуть ниже кнопок меню «музыка» и «помощь». Там можно создать приложение и использовать его client_id в качестве id приложения.

Но! Можно использовать и чужой id. Я, например, использовал вот этот — 2951857, который был опубликован вот в этой статье на хабрахабре. Если вдруг у автора будут претензии по использованию этого идентификатора, я готов его отсюда убрать.

Далее нужно указать так называемый scope — зону доступа для нашего парсера. Так как далее мы собираемся парсить группы, то стоит указать ‘group’. Подробнее о том, что можно указать в качестве scope — можно почитать здесь

Все остальное можно оставить как есть. Если все правильно, то выполнив код, показанный выше, мы получим серверное время вконтакте.

Парсим группы

Отлично! Все получилось (по крайней мере должно было).

А теперь попытаемся достать необходимые данные по группам вконтакте — количество участников для каждой группы и список этих самых участников в виде списка ID.

Важно знать, что API вконтакте выдает максимум 1000 пользователей группы – больше от него не допросишься. Впрочем, для проведения приблизительного анализа групп — сойдёт. Если надо больше — придётся парсить страницы групп напрямую.

Функция, которая ниже, берет на вход список имен групп вконтакте, а на выходе отдает нужные нам данные по этим группам.

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import vk_auth
import vkontakte
import time
 
def get_groups_users(groups_list):
    groups_out = {}
    (token,user_id) = vk_auth.auth('your_login', 'your_password', '2951857', 'groups')
    vk = vkontakte.API(token=token)
    for group in groups_list:
        #здесь му указываем count=10, который выдаст нам 10 пользователей из группы
        #это делается для наглядности. Максимум можно вытащить 1000 пользователей
        groups_out[group] = vk.get('groups.getMembers', group_id=group, sort='id_asc', offset=100, count=10)
        time.sleep(1)
    return groups_out
    
if __name__ == '__main__':
    group_list = ['oldlentach', 'obrazovach', 'superdiscoteka']
    print get_groups_users(group_list)
    >>> {'oldlentach': {u'count': 740868, u'users': [1405, 1418, 1443, 1444, 1447, 1481, 1491, 1494, 1500, 1509]}, 
    'obrazovach': {u'count': 217978, u'users': [3172, 3192, 3196, 3213, 3317, 3328, 3331, 3356, 3361, 3420]}, 
    'superdiscoteka': {u'count': 150538, u'users': [20470, 20479, 20536, 21977, 22426, 22522, 22613, 22881, 23207, 23401]}}
    

Структура выходных данных такова: ключ — это имя группы, значение — это словарь с двумя ключами: u’count’ — количество участников в группе и u’users’ — список ID участников этой группы (максимум 1000, как мы помним)

В качестве имени группы берется ее адрес вконтакте, например, есть группа Образовач, которая находится по адресу http://vk. com/obrazovach и мы берем последнюю часть адреса, т.е. «obrazovach» в качестве имени группы.

Строим социальный граф

Теперь переходим непосредственно к построению социального графа.

Здесь мы будем применять библиотеку NetworkX, которая прекраснейшим образом подходит для составления, анализа и визуализации графов.

Вот таким вот образом можно создать граф для групп вконтакте:

  1. На вход подается словарь, где ключом является название группы вконтакте, а значением — количество участников этой группы и список из максимум 1000 ID участников группы (каждый ID — это ID пользователя вконтакте)
  2. Создаём вершину в графе для каждой группы, в качестве атрибута присваиваем каждой вершине вес, равный количеству участников в группе
  3. Затем для каждой пары вершин, если между ними есть пересечение по ID участников, создается ребро, и в качестве атрибута присваиваем каждому ребру вес, равный количеству пользователей, которые присутствуют в обеих группах.

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

Вот эта функция как раз и строит описанный выше граф:

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import networkx as nx

def make_graph(groups_out):
    graph = nx.Graph()
    groups_out = groups_out.items()
    for i_group in xrange(len(groups_out)):
        graph.add_node(groups_out[i_group][0], size=groups_out[i_group][1]['count'])
        for k_group in xrange(i_group+2, len(groups_out)):
            intersection = set(groups_out[i_group][1]['users']).intersection(set(groups_out[k_group][1]['users']))
            if len(intersection) > 0:
                graph.add_edge(groups_out[i_group][0], groups_out[k_group][0], weight=len(intersection))
    return graph
    

Визуализируем

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

Вот таким образом можно визуализировать созданный нами граф:

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
import networkx as nx
import matplotlib.pyplot as plt
import numpy

def plot_graph(graph, adjust_nodesize):
    pos=nx.spring_layout(graph, k=1)
    #нормализуем размер вершины для визуализации. Оптимальное значение параметра
    #adjust_nodesize - от 300 до 500
    nodesize = [graph.node[i]['size']/adjust_nodesize for i in graph.nodes()]
    #нормализуем толщину ребра графа. Здесь хорошо подходит 
    #нормализация по Standard Score
    edge_mean = numpy.mean([graph.edge[i[0]][i[1]]['weight'] for i in graph.edges()])
    edge_std_dev = numpy.std([graph. edge[i[0]][i[1]]['weight'] for i in graph.edges()])
    edgewidth = [((graph.edge[i[0]][i[1]]['weight'] - edge_mean)/edge_std_dev) for i in graph.edges()]
    #создаем граф для визуализации
    nx.draw_networkx_nodes(graph, pos,node_size=nodesize, node_color='y', alpha=0.6)
    nx.draw_networkx_edges(graph,pos,width=edgewidth,edge_color='b')
    nx.draw_networkx_labels(graph,pos,fontsize=10)
    #сохраняем и показываем визуализированный граф
    plt.savefig('/path/to/save/figure')
    plt.show()
    

Кстати, можно значительно упростить нормализацию рёбер по Standard Score (он же Z-score), применив метод scipy.stats.mstats.zscore из библиотеки scipy.

Всё просто, не так ли?

Теперь, если собрать всё воедино,

if __name__ == '__main__':
    groups = ['oldlentach', 'echomsk', 'meduzaproject', 'tvrain', 'bbc',
    '1tv', 'izvestia', 'rt_russian', 'lentaru', 'ntv',
    'habr', 'postnauka', 'cloudytech', 'space_live', 'popularmechanics',
    'inbest', 'lovestime', 'orealno', 'devpoymut', 'padik_adik']
    groups_out = get_groups_users(groups)
    graph = make_graph(groups_out)
    plot_graph(graph, 500)
    

то можно нарисовать вот такой вот граф (щелкните по картинке, чтобы увеличить её):

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

Интересно, кстати, что между группами хабрахабра, телеканала Дождь (tvrain), Эха Москвы (echomsk), журнала Популярная механика (popularmechanics) и информационного проекта Медуза (meduzaproject) (и еще немного паблика Постнаука (postnauka)) существуют серьёзные связи — аудитория групп довольно сильно пересекается. А группа padik_adik, которая на визуализации предстает изолированной вершиной — это группа «Пацаны поймут» с соответствующим контингентом, который, как можно видеть, не особенно любит связываться со всем остальным миром

Я буду очень признателен, если вы оставите здесь комментарий — можно хвалебный, можно ругательный.

Рекомендуемая литература

Хорошая статья по подключению к API вконтакте с помощью Python и скачиванию стены (рус.)

Статья на хабре, где рассказывается о том, как написать модуль авторизации для  API vk (рус.)

Официальная документация по API vk (рус. )

Еще одна большая статья по парсингу вконтакте и построению социального графа (рус.)

Официальная документация библиотеки NetworkX (англ.)