先说结论:短视频用户兴趣分析这类题目,在目前的毕业设计里属于“性价比”很高的一档。它不像纯推荐算法那样需要深厚的数学功底,也不像纯管理系统那样缺乏亮点,而是踩在了数据采集、数据清洗、统计分析、可视化展示、Web开发这个完整链路交汇点上。你只要把每个环节扎扎实实落地,答辩时能讲清楚“数据从哪来、指标怎么算、图表怎么画、结论怎么用”,拿高分是大概率事件。这篇文章我就按自己做这类项目的完整流程,把思路、技术选型、实现细节、答辩要点和踩坑记录一次说清楚。
1. 项目整体设计与技术选型拆解
1.1 为什么选Django做后端,而不是Flask或Spring Boot
做毕设项目,技术栈选型的核心逻辑不是“哪个最流行”,而是“哪个最适合在有限时间内稳定交付”。我见过太多同学在选型阶段纠结了半个月,最后用了一个自己都驾驭不了的技术组合,光环境配置就耗费了大量时间。
短视频用户兴趣分析这个项目,后端候选主要是Django、Flask、Spring Boot三选一。Flask轻量灵活,但很多功能(后台管理、ORM、表单校验、认证体系)需要自己组装,容易出现“框架太薄、代码全靠堆”的局面。Spring Boot在企业级开发里确实是主流,但Java体系的学习成本、配置复杂度和最终的部署体积,放在毕设答辩场景里都属于“不必要的负担”。
Django的优势在于“全家桶”特性:自带Admin后台、强大的ORM、完善的模板系统、内置的认证和权限管理、迁移机制等。对毕设而言,Admin后台可以直接拿来管理采集到的数据、查看用户反馈、维护兴趣标签字典,省掉大量重复的CRUD代码。ORM让你不用手写复杂SQL也能完成多表关联查询和聚合统计,新手不容易踩SQL语法坑。模板系统配合数据可视化库,可以在Django的MTV架构里顺滑地完成页面渲染,不需要额外搭前后端分离工程。
从答辩角度讲,Django的MTV架构本身就很容易拆成“模型层—视图层—模板层”来讲,配合一份完整的技术架构图,老师能非常直观地看出你的设计思路。对比Flask的“一切从零开始”和Spring Boot的“过度工程化”,Django是“够用且不凑合”的最佳平衡点。
1.2 技术架构全景:从数据采集到可视化闭环
整套系统的链路拆开看是这样的:
短视频平台数据采集 → 数据清洗与预处理 → MySQL/PostgreSQL存储 → Django ORM模型设计 → 数据分析指标计算 → ECharts数据可视化 → Web端交互展示 → 用户画像与兴趣标签输出这里每一个环节都可以单独拿出来做“亮点”。数据采集环节展示爬虫设计能力,预处理环节展示数据清洗能力,分析环节展示统计思维,可视化环节展示前端交互能力。整套链路完整度高,每一层都有可展示的成果。
我见过有同学只做“数据分析+可视化展示”,数据是自己造出来的假数据。这种项目最大的问题是答辩时经不住追问——“你的数据哪来的?”“你这些结论的置信度怎么评估?”一问就卡壳。所以哪怕只采集一小部分真实数据,也好过全量造假。
选型上,数据库我用的是MySQL 8.0,存储过程简单直接,配合Django ORM查询效率足够。如果机器配置低,SQLite也能跑,但容量和并发性能要打折。可视化库选择了ECharts,这套开源图表库在毕设场景里几乎是最优解,文档全、图表类型丰富、社区案例多,基本你是想得到什么图就有什么图。交互上用一个ECharts的按需打包版本,如果项目规模不大,直接用CDN引入然后按需注册组件,效果已经很好了。
1.3 核心功能模块划分
模块划分直接对应到工作量分配,一般有五个核心模块:
- 数据采集模块:负责从短视频平台获取用户行为数据,包括用户基本信息、视频属性、观看记录、点赞评论转发数据等。
- 数据预处理模块:清洗无效数据、去重、补缺失值,把原始数据转换成可分析的标准化格式。
- 数据分析模块:计算用户兴趣画像所需的核心指标,包括内容类别偏好、活跃时间段、互动率、完播率等。
- 可视化展示模块:用ECharts生成词云、柱状图、饼图、折线图、热力图、雷达图等,直观展示分析结果。
- 用户兴趣画像模块:基于分析结果给用户打标签,输出《用户兴趣画像报告》文档,具备完整的阅读和导出价值。
这几个模块串起来,就是一个“数据—信息—知识”的完整链条。答辩时你就能讲清楚:每个模块为什么存在、数据是怎么在模块之间流转的、最终产出了什么。
2. 数据采集与预处理的实操细节
2.1 数据采集策略:合法合规且技术可行
数据采集是很多同学心里发怵的环节,总觉得自己要去“爬”某个大平台,风险高、技术门槛也高。但实际上,毕设场景里做数据采集,思路应该是“小而精”,不是“大而全”。
我当时的做法是通过公开数据渠道和开放接口采集模拟行为数据,再用Python脚本对数据做增强处理。合法合规是底线,即使在自己机器上报测试,也要注意合规边界。实际操作上,我先是整理了一份“种子视频特征表”,包含视频ID、标题、分类标签、发布时间、时长等基础信息,然后编写模拟用户行为生成器,随机生成不同用户对视频的“观看时长、点赞、评论、收藏、转发”等行为数据。
这里要强调的是,即使使用模拟数据,数据结构设计也要严格对标真实业务场景。你生成的每条行为数据至少包含:用户ID、视频ID、行为类型、行为时间戳、停留时长等字段。这样的数据训练出来的分析逻辑,在毕业设计答辩中是能够自洽的;未来如果有真实的合规数据源,只需要把数据源接入点替换掉,分析流程完全复用。
2.2 数据清洗的关键操作
数据预处理是整个项目里最容易“翻车”的环节,很多同学直接跳过清洗,把原始数据丢进数据库就开始分析。结果就是统计出来的指标严重失真,可视化图表看起来很怪,但又不知道问题出在哪。清洗环节踩过的几个重点坑:
第一是缺失值处理。一张表里某个用户没有点赞记录,不能简单填0,因为“未点赞”和“点赞数为0”在业务语义上并不等价。我的处理思路是:对于数值型字段,缺失值用中位数或众数填充;对于行为型字段,缺失视为“无该操作”,单独标记;对于核心分析字段,确认无法补齐的直接删除该条记录。
第二是异常值过滤。短视频场景里,观看时长大于视频本身时长、同IP下账号行为完全一致、互动频率超过合理阈值,都属于典型的异常数据。我写了一个规则引擎,对这些异常做拦截并标记“人工复核”。这里不推荐直接用标准差法一刀切,因为短视频数据的分布本身就不均匀,长尾特征非常明显,基于业务规则去过滤比纯统计学方法更可靠。
第三是时间字段规范化。不同接口返回的时间戳格式五花八门,我统一转成标准时间戳存储,同时冗余一个可读的datetime字段,方便后续做分时分析。这个操作看起来简单,但如果不做,后续基于时间维度的可视化会出很大问题。
2.3 用户兴趣模型的构建方法
数据清洗完,最核心的部分就是“怎么定义用户兴趣”。我在这个项目里用的方法是结合显式反馈和隐式反馈的混合策略。
显式反馈就是用户的主动行为:点赞、收藏、转发、评论、关注。这些行为权重应该区别对待,不能一概而论。我的权重设计参考了行业通用做法并结合自己的校验:
浏览行为权重=0.3,点赞权重=0.5,评论权重=0.6,收藏权重=0.8,转发权重=0.9为什么这么设?因为浏览是被动接收信息,点赞是轻度认可,评论是表达了观点,收藏是“我以后还要看”,转发是“我希望别人也看到”。层层递进,代表用户对内容类型的认可程度逐步加深。
隐式反馈则包括观看时长、完播比例、停留时长、滑动速度等。观看时长占比高,说明内容对用户的吸引力强;看几秒就划走,说明内容与用户兴趣匹配度差。我最终把每个用户的兴趣得分算成:
兴趣得分 = 类别基础热度 × 显式行为权重加权和 × 完播率修正系数这个公式不算复杂,但可解释性极强,论文里可以展开写好几页,答辩时也能理直气壮。有了每个用户的兴趣得分,按分数排序取Top 3类别,就是该用户的兴趣标签。
3. Django核心实现与数据可视化方案
3.1 Django模型设计与ORM操作
模型设计直接决定了后期分析的效率,这一层建议多花时间想清楚,比后期改表结构省力得多。
我设计的模型按三大主结构划分:
# 用户基础信息表 class UserProfile(models.Model): user_id = models.CharField(max_length=64, primary_key=True) age = models.IntegerField(null=True, blank=True) gender = models.CharField(max_length=10, null=True, blank=True) region = models.CharField(max_length=100, null=True, blank=True) register_time = models.DateTimeField(null=True, blank=True) # 视频内容属性表 class VideoContent(models.Model): video_id = models.CharField(max_length=64, primary_key=True) title = models.CharField(max_length=255) category = models.CharField(max_length=50) duration = models.FloatField() publish_time = models.DateTimeField() tag_list = models.CharField(max_length=255) # 用户行为记录表 class UserBehavior(models.Model): id = models.AutoField(primary_key=True) user = models.ForeignKey(UserProfile, on_delete=models.CASCADE) video = models.ForeignKey(VideoContent, on_delete=models.CASCADE) action_type = models.CharField(max_length=20) action_time = models.DateTimeField() watch_seconds = models.FloatField()三个表的设计遵循范式化思路:行为记录通过外键关联用户与视频,分析时用Django ORM的聚合函数就能高效完成。这套设计的好处是逻辑层次清楚,表之间关系明确,后续如果想扩展“搜索记录”“分享记录”等新行为类型,只需要在行为表里加一条action_type,不用改动表结构。
ORM查询的优势在这里体现得很充分。比如统计每个视频类别的平均完播率,一条链式查询就完成:
from django.db.models import F, Avg avg_completion = UserBehavior.objects.filter( action_type='view' ).annotate( completion_ratio=F('watch_seconds') / F('video__duration') ).values( 'video__category' ).annotate( avg_completion_ratio=Avg('completion_ratio') ).order_by('-avg_completion_ratio')3.2 数据分析指标的计算逻辑
可视化图表背后全靠指标支撑,指标的定义决定了图表的业务解释力。我梳理了五个核心指标,每个指标都对应一种可视化表达:
用户活跃时段分布:按小时统计行为量,用热力图展示。这里的主逻辑是对action_time做hour提取,再按周几聚合,就能同时看“周内相比”和“日内趋势”。
内容类别偏好占比:基于兴趣得分加权统计,用饼图或玫瑰图展示。这里要注意“偏好”和“观看量”的区别——用户看某个类别最多,不代表他最感兴趣,有可能是该类内容供给量大,算法推得多。所以用兴趣得分而非观看量做占比,结论更准确。
不同类别视频互动率分布:互动率定义为“点赞+评论+收藏+转发”除以曝光或播放量,用柱状图对比。短视频领域互动率一般在3%-5%,但不同内容品类差异极大,知识类视频互动率高但播放量低,娱乐类反之。所以这里建议同时展示播放量和互动率,双Y轴对比,能讲出更多故事。
用户兴趣词云:从用户感兴趣的视频标签字段中提取关键词,统计词频,用词云展示。这个做起来不难,但视觉效果冲击力很强,适合放在演示首页。
特朗普式还有用户兴趣画像雷达图:选取用户在几个主要兴趣维度上的得分,用雷达图展示用户的兴趣轮廓。这个图在答辩时是杀手锏,一眼看出“这个用户是偏搞笑幽默还是偏知识学习型”,直观又有说服力。
3.3 数据可视化落地:ECharts与Django集成
ECharts与Django集成的方式很简单:Django视图函数从数据库读出统计结果,转成JSON格式,传递到模板页面,前端用JavaScript接收JSON并渲染图表。
比如活跃时段热力图的核心逻辑:
def user_activity_heatmap(request): results = UserBehavior.objects.filter( action_type='view' ).annotate( hour=ExtractHour('action_time'), weekday=ExtractWeekday('action_time') ).values('hour', 'weekday').annotate( count=Count('id') ) heatmap_data = [[item['weekday'], item['hour'], item['count']] for item in results] return JsonResponse({'data': heatmap_data})前端配合ECharts的heatmap系列,10分钟就能渲染出一个漂亮的“星期-小时活跃度热力图”,而且工具库自带视觉映射,颜色深浅直接从白色渐变到深红色,不需要额外调色。
这里分享一个实战小技巧:ECharts图表如果直接在页面底部渲染,首次加载时会有一个“闪烁”的效果,影响演示观感。建议在Django模板中加入一个小的延迟渲染控制,等DOM结构完全加载完再初始化图表,或者用前端框架的mounted生命周期钩子来控制。另一种做法是把图表初始化代码放到document.ready中执行,稳定性最好。
3.4 词云生成的踩坑与优化
词云是我在这个项目里觉得最有趣也最容易踩坑的部分。最开始我用的是Python的wordcloud库生成图片,然后直接嵌入页面,效果很一般——中文字体渲染出来全是方块。
问题出在字体路径上。wordcloud库默认字体不支持中文,需要手动指定一个中文字体文件。解决方法是:
from wordcloud import WordCloud import jieba # 先用结巴分词切词 word_list = jieba.cut(' '.join(tag_list)) result = ' '.join(word_list) wc = WordCloud( font_path='/usr/share/fonts/truetype/wqy/wqy-microhei.ttc', width=800, height=600, background_color='white' ).generate(result) wc.to_file('wordcloud.png')后来我又换了一种思路:用前端词云库实现,数据传到浏览器端,实现“鼠标悬浮显示词频”的交互效果,答辩演示时加分不少。两种方案对比,后端生成图片简单但交互弱,前端渲染交互丰富但开发量略大。我的建议是:优先做后端方案,功能先跑通;如果时间充裕,再加前端交互版作为加分项。
3.5 用户画像报告生成
单纯在网页上展示图表还不够有“项目完成感”,我还加了一个功能:根据分析结果自动生成《用户兴趣画像报告》。
具体逻辑是:选定一个用户ID,系统调出该用户的行为记录,分析其Top3兴趣类别、平均观看时长、活跃时段、最喜欢的视频标签,然后写一个函数把这些结论拼接成结构化文本,最终输出报告页面。报告里有雷达图展示用户的多元兴趣结构,有条形图对比该用户与全部用户平均行为的偏离情况。
这个功能实现难度不高,但展示效果拔群,尤其适合答辩时“演示完整业务闭环”——从输入用户ID到输出一份完整画像报告,整个过程一气呵成,完整性直接拉满。
4. 毕设文档写作与答辩演示的经验心得
4.1 毕业论文的结构设计与写作节奏
很多同学技术实现做得不错,论文却写得一塌糊涂,最后答辩被批“说不清楚”。论文写作的节奏应该跟项目开发同步进行,不要等到代码全部写完再开始动笔。
我建议的章节结构:
- 绪论:研究背景、国内外现状、研究内容与意义。
- 相关技术介绍:Django框架、MySQL、ECharts、数据采集技术。技术介绍别写教科书式科普,而是要结合你的项目场景,说明“为什么选择它”。
- 系统需求分析:功能性需求、非功能性需求、可行性分析。
- 系统总体设计:架构图、功能模块划分、流程图、数据库E-R图设计。
- 系统详细设计与实现:这一章是重点,按功能模块逐一写,配核心代码片段和关键逻辑说明。
- 系统测试:功能测试、性能测试、测试用例表格。
- 总结与展望:写得诚恳即可,别吹太大。
写作过程中,时序图和E-R图能用工具自动生成的尽量自动生成,比如用Django的反向工程插件把模型直接导出为图,省时省力还准确。
4.2 答辩演示的“故事线”设计
答辩演示本质上是一次“技术叙事”,你需要让评委在10-15分钟内快速理解“你做了什么、为什么这么做、效果如何”。我建议按照三级递进设计演示主线:
第一层讲问题:短视频平台的信息茧房问题,用户兴趣分析可以帮助理解用户画像,实现个性化内容推荐,平台也能优化内容分发策略。
第二层讲方案:用数据采集拿到行为数据,清洗后入库,设计兴趣得分模型,建立用户画像体系,通过可视化系统呈现分析结果。
第三层讲创新:混合使用显式反馈和隐式反馈、多维度画像标签体系、自动化报告生成功能,这三点已经足够撑起一个“工作亮点”章节。
现场演示之前务必准备好一份“备用数据包”。答辩使用的电脑环境不比自己的开发机,数据库里可能没有你本地的数据,如果演示环节遇到数据问题,还要现场调,就很尴尬。我习惯在答辩前一天把数据导出到SQL文件,演示当天导入到答辩机器,确保数据库里有假数据兜底。顺带检查数据可视化组件的CDN是否可用,最好关闭浏览器缓存,防止演示时加载异常。
4.3 一份能打动评委的“亮点说明”
答辩时评委最怕听到的是“这个项目我参考了网上的开源项目,改了点东西”,最想听到的是“这个设计是我在原方案基础上做的改进,理由是……”。所以一定要有一条“亮点主线”贯穿整个答辩。
我总结的加分点公式是:明确的业务痛点 + 合理的技术选型 + 可解释的分析模型 + 稳定的系统表现 + 诚实的问题反思。你不需要设计一个多复杂的算法,但你要能清楚地解释:现有方法有什么不足,你的方法怎么弥补,实验结果如何证明你的方法更好。
比如兴趣得分权重设计,当评委问“为什么浏览权重比点赞低”,你可以回答“浏览是被动行为,点赞是主动表达,主动表达的信号强度更高”,这比单纯说“我参考了别人的权重设置”要有说服力得多。
5. 常见工程问题与排查技巧实录
5.1 Django迁移冲突与数据库版本兼容问题
开发中经常遇到的问题是模型改了之后makemigrations报冲突或fail。多发生在多人协作、模型文件乱改、数据库已有旧数据的场景下。
我的经验是:如果项目还在早期开发阶段(还没写什么关键数据),直接删掉migrations目录里除了__init__.py之外的文件,同时删掉数据库里django_migrations表的相关记录,然后重新执行:
python manage.py makemigrations python manage.py migrate如果已经有关键数据不能丢,那就选择另一个策略:手动编辑迁移文件,把冲突的地方改正,或者新建一个空迁移文件,用RunPython操作数据。
5.2 ECharts图表在Django模板中渲染失败
图表渲染失败最典型的原因是模板变量和JavaScript变量发生冲突。Django模板引擎用双花括号{{ }}解析变量,而ECharts的配置项里也有不少{{ }}结构,两者混在一起模板会报错。
解决方法有几种,要么把图表数据直接以JSON格式嵌入模板并用safe过滤器渲染,要么把JavaScript代码独立到一个.js文件中,通过接口请求数据,避免模板和JS的数据变量混淆。我强烈建议用第二种方案,因为前后端代码完全解耦,项目后续维护起来也更顺手。
另一个排查点是:ECharts的图形容器必须显式设置高度,默认高度是0,图表渲染出来是空白。在CSS中为图表容器设置height: 600px;,问题立即消失。
5.3 中文乱码问题
Django + MySQL的中文乱码问题本质上是一个字符集贯穿链的问题,从数据库级别到表结构级别到连接串,每一层都要对齐。我的统一解决方案是:数据库字符集用utf8mb4,表结构也显式指定utf8mb4,连接串加charset='utf8mb4'参数。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'shortvideo_db', 'USER': 'root', 'PASSWORD': 'your_password', 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': {'charset': 'utf8mb4'}, } }如果你遇到“数据库里看到中文正常,但页面上显示问号”的情况,多半是连接层字符集不对。在OPTIONS里加上charset参数,重启服务即可解决。
5.4 性能优化:大数据量下的查询卡顿
当行为表数据量涨到一定量级,会发现页面加载越来越慢。最直接的优化是给外键字段加索引。Django默认会给外键加索引,但如果你用CharField做主键或频繁查询的字段,要记得增加db_index=True。
进一步可以做查询缓存。用Django的缓存框架,将高频统计结果缓存5分钟,在数据量没有明显变化时大幅减少数据库压力。对于毕设级别的并发量,加上缓存之后性能问题基本消失。
最后再用一个“夜里跑批”的思路:核心统计指标不要每次页面请求时实时计算,而是由后台定时任务每天凌晨执行一次,把统计结果写入单独的汇总表。页面访问时直接查汇总表,速度能提升几十倍。这个设计不止是对毕设,在实际工作场景里也是高频做法,值得写进论文。
5.5 环境迁移时的依赖管理
换电脑或者部署到实验室服务器时,最容易翻车的就是依赖包版本不一致。我在项目根目录维护了一份requirements.txt,每次操作前都会更新:
pip freeze > requirements.txt装环境时用:
pip install -r requirements.txt如果你的开发环境是Python 3.10,而目标机是3.7,记得检查一下高版本语法是否兼容。比较省事的办法是在项目里用虚拟环境,并且把Python版本写进文档。我在实际部署中还经常遇到mysqlclient编译失败的问题,Windows上尤其明显。解决方案是直接安装预编译的whl包,比本地编译稳定得多。
6. 一条龙定制服务避坑指南
这个标题里提到了“一条龙定制”,市场上确实有不少做毕设源码定制服务的个人或工作室,质量参差不齐。如果你选择走定制这条路线,有几点经验值得留意。
第一是价格异常低于市场水平的,大概率是“卖代码”而不是“做项目”。真正的毕设定制需要理解你的任务书、帮你看重论文查重、配合你调整功能,服务周期一般在几周到一个月。如果对方报价低到离谱,你要警惕代码复用度太高导致答辩被识别出雷同。
第二是交付清单必须白纸黑字明确。一套完整的定制服务一般包含:可运行源码、数据库SQL文件、环境部署文档、毕业论文文档、答辩PPT、操作演示录制。尤其是数据库文件,很多同学拿到代码后因为数据库数据缺失,项目根本跑不起来。
第三是需求沟通时,尽量自己先把任务书里的功能点列成清单,再让定制方逐条反馈可行性。这样做的好处是后期验收时有明确的参考依据,也能降低“需求理解错位”的概率。
自己动手做的过程中如果卡住了,可以先放一放,隔几小时再来看。很多问题其实是思路绕进去了,而不是真的解决不了。
做这类项目最大的收获,不是最后那个分数,而是完整走了一遍“从需求到设计、从编码到测试、从写作到答辩”的项目生命周期。我在做完之后,明显感觉自己对Web开发全栈链路的理解比以前零散写几个小Demo要通透得多。尤其是数据处理那一环,从清洗到建模到可视化,每一步都踩过坑、填过坑,面试时聊起项目来底气都不一样。这套思路和流程,你照着走一遍,不仅能顺利毕业,还能真正学到东西。