ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

基于Python的新浪微博转发社交网络分析:从建图到中心性实战

基于Python的新浪微博转发社交网络分析:从建图到中心性实战 简介这份资源面向社交网络分析与数据挖掘的初学者及进阶学习者围绕新浪微博转发关系展开帮助读者理解如何用Python完成从数据采集到网络可视化的完整流程。包内共16个文件以6个Python脚本为核心辅以3个编译文件、3个文本说明、2张结果图、1份CSV数据与1份Markdown文档压缩包约485KB体量轻便便于快速上手。脚本模块划分清晰模拟登录与编码处理负责获取访问权限网页解析模块负责抓取转发数据网络图与时间图脚本分别用于刻画用户转发关系和传播时序配套的PNG图片与CSV数据可直接对照验证运行结果。已有771人学习下载说明该案例在社交网络分析学习中具有一定参考价值。读者可借此掌握转发网络构建、节点关系可视化与传播时间线绘制等实用技能并在此基础上迁移到其他社交平台的数据分析任务中。1. 微博转发网络到底能挖出什么从一条热搜的传播路径说起一条微博被转发了 3 万次看起来是爆款但真正值得问的是这 3 万次转发里有多少是普通用户的自发扩散有多少是几个大 V 在关键节点上推了一把如果把这 3 万次转发还原成一张有向图谁是那个「一发微博就能带动整条链路」的节点谁又是被裹挟着转发的长尾这就是新浪微博转发社交网络分析要回答的问题。它属于社交网络分析Social Network Analysis里最经典的一类任务把用户当节点、把转发关系当有向边构建一张传播图然后在图上算中心性、找社区、看传播层级。用 Python 做这件事的门槛并不高——pandas 处理转发表、networkx 建图算指标、matplotlib 或 pyecharts 出图一套流程跑下来一个中等规模的数据集在普通笔记本上几分钟就能出结果。适合谁做舆情监测的、写人工智能大作业的、想入门图数据分析的以及需要给运营侧解释「这次传播为什么起量」的人。下面我按自己实际跑过的顺序把数据、建图、指标、可视化、踩坑一条条讲清楚。2. 数据从哪来、长什么样转发表的字段设计与采集边界2.1 一张能直接建图的转发表需要哪些列社交网络分析的成败八成取决于数据表结构。微博转发数据最核心的信息是「谁转了谁的哪条微博」所以最小可用字段是这几个字段名含义建图时的角色user_id转发者用户 ID边的起点retweeted_user_id被转发者用户 ID边的终点weibo_id被转发的原微博 ID用于分图created_at转发时间传播时序分析repost_count该用户的历史转发数节点权重参考很多人只存了转发者忘了存「被转发者」结果建图时只能做无向图中心性算出来全是错的。我一般会在采集阶段就把retweeted_user_id补上——微博转发链里每条转发都会指向它转发的上一条顺着这个字段就能还原出完整的传播树。采集边界要提前想清楚是抓单条微博的完整转发链还是抓某个话题下的一批微博前者适合做深度传播路径分析数据量小但链路完整后者适合做广度网络但容易混入无关节点。做人工智能大作业的话建议先锁定 1 到 3 条有代表性的微博把链路跑通再扩量。2.2 用 Python 把原始 JSON 整理成边列表假设你已经拿到了转发数据的 JSON常见做法是用 requests 抓接口返回这里不展开采集细节只讲整理下面这段代码把嵌套结构拍平成边列表import json import pandas as pd # 原始数据每条记录包含转发者和被转发者信息 with open(retweets.json, r, encodingutf-8) as f: raw json.load(f) edges [] for item in raw: # 跳过缺失关键字段的脏数据 if not item.get(user) or not item.get(retweeted_user): continue edges.append({ user_id: item[user][id], retweeted_user_id: item[retweeted_user][id], weibo_id: item.get(weibo_id), created_at: item.get(created_at), repost_count: item[user].get(repost_count, 0), }) df pd.DataFrame(edges) # 去重同一对用户可能多次转发同一条微博建图时只保留一次 df df.drop_duplicates(subset[user_id, retweeted_user_id, weibo_id]) df.to_csv(edges.csv, indexFalse) print(df.shape)逻辑说明先做字段存在性校验避免 KeyError 直接中断drop_duplicates那一步很关键因为同一用户可能多次转发同一条微博不去重会让边权重虚高后续 PageRank 结果失真。参数上subset一定要带上weibo_id否则跨微博的相同用户对会被误删。提示如果数据量超过百万行json.load会吃满内存改用ijson流式解析或者分文件读取后pd.concat。3. 用 networkx 建传播图有向图、权重和三种中心性怎么选3.1 有向图还是无向图先想清楚传播方向微博转发是有明确方向的A 转了 B 的微博信息从 B 流向 A。所以建图必须用DiGraph不能用Graph。用无向图算度中心性会把「被很多人转的大 V」和「转了很多人的普通用户」混为一谈结论直接翻车。import networkx as nx import pandas as pd df pd.read_csv(edges.csv) G nx.DiGraph() for _, row in df.iterrows(): u, v int(row[user_id]), int(row[retweeted_user_id]) if G.has_edge(u, v): G[u][v][weight] 1 # 多次转发累加权重 else: G.add_edge(u, v, weight1) print(f节点数: {G.number_of_nodes()}, 边数: {G.number_of_edges()})参数说明weight记录同一对用户之间的转发次数后续算加权中心性时会用到。如果只关心传播结构不关心频次可以不加权重但建议保留删起来容易补起来难。3.2 度中心性、介数中心性、PageRank 各自回答什么问题三个指标不是随便挑一个就行它们回答的是不同问题度中心性degree centrality谁被转发得最多。在有向图里要分开看入度和出度入度高说明这个人被很多人转发是内容源头出度高说明这个人到处转发是活跃扩散者。介数中心性betweenness centrality谁处在传播路径的咽喉位置。去掉这个人很多传播链路会断掉。这个指标计算量大节点上万时要用k参数做近似。PageRank谁的影响力最大且考虑了转发者的质量。被一个高影响力用户转发比被一百个僵尸号转发更值钱。# 入度中心性被转发最多的节点 in_degree nx.in_degree_centrality(G) # 介数中心性近似计算k500 采样 betweenness nx.betweenness_centrality(G, k500, weightweight) # PageRank影响力排序 pagerank nx.pagerank(G, alpha0.85, weightweight) # 汇总成表按 PageRank 排序 result pd.DataFrame({ user_id: list(G.nodes()), in_degree: [in_degree[n] for n in G.nodes()], betweenness: [betweenness[n] for n in G.nodes()], pagerank: [pagerank[n] for n in G.nodes()], }).sort_values(pagerank, ascendingFalse) print(result.head(10))参数说明alpha0.85是 PageRank 的阻尼系数含义是用户有 85% 概率继续沿着转发链往下走15% 概率随机跳转这个值一般不改。k500是介数中心性的采样节点数不设的话精确计算复杂度是 O(nm)上万节点会跑到你怀疑人生。注意如果图里有大量孤立节点只转发没被转发的人先做一次G.remove_nodes_from(list(nx.isolates(G)))否则中心性分布会被拉偏。4. 社区发现与传播层级把一张大图拆成能解释的小块4.1 Louvain 社区发现在转发图上的实际效果一张几万节点的转发图直接看是一团乱麻。社区发现的作用是把图拆成若干个内部连接紧密的子群每个子群往往对应一个圈层——可能是某个兴趣群体也可能是某次事件中集中发声的一批账号。import community as community_louvain # python-louvain 包 # Louvain 要求无向图先转一下 G_undirected G.to_undirected() partition community_louvain.best_partition(G_undirected, weightweight) # 把社区编号写回节点属性 nx.set_node_attributes(G, partition, community) # 统计每个社区的规模 from collections import Counter sizes Counter(partition.values()) print(sizes.most_common(10))逻辑说明best_partition返回的是{节点: 社区编号}的字典编号本身没有语义只代表分组。weightweight让转发次数多的边在划分时权重更大更符合实际传播强度。如果社区数量过多比如几百个说明图太稀疏可以考虑先按边权阈值过滤掉只转发一次的弱连接。4.2 传播层级从源头到长尾的 BFS 分层转发网络天然是一棵以原微博发布者为根的树忽略跨微博的边。用广度优先搜索可以算出每个节点距离源头几层层数分布直接反映传播深度。from collections import deque def bfs_levels(G, source): levels {source: 0} q deque([source]) while q: node q.popleft() for neighbor in G.successors(node): # 沿转发方向 if neighbor not in levels: levels[neighbor] levels[node] 1 q.append(neighbor) return levels # 找到入度为 0 的节点作为源头原微博发布者 sources [n for n in G.nodes() if G.in_degree(n) 0] if sources: levels bfs_levels(G, sources[0]) level_counts Counter(levels.values()) print(sorted(level_counts.items()))参数说明G.successors沿边的方向走即从被转发者到转发者这样层数递增才符合传播方向。如果图里有环互转levels字典的去重逻辑会自动跳过已访问节点不会死循环。层级分布通常呈现「第一层很大、后面迅速衰减」的形态。如果第二层特别大说明有一批人几乎同时转发可能是水军集中操作也可能是某个大 V 转发后带来的爆发。5. 可视化与避坑出图好看和结果可信是两回事5.1 用 pyecharts 出一张能放进报告的传播图matplotlib 画大图会糊成一团节点超过 500 个基本没法看。pyecharts 的Graph支持交互缩放适合放进汇报页面。from pyecharts import options as opts from pyecharts.charts import Graph # 只取 PageRank 前 100 的节点避免图太密 top_nodes result.head(100)[user_id].tolist() sub G.subgraph(top_nodes) nodes [{name: str(n), symbolSize: pagerank[n] * 300} for n in sub.nodes()] links [{source: str(u), target: str(v)} for u, v in sub.edges()] g ( Graph() .add(, nodes, links, repulsion8000, layoutforce) .set_global_opts(title_optsopts.TitleOpts(title微博转发传播图Top100)) ) g.render(retweet_graph.html)参数说明symbolSize用 PageRank 值放大 300 倍让高影响力节点视觉上更突出repulsion8000是斥力系数值越大节点越分散太小人名会叠在一起。layoutforce是力导向布局适合展示社区结构。5.2 避坑五个我实际踩过的转发网络分析问题现象一中心性排名里全是采集账号。原因爬虫账号转发量极大出度异常高把度中心性榜单占满。解决先按repost_count或发博频率过滤掉明显异常的账号或者改用 PageRank它对高频低质节点有惩罚。现象二社区发现结果每次跑都不一样。原因Louvain 算法有随机性不同运行会得到不同划分。解决设random_state参数固定随机种子或者跑多次取模块度最高的那次。现象三传播层级算出来只有两层。原因数据只抓了直接转发没有抓二级转发链导致所有节点都直接连到源头。解决采集时确保拿到完整的retweeted_user_id链而不是只记录原微博 ID。现象四PageRank 结果和直觉完全相反。原因图里存在大量互转形成的环PageRank 在环里反复分配权重。解决检查是否有双向边必要时把互转合并成一条无向边或者提高阻尼系数让随机跳转概率增大。现象五可视化图加载卡死。原因节点数太多浏览器渲染不动。解决按 PageRank 或度中心性截断 Top NN 控制在 200 以内或者用 Gephi 做离线布局再导出图片。6. 从跑通到跑准一个验证分析结果是否可信的小技巧跑完上面整套流程你手里会有一张图、几个中心性排名、一份社区划分。但怎么判断这些结果不是自娱自乐我一般用一个笨办法拿已知事实做交叉验证。具体做法是从 PageRank 前 10 的节点里随机挑 3 个手动去微博上搜这个用户看他的粉丝量、认证信息、历史微博的转发量级。如果 PageRank 排第一的是一个粉丝不到 100 的账号那大概率是数据采集出了问题或者图里混入了异常节点。反过来如果排名靠前的都是你预期中的大 V 或活跃账号说明建图和指标计算这条链路是通的。另一个验证角度是看社区划分和话题的对应关系。如果某个社区里的用户手动抽查几个发现他们转发的微博内容高度相似说明社区发现确实抓到了真实的兴趣圈层。如果社区里什么人都有那可能是边权阈值设得太低弱连接把不相干的群体粘在了一起。还有一个我常用的习惯把edges.csv按created_at排序画一张转发量随时间变化的折线图。传播曲线通常有两种形态——一种是「爆发后快速衰减」对应突发事件另一种是「持续多波峰」对应有多个大 V 在不同时间点接力转发。这两种形态对应的运营策略完全不同前者要抢第一时间后者要维护好关键节点的关系。最后说一个参数上的经验值betweenness_centrality的k采样数节点数在 5000 以下时可以设kNone做精确计算超过 1 万建议k500到1000再大就失去近似意义了。pagerank的max_iter默认 100 一般够用如果图特别大收敛慢可以加到 200但别超过 500否则可能是图里有强连通分量导致震荡。这套流程我从第一次跑通到能稳定出可信结果大概调了两周大部分时间花在数据清洗和验证上建图和算指标本身反而很快。如果你刚开始做建议先用几百条数据把链路跑通确认每个环节的输出符合预期再上量。希望帮到你。本文还有配套的精品资源点击获取
返回列表