简介这份资源面向社交网络分析与Python数据挖掘的学习者围绕新浪微博转发关系展开帮助读者理解如何从模拟登录、网页解析到网络图与时间图绘制的完整分析链路。包内共16个文件以6个Python脚本为核心辅以3个pyc编译文件、3个txt说明、2张png结果图、1个csv转发数据及1个md文档压缩包约485KB结构紧凑、便于按模块查阅。其中登录与编码模块负责会话维持解析模块负责抓取转发数据绘图脚本分别输出网络关系图与时间演化图csv数据可直接用于复现实验。已有771人学习下载适合作为课程设计、毕业设计或社交网络分析入门的实践参考读者可据此掌握转发网络构建、节点关系可视化与时间维度分析的基本方法并借鉴模块划分与排错思路。1. 微博转发链路怎么变成一张可算的图这套 Python 源码能解决什么刷微博时你看到的是「A 转发了 B 的微博」但做社交网络分析时你真正要的是一张有向图谁是源头、谁是放大器、信息在第几跳衰减。这套weibo_forward_analysis-master就是干这件事的——用 Python 把新浪微博的转发关系抓下来落成data.csv再分别画出网络图和转发时间图。它适合三类人想入门社交网络分析但缺一份能跑通的代码的人、要交人工智能或数据挖掘课程大作业的学生、以及需要快速验证「转发结构长什么样」的从业者。整套代码拆得很清楚登录、解析、建图、画图各管一段不是一坨糊在一起的脚本这点对新手很友好。2. 拆开压缩包先看结构六个脚本各管哪一段拿到weibo_forward_analysis-master.zip解压后目录里既有.py源码也有.pyc编译文件和几张结果图。很多人第一反应是「怎么这么多重复文件」其实这是作者把源码和编译产物一起打包了.pyc是 Python 解释器生成的字节码运行时优先加载源码在时以源码为准。先搞清楚每个文件干什么后面调试才不会抓瞎。2.1 文件清单与职责划分文件类型作用weibo_login.py源码模拟登录拿到会话 Cookieweibo_login.pyc字节码登录模块编译产物post_encode.py源码表单/参数编码处理post_encode.pyc字节码编码模块编译产物get_weibo.py源码抓取转发页并解析出转发关系get_weibo.pyc字节码解析模块编译产物network_graph.py源码用转发关系画网络图time_graph.py源码按时间维度画转发趋势图data.csv数据已抓好的转发数据network_graph.png结果网络图输出样例time_graph.png结果时间图输出样例readme.md文档使用说明test.txt/a.txt/bug.txt杂项调试日志与临时记录从职责看整条链路是「登录 → 抓取 → 落 CSV → 建图 → 出图」。data.csv是中间产物也是核心资产只要它格式对后面两个画图脚本可以脱离爬虫单独跑。这一点很关键如果你只是想做可视化练习完全可以跳过登录和抓取直接拿现成的data.csv跑network_graph.py和time_graph.py。2.2 环境准备与依赖确认这套代码是 Python 2 时代的产物weibo_login.pyc这种编译文件基本坐实了这一点。直接上 Python 3 会踩编码和库名的坑所以第一步是把环境对齐。常见做法是建一个独立虚拟环境避免污染系统 Python。# 建虚拟环境Python 2.7 环境老项目常见做法 virtualenv venv27 source venv27/bin/activate # Windows 用 venv27\Scripts\activate # 核心依赖网络图靠 networkx matplotlib pip install networkx matplotlib requests beautifulsoup4逻辑说明virtualenv隔离出一个干净的解释器networkx负责图结构的构建与布局计算matplotlib负责把图渲染成 PNGrequests和beautifulsoup4是抓取和解析网页的基础。参数上networkx版本别装太新2.x 早期版本对老代码的 API 兼容更好如果pip默认拉到了最新版导致draw报错回退到networkx2.2通常能解决。提示如果你机器上只有 Python 3别硬改源码里的print语句去凑先确认weibo_login.pyc能否被 Python 3 加载——大概率不能。要么装 Python 2.7要么只跑画图部分。3. 从登录到 data.csv抓取链路怎么跑通抓取是整套代码里最容易翻车的一环因为它依赖登录态。weibo_login.py和post_encode.py配合完成模拟登录get_weibo.py拿着会话去请求转发页并解析。理解这条链路比盲目运行脚本重要得多。3.1 模拟登录与会话保持weibo_login.py的核心思路是构造登录表单 → 编码 → POST 到登录接口 → 从响应里取 Cookie 存下来。post_encode.py负责把用户名、密码等字段按接口要求编码这一步在 Python 2 里涉及urllib.quote之类的处理编码错了就会返回「用户名或密码错误」其实根本不是密码问题。# weibo_login.py 典型结构示意按实际源码为准 import requests from post_encode import encode_post_data def login(username, password): session requests.Session() payload encode_post_data(username, password) # 表单编码 headers { User-Agent: Mozilla/5.0 ..., # 伪装浏览器 Referer: https://weibo.com/, } resp session.post(LOGIN_URL, datapayload, headersheaders) if 登录成功标志 in resp.text: return session # 带着 Cookie 的会话 raise RuntimeError(登录失败检查编码或验证码)逻辑说明用requests.Session()而不是单次requests.post是因为 Session 会自动在后续请求里带上登录拿到的 Cookie这是保持登录态的关键。headers里的User-Agent和Referer不是可选项缺了容易被判定为异常请求。参数上encode_post_data返回的字典键名必须和登录接口字段严格对应改一个字母就失败。注意新浪微博登录现在普遍有验证码和风控老代码直接跑很可能卡在登录。如果只是为了分析转发结构建议直接用仓库里现成的data.csv把精力放在建图和出图上。3.2 解析转发页并落成 CSVget_weibo.py拿到会话后请求目标微博的转发列表页用 BeautifulSoup 解析出每条转发的「转发者」和「被转发者」逐条写进data.csv。CSV 的列结构决定了后面建图能不能直接用所以这一步的字段设计要留意。# get_weibo.py 解析与写盘示意 import csv from bs4 import BeautifulSoup def parse_forwards(html): soup BeautifulSoup(html, html.parser) rows [] for item in soup.select(.forward-item): # 转发条目选择器 user item.select_one(.user-name).text.strip() target item.select_one(.origin-user).text.strip() rows.append((user, target)) return rows def save_csv(rows, pathdata.csv): with open(path, w) as f: writer csv.writer(f) writer.writerow([from_user, to_user]) # 表头转发者 - 被转发者 writer.writerows(rows)逻辑说明parse_forwards把每条转发拆成「谁转发了谁」的二元组这是有向图的边。save_csv写两列第一列是边的起点第二列是终点。参数上CSS 选择器.forward-item、.user-name必须和当时页面结构一致微博改版后这些类名会变解析为空就是选择器失效的信号。翻页逻辑通常靠循环改page参数实现注意加time.sleep控制频率否则容易触发限制。4. 建图与出图networkx 怎么把 CSV 变成网络图数据到手后network_graph.py和time_graph.py是两个独立的可视化脚本。前者画转发关系网络后者画转发随时间的变化。这两个脚本可以脱离爬虫单独运行是整套代码里复用价值最高的部分。4.1 用 networkx 构建有向转发图网络图的核心是把 CSV 的每一行当成一条有向边节点是用户边是转发行为。networkx提供DiGraph专门处理有向图布局算法决定节点怎么摆。# network_graph.py 建图与绘制示意 import csv import networkx as nx import matplotlib.pyplot as plt def build_graph(csv_pathdata.csv): G nx.DiGraph() # 有向图 with open(csv_path) as f: reader csv.reader(f) next(reader) # 跳过表头 for from_user, to_user in reader: G.add_edge(from_user, to_user) # 加一条有向边 return G def draw_graph(G, outnetwork_graph.png): plt.figure(figsize(12, 12)) pos nx.spring_layout(G, k0.5, iterations50) # 力导向布局 nx.draw(G, pos, with_labelsFalse, node_size30, edge_colorgray, alpha0.6) plt.savefig(out, dpi150) plt.close()逻辑说明DiGraph保证边有方向箭头从转发者指向被转发者。spring_layout是力导向布局节点之间像弹簧一样互相排斥、边像橡皮筋一样拉近最终形成聚类结构——转发集中的节点会自然聚在一起。参数上k控制节点间距调大节点更分散iterations是迭代次数太小布局不稳定50 左右比较均衡。node_size和alpha影响可读性节点多的时候要调小。4.2 时间维度转发趋势怎么画time_graph.py关注的是「转发量随时间怎么变」。它需要从数据里提取时间字段按时间窗口聚合计数再画折线或柱状图。如果data.csv里没有时间列这个脚本就跑不起来这是很多人卡住的地方。# time_graph.py 时间聚合与绘制示意 import csv from collections import Counter import matplotlib.pyplot as plt def load_times(csv_pathdata.csv): times [] with open(csv_path) as f: reader csv.DictReader(f) for row in reader: if row.get(time): # 需要时间列 times.append(row[time][:13]) # 按小时聚合 return times def draw_time(times, outtime_graph.png): counter Counter(times) keys sorted(counter.keys()) values [counter[k] for k in keys] plt.figure(figsize(14, 6)) plt.plot(keys, values, markero) plt.xticks(rotation45) plt.tight_layout() plt.savefig(out, dpi150)逻辑说明row[time][:13]截取到小时粒度把同一小时的转发归到一组Counter完成计数。sorted保证时间轴有序否则折线会乱跳。参数上切片长度决定聚合粒度[:10]是天[:13]是小时[:16]是分钟。rotation45防止时间标签重叠tight_layout避免标签被裁掉。提示如果data.csv只有from_user和to_user两列time_graph.py会拿到空列表画出来是空白图。这时要么补抓时间字段要么只跑网络图。5. 避坑与排查这套老代码最容易翻车的五个地方这套代码年代久远直接跑十有八九会撞上几个固定坑。下面五条是我实际拆这类项目时反复遇到的按「现象 → 原因 → 解决」记下来能省不少时间。现象一运行报SyntaxError: Missing parentheses in call to print。原因源码是 Python 2 写法print xxx在 Python 3 里非法。 解决装 Python 2.7 跑或者用2to3工具批量转换但转换后.pyc文件会失效得删掉重新生成。现象二登录一直失败提示账号密码错误但密码明明是对的。原因post_encode.py的编码方式和当前登录接口不匹配或者触发了验证码风控。 解决先确认编码逻辑再考虑风控。最省事的做法是跳过登录直接用仓库自带的data.csv做后续分析。现象三network_graph.py报module networkx has no attribute spring_layout或绘图空白。原因networkx版本过新部分 API 改名或移除或者matplotlib后端在无图形界面环境下无法渲染。 解决降级到networkx2.2并在脚本开头加matplotlib.use(Agg)强制用非交互后端。现象四CSV 读进来中文乱码节点名变成问号。原因Python 2 默认按 ASCII 读文件中文编码没声明。 解决打开文件时指定编码或在脚本头部加# -*- coding: utf-8 -*-读 CSV 时用codecs.open(path, encodingutf-8)。现象五图能画出来但节点挤成一团完全看不出结构。原因节点太多、spring_layout参数没调或者没有过滤低频节点。 解决先按度数过滤只保留转发次数超过阈值的节点再调大k和iterations让布局充分展开。6. 进阶玩法把转发图做成能读懂的传播分析跑通基础流程后这套代码真正的价值在于它能支撑更细的传播分析。我一般会做三件事找关键节点、看传播层级、对比不同微博的结构差异。找关键节点靠中心性指标。networkx内置了多种中心性计算度中心性看谁转发最多介数中心性看谁处在传播路径的咽喉位置。# 关键节点识别 import networkx as nx G build_graph(data.csv) deg nx.degree_centrality(G) # 度中心性 btw nx.betweenness_centrality(G) # 介数中心性 top_deg sorted(deg.items(), keylambda x: x[1], reverseTrue)[:10] top_btw sorted(btw.items(), keylambda x: x[1], reverseTrue)[:10] print(转发最多, top_deg) print(桥梁节点, top_btw)逻辑说明degree_centrality归一化后的度数值越高说明该用户直接转发关系越多是传播的「放大器」。betweenness_centrality衡量节点出现在多少条最短路径上值高说明它是不同转发簇之间的「桥梁」。参数上介数中心性计算复杂度高节点上千时会慢可以先过滤再算。看传播层级用 BFS。从源头节点出发做广度优先遍历每一层的节点数就是该跳的传播规模能直观看出信息是「一层就爆」还是「层层扩散」。# 传播层级分析 source 源头用户 # 换成实际源头节点 levels nx.single_source_shortest_path_length(G, source) from collections import Counter dist Counter(levels.values()) # 每层有多少节点 print(各跳传播规模, sorted(dist.items()))逻辑说明single_source_shortest_path_length返回从源头到每个节点的最短跳数Counter统计每跳的节点数量。参数上source必须是图里真实存在的节点否则报错如果图是有向的只能沿转发方向统计符合信息传播的实际方向。对比不同微博的结构差异可以把两张图的统计量放一起看指标单中心爆发型多中心扩散型最大度数极高中等介数集中度高低传播层级浅而宽深而窄典型场景大 V 转发话题自然发酵这套代码的边界也要说清楚它抓的是公开转发关系不涉及私信和粉丝关系时间图依赖数据里有时间字段老代码在新环境下需要做兼容处理。我自己的习惯是每次拿到这类老项目先只跑画图部分验证数据格式确认data.csv能读、图能出再回头折腾抓取。从那以后我每次拆这类压缩包都强制先看readme.md和data.csv的表头再决定从哪一段切入省下的调试时间比想象中多。希望帮到你。本文还有配套的精品资源点击获取