尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Django+Python构建网易云音乐排行榜数据分析系统

Django+Python构建网易云音乐排行榜数据分析系统 作为一名常年泡在技术社区、也带过不少毕业生做课题的老程序员我每年都会看到大量“看起来很美好做起来全是坑”的毕设题目。今天要聊的这个“基于Django大数据技术的Python网易云音乐排行榜数据分析系统”是我认为目前计算机类毕业设计里性价比非常高、也相当有区分度的一个方向。它几乎把所有核心技能点都串起来了Python爬虫、数据清洗、数据库设计、数据分析和可视化最后通过Web框架Django做成一个能看的项目demo写进简历、应付答辩都拿得出手。这几年“大数据”这个词被喊得有点滥但真正落到一个毕业生能独立完成、又能讲清楚技术细节的选题其实并不多。网易云音乐排行榜是典型的半结构化数据榜单本身变化快、评论情感丰富、用户行为数据维度多拿来练手非常合适。项目做完之后你不但能交出一套完整源码和文档还能从数据里挖掘出一些很有意思的结论比如不同时段榜单的更替规律、评论量和歌曲热度之间的关系等等。这篇文章把我实操验证过的一套完整方案写出来从环境搭建到爬虫、入库、分析、可视化再到Django整合尽量把每个环节的“为什么这么做”也讲清楚希望能帮你少走点弯路。1. 项目概述与整体设计思路1.1 这个系统到底做了什么先把这个项目到底要交付什么说清楚。整套系统简单来说就是一条数据流水线从网易云音乐平台获取排行榜相关数据经过清洗和标准化处理后存入本地数据库再用数据分析手段从不同维度进行统计分析最终通过Django搭建的Web界面把分析结果以图表、榜单、词云等形式展示出来。这里“排行榜数据”不是单指某一个榜单而是围绕排行榜衍生出来的多个维度的数据集合。实际做的时候我们会去采集新歌榜、热歌榜、飙升榜、原创榜等多个榜单的歌曲信息包括歌曲名称、歌手、排名、上榜天数、播放量如果有、评论数等字段。有精力的话还可以把热门评论一起爬下来做文本情感分析。我自己带的几个学弟学妹做完这个项目后普遍反馈是难度适中不存在完全做不出来的技术点但又没有简单到“水”的程度。从毕设答辩的角度来说评委会非常喜欢这种数据驱动型的项目因为它的每一个页面、每一个图表背后都有实际数据支撑而不是纯做界面展示。1.2 为什么用Django和Python这套技术栈很多人在选型时会纠结大数据分析用Java或者Scala不是更主流吗为什么这里要选Django我的回答是脱离应用场景谈技术栈就是耍流氓。这个项目的核心矛盾在于数据量远没到需要Hadoop、Spark、Flink这类分布式计算框架来处理的程度。网易云音乐排行榜即便把多个榜单的数据都抓下来加上历史数据积累通常也就是几万到几十万条的规模。这种量级的数据用Pandas处理起来是毫秒级到秒级的性能完全够用。引入重型的分布式大数据组件反而会让代码复杂度急剧上升部署和运行内存都会成为问题。对于本科毕设来说用Python的Pandas Django方案逻辑清晰、代码量可控、文档好写还能把“大数据处理”的思维方法体现出来比如数据的采集、清洗、转换、加载ETL流程以及基于统计学的分析手段。Django在这个项目里承担的是Web层和业务调度层的角色。它有几点很适合毕设场景自带Admin后台方便我们快速查看和维护数据表ORM模型非常成熟不需要自己写大量的SQL模板系统加上ECharts前端图表库能快速搭建出数据可视化页面内置的CSRF、XSS防护等安全机制也让系统在答辩演示时更“成熟”。Python这边核心库无非就是Requests、Pandas、NumPy、Matplotlib或PyECharts、Jieba。这些库生态成熟遇到问题网上能搜到大量案例对一个毕业设计来说这就是最好的保障。2. 数据获取与存储方案设计2.1 数据采集的整体方案数据采集是整个系统的上游也是很多同学第一个卡住的地方。我这里只说合规、可复现的方案通过网易云音乐Web端对外公开的接口来获取数据不涉及任何逆向破解、越权访问或绕过版权保护的手段。所有采集行为都限定在学习研究范围内控制请求频率设置合理的延迟尽量不给目标服务器造成压力。接口路径大致是https://music.163.com/api/search/get/web这类公开搜索接口以及通过页面请求获取榜单详情。实际操作中大家遇到最多的坑是接口参数里的加密字段比如params和encSecKey。这两个参数确实是用AES和RSA加密的但网上的开源教程里到处都是前端加密逻辑的分析照着走一遍就能构造出合法请求。不过我还是建议你优先直接用页面上公开的JSON接口比如/api/v6/playlist/detail?idxxxx这样的路径参数简单返回结构清晰定位到对应榜单的ID就能拿到歌曲列表。我实际用下来稳定的做法是先用浏览器开发者工具打开网易云音乐网页版找到目标榜单页面在Network面板里筛选XHR请求找到返回歌曲列表的接口。把这个接口的URL、请求头、Cookie等信息复制出来在Python的Requests脚本里模拟浏览器请求。解析返回的JSON数据提取出歌曲ID、名称、歌手、专辑、排名等字段。千万注意Headers里的User-Agent和Referer一定要伪装成正常的浏览器请求这是最基本的反爬规避手段。请求频率控制在每两次请求间隔3到5秒不要用并发去刷否则IP被临时封禁是大概率事件。2.2 数据表结构与存储选型存储选型方面这个项目用MySQL就足够了不需要上MongoDB或Elasticsearch。原因很简单数据结构相对规整排行榜、歌曲、歌手这些实体能用传统关系型数据库清晰建模Django的ORM对MySQL的支持最完善评审老师普遍更熟悉MySQL答辩时被问到数据库设计也更好回答。我设计的核心表结构大致是这样的song表歌曲ID主键、歌曲名称、歌手、专辑、时长、发布时间。ranklist表榜单类型新歌榜/热歌榜/飙升榜等、歌曲ID、排名、上榜日期、排名变化。comment表如果采集评论评论ID、歌曲ID、用户昵称、评论内容、点赞数、评论时间。这里有一个很容易忽略的点排行榜数据是和时间强相关的同一首歌在不同日期的排名是不同的。所以ranklist表必须把“日期”和“榜单类型”作为组合维度来设计不能简单只存一个当前排名。否则后期做趋势分析时你会发现数据缺失严重根本画不出持续变化曲线。存储过程的实现方式是爬虫脚本每天定时运行一次抓取当天各榜单快照存入数据库。这正好也体现在项目文档里可以作为“数据仓库的增量更新策略”来写非常符合大数据领域的思想。3. 数据分析与可视化实现3.1 分析维度与指标体系数据收集回来只是原料体现技术含量的地方在分析和展示环节。我当时定的分析维度主要有六个方向每个方向都能出一张图表页面撑起整个Web系统榜单特征分析计算各榜单Top10歌曲的歌手分布、上榜时长均值、排名变动幅度用柱状图和折线图展示。可以观察出热歌榜的“头部效应”是否明显新歌榜的“新陈代谢”速度有多快。歌曲热度与评论关系分析把歌曲播放量、排名和评论数做相关性分析用散点图加线性拟合线。通常会得到一个有意思的结论排名靠前的歌曲评论数不一定多有些歌评论区热闹但排名很一般这反映了用户的“沉默听歌”行为。榜单更替规律分析对连续多天的榜单数据做差分统计每天有多少首歌新进榜、多少首歌跌出榜计算平均在榜天数。这组数据能很好地体现“排行榜生命周期”的概念。歌手霸榜分析聚合歌手维度统计每个歌手在不同榜单的出现次数、最高排名、平均排名做成Top20歌手排行榜。评论情感分析用Jieba分词加简单的情感词典方法分析热门歌曲评论的正负情感比例用饼图和词云展示。这里不需要上大模型太重的模型放到毕设里反而容易被评委追问训练细节自己反而答不上来。时间维度分析如果你采集的数据时间跨度够长可以按周、按月统计榜单变化趋势看是否存在季节性规律。3.2 可视化大屏与图表实现可视化层面我强烈推荐用ECharts而不是Matplotlib直接生成图片。原因有两点ECharts是纯前端的交互式图表支持鼠标悬浮、缩放、点击跳转演示体验远好于静态图片它和Django模板的结合非常自然只需要在模板里引入JS文件通过Ajax请求JSON数据接口就能动态渲染图表。具体实现时我建议把系统主页面设计成一个“数据大屏”风格。顶部是汇总指标卡片比如“累计采集歌曲数”“今日上榜歌曲数”“平均评论数”“覆盖歌手数”中间一大块用折线图展示各榜单热度趋势下方用多个小面板展示歌手Top10、歌曲排名变化Top10、评论情感占比饼图等。这种设计视觉冲击力强答辩时往投影上一放先不提技术深度印象分就已经拉满了。Django后端需要提供一组只返回JSON数据的接口比如/api/rank/trend/返回榜单趋势数据/api/song/top/返回歌曲排名数据。前端页面用原生JavaScript或Vue的CDN模式请求这些接口拿数据后用ECharts渲染。有一点要特别注意接口返回的JSON字段命名要规范不要直接把数据库字段名抛给前端。比如数据库里是song_name前端需要的是name你应该在API层做一次映射。这不仅是代码规范问题也是答辩的加分项——“我在接口层做了数据规整让前后端解耦”。4. 系统功能模块与核心代码实现4.1 Django项目结构与核心模块一个结构清晰的Django项目应该是一眼就能看懂每个模块是干什么的。我推荐这样组织music_analysis/ ├── manage.py ├── requirements.txt ├── analysis/ # 数据分析相关模块 │ ├── crawler.py # 爬虫脚本 │ ├── cleaner.py # 数据清洗逻辑 │ ├── statistics.py # 统计聚合函数 │ └── sentiment.py # 情感分析 ├── dashboard/ # 可视化页面模块 │ ├── views.py # 视图函数 │ ├── urls.py │ └── api.py # JSON数据接口 ├── templates/ │ ├── dashboard.html # 数据大屏页面 │ ├── ranklist.html # 榜单详情页 │ └── song_detail.html # 歌曲详情页 ├── static/ │ ├── css/ │ ├── js/ │ └── echarts/ └── db.sqlite3这里我把爬虫和分析逻辑单独拆成一个analysis应用和Web展示的dashboard应用分开目的是保证“数据和展示”解耦。爬虫每天定时抓数据更新数据库Web应用只负责把数据库已有数据查出来、聚合、渲染到前端。这样任何一个环节出问题不会影响系统整体运行。核心的爬虫代码结构大致是这样import requests import time HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36, Referer: https://music.163.com/, Cookie: 你的合法会话Cookie } rank_list_map { 热歌榜: 3778678, 新歌榜: 3779629, 飙升榜: 19723756, 原创榜: 2884035, } def fetch_rank_list(rank_id): url fhttps://music.163.com/api/v6/playlist/detail?id{rank_id} resp requests.get(url, headersHEADERS, timeout10) json_data resp.json() tracks json_data[playlist][tracks] result [] for idx, track in enumerate(tracks): result.append({ rank: idx 1, song_id: track[id], name: track[name], artist: track[ar][0][name], album: track[al][name], duration: track[dt], }) return result def run(): for rank_name, rank_id in rank_list_map.items(): data fetch_rank_list(rank_id) save_to_database(rank_name, data) time.sleep(3)4.2 排行榜数据展示与交互功能Web端我设计了三个核心页面覆盖了用户从“看榜单”到“看分析”再到“看详情”的完整路径。榜单列表页展示当前数据库里的所有榜单类型每张榜单显示歌曲排名、歌曲名、歌手、专辑支持按日期筛选历史数据。这里背后其实是一个列表查询接口利用Django ORM的filter(datexxx)就能实现关键是页面上的分页要处理好用Django自带的分页器Paginator即可。数据大屏页这是整个项目的门面。进入页面后系统自动请求六个接口分别返回趋势数据、歌手排名、歌曲排名变化、评论情感占比、评论词云、汇总指标。页面每30秒自动刷新一次数据用JavaScript的setInterval加fetch实现。歌曲详情页点击榜单里的任意歌曲跳转到详情页展示该歌曲在不同日期的排名折线图、评论情感分析结果、歌词关键词词云。这个页面最考验数据组织的功力因为你要把多张表的数据关联起来。如果数据库设计得合理这一步会非常顺畅如果一开始没设计好到这里会疯狂写原生SQL效率极低。这里给一个视图函数的示例仅供参考from django.http import JsonResponse from analysis.models import Song, RankList from django.db.models import Avg, Count def api_rank_trend(request): 返回指定榜单近N天的排名趋势 days int(request.GET.get(days, 7)) rank_type request.GET.get(type, 热歌榜) data ( RankList.objects .filter(rank_typerank_type) .values(date) .annotate(avg_rankAvg(rank), song_countCount(song_id)) .order_by(-date)[:days] ) result { dates: [item[date].strftime(%m-%d) for item in data], avg_rank: [round(item[avg_rank], 2) for item in data], song_count: [item[song_count] for item in data], } return JsonResponse(result)前端ECharts渲染的关键代码也不复杂核心是在fetch到数据后调用chart.setOption更新配置。5. 常见问题与排查技巧实录5.1 数据采集中高频踩坑记录说实话这个项目90%的问题都集中在数据采集阶段。整理几个我见到最多的坑每个都是典型请求头缺失导致返回错误页面。表现是状态码200但返回的是HTML而非JSON根本原因通常是Referer或User-Agent没有设置。解决方法是把浏览器开发者工具里的标准请求头完整复制过来。接口参数不正确。网易的一些接口更新迭代比较快你网上下载的旧教程代码很可能已经失效。遇到这种情况不要硬调回到浏览器Network里看最新的真实请求长什么样以实际抓包为准。请求太频繁被封IP。这个问题最麻烦因为多半不是立刻被封而是请求几十次后突然失效。解决方案有两个一是每次请求后强制sleep(3)以上二是用代理池轮换IP。对于毕设来说第一种就够了代理池反而会增加复杂度和不稳定性。数据库重复数据。爬虫脚本重跑时会把同一天、同一首歌的排名重复插入。解决办法是在表设计时对(date, rank_type, song_id)三个字段加联合唯一约束插入时用get_or_create或update_or_create。5.2 大数据量场景下的性能优化墙上贴一句“大数据”的标签就得在性能上有点追求。数据量一旦积累到几十万条不做优化的话很多页面查询会明显变慢。我实测了几个有效的优化手段索引设计最关键。对ranklist表的date、rank_type、song_id三个字段建立联合索引对song表的song_name字段建立普通索引。这行操作能让查询速度提升好几倍。查询要避免N1问题。Django的ORM默认懒加载如果你在模板里循环访问关联表的字段会产生大量SQL查询。解决方法是使用select_related()或prefetch_related()一次性把关联数据取出来。这一步优化效果立竿见影一个页面可能从几十条SQL变成一条。聚合操作不要在前端做。前端拿到原始数据再排序、过滤不仅代码冗余而且性能差。所有聚合统计逻辑都放到后端SQL层面用Django的annotate和aggregate完成前端只负责渲染最终结果。这也是答辩时评委比较看重的点。5.3 系统部署与文档编写经验最后说一下部署和文档。毕设不是写完代码就结束了从“能跑”到“能演示、能答辩”还有一段路。我的经验是系统务必做到在答辩现场可以离线演示。数据都提前采集好存在本地库里页面和数据接口不要依赖外部网络否则现场网络一波动就尴尬了。部署环境不要追求花哨。Windows Python Django开发服务器是最稳的组合不需要上Nginx和Gunicorn那些是加分项不是必选项。你只需要保证答辩时用python manage.py runserver能启动浏览器能正常访问即可。文档里一定要画系统架构图和数据流程图。这不是形式主义而是帮助你在答辩时快速组织讲述逻辑。画图工具就用Visio或Draw.io导出图片放进论文里即可。有一个细节容易被忽视展示时要提前准备好至少两周的连续数据。只抓一天的数据很多趋势图、更替分析根本出不来效果。所以我建议从开题之后就开始定时跑爬虫到答辩前数据积累得越久能讲的故事就越丰富。不得不说这个题目虽然标着“网易云音乐”但真正做完之后你会意识到自己掌握的不是某一个音乐平台的爬取方法而是一整套大数据分析项目的通用流程。技术的核心逻辑是相通的不管数据来自哪里最后都要落到“采集—清洗—存储—分析—可视化—决策支持”这条主线上。我个人在几次实操里最大的体会是这种数据驱动型项目的价值就在于它能逼着你去思考每一个设计决策背后的理由为什么选MySQL不选MongoDB为什么用ECharts不用Matplotlib为什么排行榜表要加联合唯一约束……把这些“为什么”都吃透了项目答辩时基本上就不会被问倒。后面你完全可以把这个系统往其他领域迁移比如电商商品排行榜、影视热度榜甚至招聘网站职位热度分析技术架构不变只需要换掉数据源和分析指标又是一套新项目。这套东西的价值是会复利增长的。
返回列表