尧图精选

基于Python的网易云音乐歌单数据分析与可视化实战

🕒 发布时间:2026/10/1 6:11:55 📁 来源:尧图网络
简介这是一份面向高校学生与Python数据分析初学者的结课项目资料以网易云音乐歌单为分析对象完整呈现从数据获取到可视化呈现的全流程适合作为大学编程作业参考或数据分析入门练手案例。项目综合运用numpy、pandas、matplotlib、requests、jieba、wordcloud、squarify、bs4等第三方模块完成歌单数据的抓取与清洗并输出评论、收藏、播放、贡献、分布等数量图及词云最后给出歌单优化建议。压缩包共39个文件约10.53MB包含12个py源码、11个pyc编译文件、7张png图表、3个csv数据文件以及md说明、ttf字体、pdf报告等结构清晰便于复现与二次修改。目前已有3342人学习下载读者可借此掌握数据采集、清洗、可视化与词云生成的完整思路巩固Python语法与常用库的实战应用为后续数据分析学习打下基础。1. 从一份歌单 CSV 说起网易云音乐歌单分析系统到底在分析什么你手上有一份从网易云音乐导出的歌单 CSV字段大概长这样歌曲名、歌手、专辑、时长、播放量、收藏量、评论数、发行年份。看起来平平无奇但真正做过的人都知道这份表里藏着几个能直接决定分析成败的坑——时长字段可能是03:45这种字符串播放量可能是1.2万这种中文单位歌手字段可能塞了三个名字用斜杠隔开。把这些清洗干净再用 Python 做数据可视化就是「网易云音乐歌单分析系统」这个大学编程作业的核心工作。这个方向适合两类人一类是刚学完 Python 基础语法、想找一个完整项目练手的学生另一类是想用真实数据练 pandas 和 matplotlib 的转行者。它不需要爬虫数据可以手动导出或从公开数据集获取不需要数据库一台装了 Python 的电脑就能跑通全流程。下面按「数据怎么来 → 怎么清洗 → 怎么分析 → 怎么可视化 → 怎么避坑」的顺序把每个环节的参数和代码都落到可复现的程度。2. 数据获取与字段理解歌单 CSV 里到底有什么2.1 三种数据来源的取舍做歌单分析数据来源决定了后面所有工作的难度。常见做法有三种第一种是手动导出。网易云音乐网页版在歌单页面按 F12 打开开发者工具切到 Network 面板刷新页面后能找到返回歌单数据的接口响应把 JSON 复制出来存成文件。这种方式拿到的字段最全包含播放量、收藏量、评论数这些核心指标但需要手动操作适合数据量不大的作业场景。第二种是使用公开数据集。Kaggle 和国内一些数据竞赛平台上有整理好的网易云音乐歌单数据集字段已经结构化直接下载 CSV 就能用。缺点是字段可能不全比如缺少评论数或收藏量。第三种是自己写请求脚本批量获取。这种方式能拿到大量数据但涉及请求频率控制和接口稳定性问题对于编程作业来说性价比不高除非作业明确要求爬虫部分。我一般建议作业场景用第一种拿 3 到 5 个歌单、总共 200 到 500 首歌的数据就够了。数据量太大反而会让可视化图表变得拥挤分析结论也不一定更清晰。2.2 字段类型与清洗优先级拿到原始数据后先别急着画图。用 pandas 读进来执行df.info()和df.head(10)把每个字段的类型和前几行值看清楚。下面是一份典型的歌单数据结构字段名原始类型问题清洗后类型歌曲名object可能含空格和特殊符号object歌手object多人用/分隔object拆分后存列表时长object03:45格式int秒播放量object可能含万字int收藏量object可能含万字int评论数int可能有缺失值int发行年份object可能是2023-05-12int清洗顺序很重要先处理缺失值再处理类型转换最后处理异常值。顺序反了会出现转换报错比如对含万字的字符串直接调astype(int)会直接抛异常。import pandas as pd import numpy as np # 读取原始数据指定编码避免中文乱码 df pd.read_csv(playlist_raw.csv, encodingutf-8-sig) # 第一步查看缺失情况 print(df.isnull().sum()) # 第二步处理播放量中的万字 def parse_play_count(val): if pd.isna(val): return 0 val str(val).strip() if 万 in val: return int(float(val.replace(万, )) * 10000) return int(val) df[播放量] df[播放量].apply(parse_play_count) # 第三步时长字符串转秒数 def duration_to_seconds(val): if pd.isna(val): return 0 parts str(val).strip().split(:) if len(parts) 2: return int(parts[0]) * 60 int(parts[1]) return 0 df[时长_秒] df[时长].apply(duration_to_seconds) # 第四步发行年份提取 df[发行年份] pd.to_datetime(df[发行日期], errorscoerce).dt.year df[发行年份] df[发行年份].fillna(0).astype(int) print(df[[歌曲名, 播放量, 时长_秒, 发行年份]].head())这段代码的关键点在于parse_play_count函数。网易云音乐的播放量在页面上显示为1.2万这种格式直接读进来是字符串。函数先判断是否含万含则去掉后乘 10000不含则直接转整数。errorscoerce参数的作用是遇到无法解析的日期时返回NaT而不是报错后面用fillna(0)兜底。注意encodingutf-8-sig比utf-8多处理了一个 BOM 头Windows 下用 Excel 打开过的 CSV 经常带这个头不加的话第一列列名会多一个不可见字符。3. 用 pandas 做歌单特征分析从播放量分布到歌手热度3.1 描述性统计与分布分析数据清洗完之后第一步分析是看整体分布。播放量、收藏量、评论数这三个指标的分布形态直接决定了后面用什么图表。如果数据集中在低值区、少数歌曲极高那就是长尾分布用直方图要配合对数坐标否则大部分柱子挤在左边看不清。# 基础描述性统计 stats df[[播放量, 收藏量, 评论数, 时长_秒]].describe() print(stats) # 播放量分布分位数查看 percentiles [0.1, 0.25, 0.5, 0.75, 0.9, 0.95, 0.99] for p in percentiles: val df[播放量].quantile(p) print(f播放量 {int(p*100)}% 分位: {int(val)}) # 歌手出现频次 Top 15 artist_counts df[歌手].value_counts().head(15) print(artist_counts)describe()给出的是均值、标准差、四分位数。但播放量这种指标均值往往被少数爆款拉高中位数更能代表「典型歌曲」的水平。我一般会同时看均值和 50% 分位如果两者差距超过 3 倍就说明分布严重右偏后续可视化必须做处理。歌手频次统计有个细节如果一首歌有多个歌手value_counts()会把「周杰伦/方文山」当成一个整体。正确做法是先按/拆分再展开统计。# 拆分多歌手并统计 artist_series df[歌手].str.split(/).explode() artist_counts artist_series.str.strip().value_counts().head(15) print(artist_counts).str.split(/)把每个字符串按斜杠切成列表.explode()把列表展开成多行每个歌手占一行。这样统计出来的才是单个歌手的真实出现次数。3.2 交叉分析与相关性单字段统计只能看到表面交叉分析才能发现规律。比如「发行年份 vs 平均播放量」可以看出老歌和新歌的播放差异「时长区间 vs 评论数」可以看出短歌和长歌的互动差异。# 按发行年份分组看平均播放量 year_stats df[df[发行年份] 0].groupby(发行年份).agg( 歌曲数(歌曲名, count), 平均播放量(播放量, mean), 平均评论数(评论数, mean) ).reset_index() # 时长分桶 bins [0, 180, 240, 300, 600] labels [3分钟以内, 3-4分钟, 4-5分钟, 5分钟以上] df[时长区间] pd.cut(df[时长_秒], binsbins, labelslabels) duration_stats df.groupby(时长区间).agg( 歌曲数(歌曲名, count), 平均评论数(评论数, mean) ).reset_index() print(year_stats.tail(10)) print(duration_stats)pd.cut的分桶边界要根据实际数据调整。上面用的[0, 180, 240, 300, 600]对应 3 分钟、4 分钟、5 分钟这是流行歌曲的常见时长范围。如果歌单里古典乐多边界要往上调。相关性分析用df.corr()看数值字段之间的皮尔逊系数。播放量和收藏量的相关系数通常在 0.6 到 0.8 之间说明两者正相关但不完全同步——有些歌播放量高但收藏率低可能是短视频带火的口水歌。4. 数据可视化落地matplotlib 和 pyecharts 怎么选4.1 静态图表用 matplotlib 的五个必调参数matplotlib 是作业场景最稳妥的选择不依赖网络导出图片直接贴报告。但默认样式比较粗糙下面五个参数是每次都要调的import matplotlib.pyplot as plt import matplotlib # 中文字体设置Windows 用 SimHeiMac 用 Arial Unicode MS matplotlib.rcParams[font.sans-serif] [SimHei] matplotlib.rcParams[axes.unicode_minus] False # 负号正常显示 fig, axes plt.subplots(2, 2, figsize(14, 10)) # 图1播放量 Top 10 水平柱状图 top10 df.nlargest(10, 播放量)[[歌曲名, 播放量]] axes[0, 0].barh(top10[歌曲名], top10[播放量], color#e74c3c) axes[0, 0].set_title(播放量 Top 10, fontsize14) axes[0, 0].invert_yaxis() # 让第一名在最上面 # 图2发行年份分布 year_counts df[df[发行年份] 2000][发行年份].value_counts().sort_index() axes[0, 1].plot(year_counts.index, year_counts.values, markero, color#3498db) axes[0, 1].set_title(发行年份分布, fontsize14) axes[0, 1].set_xlabel(年份) axes[0, 1].set_ylabel(歌曲数) # 图3时长分布直方图 axes[1, 0].hist(df[时长_秒] / 60, bins20, color#2ecc71, edgecolorwhite) axes[1, 0].set_title(歌曲时长分布分钟, fontsize14) axes[1, 0].set_xlabel(时长分钟) # 图4播放量 vs 评论数散点图 axes[1, 1].scatter(df[播放量], df[评论数], alpha0.5, color#9b59b6) axes[1, 1].set_title(播放量 vs 评论数, fontsize14) axes[1, 1].set_xlabel(播放量) axes[1, 1].set_ylabel(评论数) plt.tight_layout() plt.savefig(playlist_analysis.png, dpi150, bbox_inchestight) plt.show()五个必调参数分别是font.sans-serif解决中文乱码、axes.unicode_minus解决负号显示、figsize控制画布大小、dpi控制导出清晰度、bbox_inchestight去掉多余白边。alpha0.5是散点图的透明度数据点密集时能看出重叠程度。invert_yaxis()是水平柱状图的常用操作因为 matplotlib 默认从下往上画不反转的话第一名在最下面阅读习惯上不自然。4.2 pyecharts 做交互式图表如果作业要求网页展示或者想要更现代的视觉效果pyecharts 是首选。它生成的 HTML 文件可以直接用浏览器打开支持鼠标悬停查看数值。from pyecharts.charts import Bar, Pie, Scatter from pyecharts import options as opts # 歌手歌曲数 Top 10 柱状图 artist_top10 artist_series.str.strip().value_counts().head(10) bar ( Bar() .add_xaxis(artist_top10.index.tolist()) .add_yaxis(歌曲数, artist_top10.values.tolist(), color#5470c6) .set_global_opts( title_optsopts.TitleOpts(title歌手歌曲数 Top 10), xaxis_optsopts.AxisOpts(axislabel_optsopts.LabelOpts(rotate30)), yaxis_optsopts.AxisOpts(name歌曲数) ) ) bar.render(artist_top10.html)rotate30是 x 轴标签旋转角度歌手名字长的时候必须加否则标签会重叠。render()输出的 HTML 文件用浏览器打开就能看到交互效果。matplotlib 和 pyecharts 的选择标准很简单要贴进 Word 报告就用 matplotlib要做网页展示就用 pyecharts。两者不冲突可以同时用。5. 避坑与排查歌单分析里最容易翻车的五个地方5.1 中文乱码图表里全是方框现象matplotlib 图表标题和轴标签显示为方框中文完全看不到。原因matplotlib 默认字体不含中文字形SimHei在部分 Linux 系统上也没有安装。解决先确认系统里有哪些中文字体用matplotlib.font_manager.findSystemFonts()列出所有字体路径找到含中文的字体名。Windows 用SimHeiMac 用Arial Unicode MSLinux 用WenQuanYi Micro Hei。如果都没有下载一个开源中文字体放到代码同目录用font_manager.FontProperties(fname字体文件路径)手动指定。5.2 播放量转换后数值不对现象1.2万转换后变成 12000 没问题但10万这种带加号的转换报错。原因网易云音乐部分歌曲播放量显示为10万加号导致int()转换失败。解决在parse_play_count函数里先去掉号再处理。更稳妥的做法是用正则提取数字部分import re def parse_play_count(val): if pd.isna(val): return 0 val str(val).strip().replace(, ) match re.search(r([\d.])(万?), val) if not match: return 0 num float(match.group(1)) if match.group(2) 万: num * 10000 return int(num)5.3 歌手拆分后统计结果翻倍现象拆分多歌手后总歌曲数比原始数据多。原因.explode()会把一行拆成多行一首歌有三个歌手就变成三行。如果后面用len(df)统计歌曲数结果会偏大。解决统计歌曲数时用原始df统计歌手频次时用拆分后的artist_series。两个变量分开维护不要混用。5.4 散点图数据点重叠看不清现象播放量和评论数的散点图大部分点挤在左下角右上角只有零星几个点。原因数据长尾分布少数爆款数值极大线性坐标下低值区被压缩。解决对 x 轴和 y 轴都取对数用axes[1, 1].set_xscale(log)和set_yscale(log)。取对数后分布会展开能看到更多细节。如果数据中有 0 值先加 1 再取对数避免报错。5.5 导出图片模糊现象savefig导出的 PNG 贴进 Word 后放大看很模糊。原因默认 dpi 是 100对于打印或高清展示不够。解决savefig时指定dpi150或dpi300。300 适合打印150 适合屏幕展示。同时加bbox_inchestight去掉白边避免图片周围有大片空白。6. 从作业到作品三个让分析报告加分的进阶技巧6.1 用词云展示歌单关键词歌单里的歌曲名和歌手名可以生成词云直观展示歌单的风格倾向。用wordcloud库配合jieba做中文分词import jieba from wordcloud import WordCloud # 把所有歌曲名拼接后分词 text .join(df[歌曲名].dropna().tolist()) words jieba.cut(text) word_str .join(words) wc WordCloud( font_pathSimHei.ttf, # 中文字体路径 width800, height400, background_colorwhite, max_words100 ) wc.generate(word_str) wc.to_file(wordcloud.png)font_path必须指定中文字体文件路径否则词云里全是方框。max_words100控制显示词数太多会拥挤。6.2 用 Flask 把分析结果做成网页如果作业要求展示系统可以用 Flask 把图表嵌到网页里。核心代码不超过 30 行from flask import Flask, render_template import pandas as pd app Flask(__name__) app.route(/) def index(): df pd.read_csv(playlist_cleaned.csv) top10 df.nlargest(10, 播放量)[[歌曲名, 播放量]].to_dict(records) return render_template(index.html, top10top10) if __name__ __main__: app.run(debugTrue)to_dict(records)把 DataFrame 转成字典列表模板里用{% for item in top10 %}循环渲染。debugTrue在开发阶段开启热重载改代码不用重启。6.3 分析结论要落到具体数字很多作业的可视化做得漂亮但结论部分只写「播放量最高的是某某歌曲」这不够。好的结论要带数字和对比播放量 Top 10 的歌曲平均播放量是 50 万而全歌单中位数是 3 万差距 16 倍3 到 4 分钟的歌占比 62%是歌单的绝对主力时长区间。我自己的习惯是每张图下面配一句话结论结论里至少包含一个具体数字和一个对比关系。这样报告读起来才有信息量而不是图表的重复描述。做这个方向最大的体会是数据清洗花的时间永远比画图多。我第一版跑通全流程用了两天其中一天半在调parse_play_count函数和字体配置。但把清洗逻辑写成函数之后换一个歌单只需要改文件路径就能复用。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →