社会网络分析《平凡的世界》-Python实现(二)
社交媒体充斥着我们生活的时代,其已经成为了人们交流、获取信息、建立关系的重要平台。无论是微信、微博、抖音等,还是其他社交媒体,都构成了庞大而复杂的社交网络。在这个网络中,我们关注着各种KOL(Key Opinion Leader,关键意见领袖),同时也有自己的粉丝,形成了一个错综复杂的社交关系网。随着时间的推移,这个关系网络不断壮大,关注和粉丝数量逐渐增加。这个网络不仅仅是我们个人的社交圈子,更是信息传播的重要渠道。通过社交网络,我们可以了解到各种新闻、热点话题、产品信息等,而且这些信息的传播速度之快常常令人惊叹。因此,分析这些社交网络对于了解我们的行为,以及做出决策来说至关重要。
一、爬取《平凡的世界》(162个文本文件)
注意:爬取分两部分,一部分是完整书格式:world1.txt;一部分为章格式:第三部 第49章.txt。
import os
import time
import requests
from bs4 import BeautifulSoup
def scrape_and_save_content(url, folder_path):
# Make a request
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
response = requests.get(url=url, headers=headers)
# Set encoding
response.encoding = 'utf-8'
# Parse HTML
soup = BeautifulSoup(response.text, 'lxml')
# Get chapter title
chapter_title = soup.find('h1').get_text()
print(chapter_title)
# Get paragraph content
paragraphs = soup.find_all('p')
content = ""
for paragraph in paragraphs:
if '下一章' in paragraph.get_text():
break
content += paragraph.get_text().replace('S*锓', '') + '\n'
# Write content to file
filename = f'{chapter_title}.txt'
with open(os.path.join(folder_path, filename), 'w', encoding='utf-8') as f:
f.write(content)
# Start time
starttime = time.time()
print(starttime)
# Create a new folder
folder_path = "E:/Python/Ordinary_world_1/" #文件保存目录,可修改!!!
os.makedirs(folder_path, exist_ok=True)
# Loop through categories and chapters
categories = ['yi', 'er', 'san']
for category in categories:
for chapter_num in range(1, 55):
# Construct URL
url = f'http://www.pingfandeshijie.net/di-{category}-bu-{chapter_num:02d}.html'
# Scrape and save content
scrape_and_save_content(url, folder_path)
# End time
endtime = time.time()
print(endtime)
# Total program execution time
print(round(endtime - starttime, 2))
二、获取主要人物
从网上诸如电视剧人物介绍中提取相关人物,命名为name.txt,放入Python当前工作路径里,以便后面程序使用。这里收集了69个人物,数据结构见图1。
图1 | 图2 |
---|---|
![]() |
![]() |
三、生成词云图
import os
import random
import numpy as np
import matplotlib.pyplot as plt
from wordcloud import WordCloud
# 打开文件
def open_file(filename):
with open(filename, encoding='utf-8') as file:
return file.readlines()
# 提取人物信息
def extract_names(filename):
names = []
for name in open_file(filename):
names.append(name.strip())
return names
# 提取文本信息
def extract_content(filename):
return open_file(filename)
# 统计人物出现频数
def count_frequency(names, content):
data = []
for name in names:
num = sum(1 for line in content if name in line)
data.append((name, num))
return data
# 生成词云
def generate_wordcloud(data):
def random_color_func(word=None, font_size=None, position=None, orientation=None, font_path=None, random_state=None):
h, s, l = random.choice([(188, 72, 53), (253, 63, 56), (12, 78, 69)])
return "hsl({}, {}%, {}%)".format(h, s, l)
x, y = np.ogrid[:1500,:1500]
mask = (x - 700) ** 2 + (y - 700) ** 2 > 700 ** 2
mask = 255 * mask.astype(int)
wc = WordCloud(
background_color='white',
mask=mask,
font_path='simhei.ttf', # 使用中文字体
max_words=2000,
max_font_size=250,
min_font_size=15,
color_func=random_color_func,
prefer_horizontal=1,
random_state=50
)
word_freq = {name: freq for name, freq in data}
wc.generate_from_frequencies(word_freq)
plt.imshow(wc)
plt.axis('off')
plt.show()
wc.to_file("平凡的世界.jpg")
print('生成词云成功!')
if __name__ == "__main__":
# 提取人物信息
names = extract_names('name.txt')
# 提取文本信息
content = extract_content('world1.txt')
# 统计人物出现频数
data = count_frequency(names, content)
# 生成词云
generate_wordcloud(data)
四、获得社交网络数据
为可视化《平凡的世界》为例的人物关系,定义两两人物关系采用以下两种方式:两个人名同时出现在同一段落,则联系+1;②两个人名同时出现在同一章节,则联系+1。接下来利用前面爬取的文本文件,生成社交网络数据包。
import os
import pandas as pd
# 打开文本
file_text = open('world1.txt', encoding='utf-8')
file_name = open('name.txt', encoding='utf-8')
# 人物信息
names = []
for name in file_name:
names.append(name.replace('\n', ''))
# 文本信息
content = []
for line in file_text:
content.append(line)
# 生成下标
flags = [x * 0 for x in range(len(names))]
# 生成人物联系
data = []
for a in range(len(names)):
flags[a] = 1
name_1 = names[a]
for b in range(len(names)):
if flags[b] == 0:
name_2 = names[b]
# 为三个字符时,取名字
if len(name_1) == 3:
name_1 = name_1[1:]
if len(name_2) == 3:
name_2 = name_2[1:]
# 遍历章节及段落
num1, num2 = 0, 0
for i in os.listdir('E:\Python\Ordinary_world_1'):
with open('E:\Python\Ordinary_world_1\\' + i, encoding='utf-8') as worldFile:
worldContent = worldFile.read()
if (name_1 in worldContent) and (name_2 in worldContent):
num1 += 1
for j in content:
if (name_1 in j) and (name_2 in j):
num2 += 1
if num1 != 0 and num1 >= 3 and num2 >= 2:
data.append([names[a], names[b], num1, num2])
# 将数据转换为DataFrame
df = pd.DataFrame(data, columns=['姓名1', '姓名2', '章中出现次数', '段落中出现次数'])
# 将DataFrame写入Excel文件
df.to_excel('weight.xlsx', index=False)
五、可视化社交网络
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
# 显示中文,及字体设置
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['font.size'] = 10
plt.rcParams['axes.unicode_minus'] = False
# 读取文件
df = pd.read_excel('weight.xlsx', header=None, names=['First', 'Second', 'chapweight', 'duanweight'])
print(df.head())
# 将 'chapweight' 列中的字符串转换为数值型数据
df['chapweight'] = pd.to_numeric(df['chapweight'], errors='coerce')
# 计算段落人物关系权重
df['weight'] = df['chapweight'] / 162 #书总计162章
# 获取联系大于4的数据,重新生成索引
df2 = df[df.weight > 0.025].reset_index(drop=True)
plt.figure(figsize=(12, 12))
# 生成社交网络图
G = nx.Graph()
# 添加边
for ii in df2.index:
G.add_edge(df2.First[ii], df2.Second[ii], weight=df2.weight[ii])
# 定义3种边,大于32,16-32,小于16
elarge = [(u, v) for (u, v, d) in G.edges(data=True) if (d['weight'] > 0.2)]
emidle = [(u, v) for (u, v, d) in G.edges(data=True) if (d['weight'] > 0.1) & (d['weight'] <= 0.2)]
esmall = [(u, v) for (u, v, d) in G.edges(data=True) if (d['weight'] <= 0.1)]
# 图的布局
# 节点在一个圆环上均匀分布
pos = nx.circular_layout(G)
# 点
nx.draw_networkx_nodes(G, pos, alpha=0.6, node_size=350)
# 边
nx.draw_networkx_edges(G, pos, edgelist=elarge, width=2, alpha=0.9, edge_color='g')
nx.draw_networkx_edges(G, pos, edgelist=esmall, width=1, alpha=0.3, edge_color='b', style='dashed')
# 标签
nx.draw_networkx_labels(G, pos, font_size=10)
# 生成结果
plt.axis('off')
plt.title('平凡的世界')
plt.show()
# 计算每个节点的重要程度
Gdegree = nx.degree(G)
Gdegree = dict(Gdegree)
Gdegree = pd.DataFrame({'name': list(Gdegree.keys()), 'degree': list(Gdegree.values())})
# 第一张图,所有人物
#Gdegree.sort_values(by='degree', ascending=False).plot(x='name', y='degree', kind='bar', color=(136/255, 43/255, 48/255), figsize=(12, 6), legend=False)
# 第二张图,前20人物
Gdegree.sort_values(by='degree', ascending=True)[-20:].plot(x='name', y='degree', kind='barh', color=(16/255, 152/255, 168/255), figsize=(12, 6), legend=False)
plt.xticks(size=8)
# 第一张图标签
# plt.ylabel('degree')
# 第二张图标签
plt.ylabel('name')
plt.show()
图3 | 图4 |
---|---|
![]() |
![]() |
总结
社交网络不仅是我们日常生活中的重要组成部分,也是我们获取信息、建立关系、进行互动的重要平台。通过对社交网络的分析,我们可以更好地了解社交关系、把握信息传播规律、满足用户需求,从而更好地做出各项决策,提升我们的社交体验和生活质量。
首先,通过分析社交网络中的关系,我们可以更好地了解自己的社交圈子,找到我们最感兴趣的内容和人群。比如,通过分析我们的关注列表和粉丝列表,我们可以发现哪些KOL拥有更大的影响力,哪些朋友更可能成为我们的忠实支持者,从而更有针对性地选择我们关注的内容,提升我们的社交体验。其次,社交网络也是一个信息传播的重要平台。通过社交网络,我们可以迅速了解到各种热点事件、新闻资讯和产品推广。而且,这些信息常常是通过我们的朋友或者KOL传播给我们的,具有更高的可信度和影响力。因此,对社交网络中信息的传播规律进行分析,可以帮助我们更好地了解信息的来源、传播路径和影响范围,从而更准确地判断信息的真实性和重要性。最后,社交网络也是一个互动的平台。通过社交网络,我们可以和朋友、KOL以及其他用户进行实时的交流和互动。通过分析社交网络中的互动行为,我们可以更好地了解用户的需求和偏好,从而更有针对性地制定营销策略、推广产品和服务。
参考文献
自我中心网络(Ego Network)
1.1 网络虚假数据生成
鉴于社交数据涉及个人隐私信息,数据需要脱敏,所以采用Python库Faker虚构了下面的社交数据,描述个人社交关系,数据结构如下图所示。
import csv
from faker import Faker
# 初始化Faker
fake = Faker()
# 打开一个文件以写入数据
with open('Connections.csv', 'w', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
# 写入标题行
writer.writerow(['first Name', 'last Name', 'company', 'position', 'connected on'])
# 生成500行数据
for _ in range(500):
# 使用Faker生成假数据
first_name = fake.first_name()
last_name = fake.last_name()
company = fake.company()
position = fake.job()
connected_on = fake.date_between(start_date='-5y', end_date='today').isoformat()
# 写入生成的行数据
writer.writerow([first_name, last_name, company, position, connected_on])
1.2 自我中心网络展示
import pandas as pd
from pyvis import network as net
import networkx as nx
# 读取数据集
df_ori = pd.read_csv("Connections.csv")
# 查看数据框的列名和前几行数据
print(df_ori.columns)
print(df_ori.head())
# 数据清洗和预处理
df = (
pd.DataFrame(df_ori) # 将df_ori转换为DataFrame对象
.dropna() # 去除掉空值
)
# 统计公司和职位信息
df_company = df['company'].value_counts().reset_index()
df_company.columns = ['company', 'count']
df_company = df_company.sort_values(by="count", ascending=False)
# 实例化网络
g_company = nx.Graph()
# 遍历公司数据集
for _, row in df_company.iterrows():
company = row['company']
count = row['count']
positions = set(df[df['company'] == company]['position'])
hover_info = f"<b>{company}</b> – {count}<ul>{''.join(f'<li>{x}</li>' for x in positions)}</ul>"
g_company.add_node(company, size=count * 2, title=hover_info, color='#3449eb')
g_company.add_edge('myself', company, color='grey') # 使用 "myself" 作为中心节点
# 生成公司网络图表
nt_company = net.Network(height='700px', width='700px', bgcolor="black", font_color='white')
nt_company.from_nx(g_company)
nt_company.hrepulsion()
# 保存公司网络图表为HTML文件
nt_company.save_graph('company_graph.html')
# 实例化网络
g_position = nx.Graph()
# 统计职位信息
df_position = df['position'].value_counts().reset_index()
df_position.columns = ['position', 'count']
# 遍历职位数据集
for _, row in df_position.iterrows():
position = row['position']
count = row['count']
companies = set(df[df['position'] == position]['company'])
hover_info = f"<b>{position}</b> – {count}<ul>{''.join(f'<li>{x}</li>' for x in companies)}</ul>"
g_position.add_node(position, size=count * 2, title=hover_info, color='#3449eb')
g_position.add_edge('myself', position, color='grey') # 使用 "myself" 作为中心节点
# 生成职位网络图表
nt_position = net.Network(height='700px', width='700px', bgcolor="black", font_color='white')
nt_position.from_nx(g_position)
nt_position.hrepulsion()
# 保存职位网络图表为HTML文件
nt_position.save_graph('position_graph.html')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!