9.8 KiB
Лабораторная работа 4. «Визуализация связей в виде графов»
При выполнении данной лабораторной работы производится визуализация связей социальных сетей в виде графа.
1. Запрос перечня друзей пользователя
Для выполнения работы импортируем необходимый пакет.
import vk_api
Как и при выполнении первой лабораторной работы создаем подключение, а далее находим друзей user1
с помощью вызова метода friends.get
.
friends_user1 = tools.get_all('friends.get', 100, {'user_id': user1})
На выходе получим перечень id
друзей пользователя. API VK позволяет дополнительно сразу запрашивать параметры пользователя такие как:
nickname, domain, sex, bdate, city, country, timezone,
photo_50, photo_100, photo_200_orig, has_mobile,
contacts, education, online, relation, last_seen,
status, can_write_private_message, can_see_all_posts,
can_post, universities
Необходимые параметры указываются в параметре fields
. При этом для выполнения текущей задачи имеет ценность лишь список друзей. Поэтому дополнительный параметры указывать не будем.
Итоговый код будет выглядеть следующим образом.
import vk_api
import time
import json
import pickle
user1 = 249771326
def auth_handler():
""" При двухфакторной аутентификации вызывается эта
функция. """
# Код двухфакторной аутентификации
key = input("Enter authentication code: ")
# Если: True ‐ сохранить, False ‐ не сохранять.
remember_device = True
return key, remember_device
def stop_f(items):
print (items)
def get_groups_users(friends_list, tools):
friends_out = {}
for friend in friends_list:
try:
friends_out[friend] = tools.get_all('friends.get', 100, {'user_id': friend})
except Exception:
friends_out[friend] = []
time.sleep(1)
return friends_out
def main():
login, password = '<ВАШ ЛОГИН>', '<ВАШ ПАРОЛЬ>'
vk_session = vk_api.VkApi(
login,
password,
# функция для обработки двухфакторной аутентификации
auth_handler=auth_handler
)
try:
vk_session.auth()
except vk_api.AuthError as error_msg:
print(error_msg)
tools = vk_api.VkTools(vk_session)
friend_list=[]
friend_list.append(user1)
friends_out = get_groups_users(friend_list, tools)
print(friends_out)
if __name__ == '__main__':
main()
В результате исполнения этого данного получится JSON-response со списком друзей пользователя, id
которого, был указан в переменной user1
.
2. Формирование графа друзей пользователя
Установим модуль networkX (необходима версия 1.9).
pip install networkx==1.9
Далее реализуем функции для визуализации графа.
import networkx as nx
def make_graph(friends_out, friends_friends):
graph = nx.Graph()
graph.add_node(user1, size = friends_out[user1]['count'])
for i in friends_out[user1]['items']:
try:
graph.add_node(i, size=friends_friends[i]['count'])
intersection = set(friends_out[user1]['items']).intersection(
set(friends_friends[i]['items']))
graph.add_edge(user1, i, weight=len(intersection))
except Exception:
print("err")
return graph
Данная функция создает граф, вершинами которого являются узлы, содержащие id
друзей, а также связывает между собой пользователя и его друга. Так как необходимо связать не только пользователя и друзей, а ещё и друзей между собой, то модифицируем код следующим образом.
def make_graph(friends_out, friends_friends):
graph = nx.Graph()
graph.add_node(user1, size = friends_out[user1]['count'])
for i in friends_out[user1]['items']:
try:
graph.add_node(i, size = friends_friends[i]['count'])
intersection = set(friends_out[user1]['items']).intersection(
set(friends_friends[i]['items']))
graph.add_edge(user1, i, weight=len(intersection))
except Exception:
print("err")
for i in range(len(friends_out[user1]['items'])):
id1 = friends_out[user1]['items'][i]
for k in range(i+1, len(friends_out[user1]['items'])):
id2 = friends_out[user1]['items'][k]
try:
intersection = set(friends_friends[id1]['items']).intersection(
set(friends_friends[id2]['items']))
if len(intersection) > 0:
graph.add_edge(id1, id2, weight=len(intersection))
except Exception:
print("err friend")
return graph
Здесь дополнительно добавляется переменная friends_friends
, которая содержит в себе списки друзей друзей пользователя.
Данная переменная появляется в результате вызова метода get_groups_users
куда на вход подаем список id
друзей пользователя.
friend_friends = get_groups_users(friends_out[user1]['items'], tools)
Количество запросов ограничено, поэтому с целью экономии предлагается использовать модуль pickle
. Данный модуль реализует мощный алгоритм сериализации и десериализации объектов Python. "Pickling" – процесс преобразования объекта Python в поток байтов, а "unpickling" – обратная операция, в результате которой поток байтов преобразуется обратно в Python-объект. Поток байтов легко можно записать в файл, поэтому модуль pickle
широко применяется для сохранения и загрузки сложных объектов в Python.
Пример его использования выглядит следующим образом.
with open('friends_friends.pkl', 'wb') as output:
pickle.dump(friend_friends, output, pickle.HIGHEST_PROTOCOL)
Этот пример для сохранения объекта. Следующий пример – для загрузки объекта.
with open('friends_friends.pkl', 'rb') as input:
friends_friends = pickle.load(input)
Вызовем функцию make_graph
в функции main
.
g = make_graph(friends_out, friend_friends)
После формирования связей так же рекомендуется сохранить полученный граф при помощи Pickle.
3. Визуализация графа друзей пользователя
Сформированный граф необходимо визуализировать. Для этого будем использовать модуль matplotlib
(необходимая версия – 2.2.4).
Реализуем функцию визуализации.
def plot_graph(graph, adjust_nodesize):
#pos = nx.drawing.layout.circular_layout(graph)
pos=nx.spring_layout(graph, k=0.1)
# нормализуем размер вершины для визуализации.
# Оптимальное значение параметра
#vadjust_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/2) for i in graph.edges()]
#создаем граф для визуализации
nx.draw_networkx_nodes(
graph,
pos,
node_size=nodesize,
node_color='y',
alpha=0.9
)
nx.draw_networkx_edges(
graph,
pos,
width=edgewidth,
edge_color='b'
)
nx.draw_networkx_labels(graph, pos, fontsize=5)
# сохраняем и показываем визуализированный граф
plt.savefig('saved')
plt.show()
Вызовем реализованную функцию в main
.
plot_graph(g, 500)
В результате работы кода будет получено изображение графа друзей пользователя.
Данный метод является довольно простым, т.к. при этом не происходит процесс кластеризации графа, для лучшего понимания его структуры. Однако этот пример удобен для понимания процесса работы с графами.