☰
小说推荐系统毕业设计实战:从爬虫到Django+Vue全栈实现
2026/10/15 7:18:43 网站建设 项目流程

最近有同学来问小说推荐系统这个毕业设计选题怎么做,问题基本都集中在几个地方:爬虫数据哪里来、推荐算法怎么选型、可视化要画什么图、前后端怎么串起来。说实话,这个题目的信息量比表面上看起来大得多,它同时踩中了算法、工程、数据、展示四个维度——这恰恰是它适合做毕业设计的原因。

这篇就顺着一个完整的项目脉络来写,从前期的选题定位、数据采集,到Django后端建模、推荐算法落地,再到Vue.js前端和可视化看板,最后讲讲联调、部署和答辩交付那些最容易翻车的细节。不管你是正在准备开题,还是已经写完了一半在补文档,这篇文章都值得你反复翻一翻。

1. 从"普通管理页面"到小说推荐系统:选题的价值在哪

每年毕业设计里都不缺图书管理系统、商品管理系统这类CRUD项目。它们不是说没用,而是在技术含量上太容易一眼看穿:无非是后端接数据库做增删改查,前端写几个表格页面。评阅老师翻完文档,问两句"你这个查询条件怎么设计的""并发上来怎么办",整个项目的水分就全挤出来了。小说推荐系统之所以值得做,是因为它的题目里藏着一条完整的数据价值链路:采集数据、清洗入库、算法加工、前端呈现。每一环都能独立拿出来谈技术深度,又不是各做各的,最终通过"推荐"这一个核心功能把它们拧成一股绳。

1.1 评阅老师愿意看到的项目闭环

一个好的毕设题目,评阅人最在意的是"完整性"和"工作量"是不是真实的。小说推荐系统的天然优势在于,它自带了从数据到展示的闭环。爬虫部分贡献了数据采集和清洗的能力,Django后端贡献了数据建模、接口设计和推荐算法实现,Vue.js前端贡献了SPA交互体验和数据可视化。

这套结构在答辩时特别好讲,因为它符合一个非常朴素的故事线:先有数据,再有计算,最后有呈现。老师问"你的推荐依据是什么",你可以直接打开可视化看板,指着小说分类占比和热度趋势说,算法是基于这些行为数据算出来的。这样所有模块都互相支撑,不是东拼西凑的几个功能堆叠。

1.2 Django + Vue.js 的组合到底合适在哪

选型这件事,毕业设计里"求稳"比"求新"更重要。Django 和 Vue.js 是久经考验的组合,各自的能力边界非常清晰。

Django 这边负责三件事:ORM 数据模型、RESTful 接口、后台任务。它是全栈框架里对新手最友好的之一,Admin 后台可以直接用来管理爬虫采集结果,省掉不少调试精力。Vue.js 这边负责前端组件化、状态管理和图表展示。相比后端渲染模板的方式,前后端分离后可以明显感受到接口调试的便利,而且 Vue 单文件组件的写法对代码量比较大的可视化页面来说,维护起来也舒服很多。

组合的另一个好处是生态成熟。Django REST Framework 提供现成的序列化和权限控制,SimpleJWT 管登录鉴权;Vue 这边 Element Plus 或者 Vant 直接提供卡片、表格、弹窗组件。你不需要也不应该在毕设阶段去折腾冷门框架,因为时间应该花在业务逻辑和数据质量上,而不是给框架本身填坑。

1.3 第一版必须先砍掉这些伪需求

很多同学拿到题目会陷入功能膨胀,觉得既然叫推荐系统,那用户评论、章节点赞、阅读进度同步、小说订阅通通都要。我的建议很直接:第一版只做四个核心页面,一个推荐首页,一个分类列表,一个小说详情,一个可视化看板,外加用户登录和收藏记录。这套功能已经足够支撑一篇合格的毕业论文了。

评论功能看着简单,实际上要处理敏感词、排序、楼中楼、分页,工作量和推荐算法不相上下。阅读进度同步则需要一套完整的前后端状态管理。这些功能在毕业设计的周期里性价比极低,一旦做进去,大概率会吃掉你调算法的时间。先砍掉它们,不是逃避工作量,而是把有限的精力集中在项目的核心价值上。

2. 数据是命根子:学会有边界地写小说爬虫

推荐系统没有数据就是空中楼阁。选小说这个领域有个客观优势:公开的排行榜、分类页、书籍详情页非常多,结构化程度也高,书名、作者、分类、简介、字数、评分、点击量这些字段几乎都是现成的。比爬那些需要登录才能看的数据要省心得多。

我先说一句容易被忽略的话:爬虫的代码实现只占一半工作量,另一半是对目标站点结构的分析和对采集数据的清洗。

2.1 字段规划和数据源的合规边界

动手写代码之前,先把要抓的字段定死。我常用的字段清单是:

字段说明推荐系统里的用途
书名唯一标识的一部分展示、去重
作者作者名内容相似度计算
分类玄幻、都市、历史等分类筛选、占比统计
简介一段文本描述关键词提取、词云
字数正文字数总量热度分析和筛选
状态连载中 / 已完结列表筛选项
评分站方评分热门推荐权重
封面图片链接前端展示
点击量站方点击数据热度排序、分析维度

关于合规,毕设阶段的爬虫只做两件事:抓公开可访问的数据,控制合理频率。不要碰需要登录才能看的内容,不要去对抗反爬验证,也不要在论文里写任何钻空子的话。答辩时老师问起来,标准答案就是"数据来源为公开排行榜页面,采集间隔控制在数秒以上,仅用于学术研究"。这既是保护自己,也是让项目站得住脚。

2.2 从列表页到数据库的四步流程

爬虫的基本工作流看起来简单,但每一步都有坑。我以 requests + BeautifulSoup 的组合为例,讲一下完整链路。

第一步是请求列表页。几乎所有的榜单页都有分页,URL 规律一般很容易找到。请求的时候一定要带上 User-Agent,最好准备一个小列表随机切换,不然很多站点会直接给你返回一个验证页。

import requests import random import time UA_POOL = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Safari/605.1.15", ] def get_page(url): session = requests.Session() session.headers.update({ "User-Agent": random.choice(UA_POOL), "Accept": "text/html,application/xhtml+xml", }) resp = session.get(url, timeout=10) resp.raise_for_status() return resp.text

第二步是解析列表,拿到每本书的详情页链接。BeautifulSoup 的选择器要写准,先拿一个页面练手,确定列表项都在哪个节点下面。用浏览器开发者工具检查元素是最快的定位方式,别上来就猜 class 名。

第三步是请求详情页,解析封面、简介、字数、评分这些字段。这里要提醒一句:详情页的字段往往有缺失,比如老书没有评分、新书没有字数,解析时一律用默认值兜底,不要因为一个字段缺失就整个跳过这本书。

第四步是清洗入库。直接用 Django 的 ORM 在爬虫脚本里建模型,每抓完一本书就执行一次 get_or_create。数据库里加一个唯一约束(书名 + 作者),天然避免了重复采集。

# 伪代码:爬虫脚本中直接使用 Django ORM from novels.models import Novel, Category def save_novel(item): category, _ = Category.objects.get_or_create(name=item["category"]) defaults = { "intro": item.get("intro", ""), "words": int(item.get("words", 0)), "score": float(item.get("score", 0)), "cover": item.get("cover", ""), "clicks": int(item.get("clicks", 0)), } novel, created = Novel.objects.get_or_create( title=item["title"], author=item["author"], category=category, defaults=defaults, ) if not created: for key, value in defaults.items(): setattr(novel, key, value) novel.save()

2.3 请求频率、断点续爬这些工程细节

爬虫部分的代码量其实不大,真正的分水岭在于好不好维护。我踩过最典型的坑是抓了几百本书之后网络抖动,脚本直接崩溃,前面采的全白干了。

解决办法很朴素,就是每个页面解析成功后立即入库,而不是先存在一个临时列表最后一次性写入。这样天然实现了断点续爬:下次启动时直接跳过数据库中已存在的记录,不需要自己维护任何进度文件。

请求频率也要定得保守一些。两次请求之间至少间隔一到三秒,并加一点随机抖动。这样做的好处有两个,一是降低目标站的压力,二是避免被限流导致整个采集任务中断。采集全部数据之后,每天的更新任务只需要抓排行榜前几十本,一两分钟就完成了,完全没有性能压力。

还有一个细节是编码问题。中文站点的页面可能是 UTF-8 也可能是 GBK 编码,resp.encoding 要根据网页 meta 信息显式指定,否则解析出来全是乱码,后面清洗多难受就不用我说了。

2.4 增量更新与定时任务

数据不能只爬一次,毕业论文的系统如果连续跑一个月,里面数据还是最初的几千条,答辩演示时很难看。用 Django 接入一个轻量级定时任务库,比如 APScheduler 或 django-crontab,每天凌晨两点跑一次增量更新脚本。

增量更新脚本的逻辑就是上面说的:去排行榜页抓最新的几十本书,新书则入库,旧书则更新 click 和 score。这个设计也直接支撑了可视化看板里的"热度趋势"图表,让图表的横轴日期有了实际意义。

提示:把定时任务开关放到 settings 里,用环境变量控制。本地开发时不启动定时任务,只保留手动命令入口,避免每次跑开发服务器的时候都在后台偷偷重新爬数据。

3. Django 后端建模与接口设计:把复杂业务拆成清晰模块

爬虫把数据喂进数据库之后,真正考验后端功底的部分才开始。Django 本身是一个约定大于配置的框架,只要表结构设计合理,后面的接口开发会非常顺手;反过来,表关系一旦设计错位,改起来就是牵一发而动全身。

3.1 数据模型该建哪几张表

除了之前提到的小说主表,至少还需要四张配套表:分类表、用户表、收藏记录表、阅读行为表。分类表用来挂小说,避免每本书里存一个重复的字符串;收藏表是用户与小说的多对多关系的载体;阅读行为表则是推荐算法的核心数据来源,记录每个用户访问了哪些小说、停留多长时间、是否收藏。

我见过不少同学把收藏直接做成用户表里的一个数组字段,或者是把行为记录全部塞在一张表里不分动作类型。这些做法在小规模 demo 里没问题,但写到论文的设计章节时会非常被動。更合理的方式是给行为记录加一个 action_type 字段,点击、收藏、阅读时长分开存,这样后面算用户相似度时,不同行为的权重才能自由调节。

class ReadingRecord(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) novel = models.ForeignKey(Novel, on_delete=models.CASCADE) action_type = models.CharField(max_length=16) # click / collect / read score = models.FloatField(default=1.0) created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = "reading_record" } 在收藏表上,联合唯一约束(user, novel)是必须的,防止同一个用户重复收藏同一本书。阅读行为表则加上索引,因为协同过滤算法在计算时会对行为表做频繁的查询,索引能明显缩短响应时间。 ### 3.2 RESTful API 怎么规划最合理 接口设计不是随便写几个 URL 就完事。我的经验是先在文档里把接口清单列出来,前后端联调时照着推进,比一边写一边改要高效得多。 | 方法 | 接口路径 | 作用 | 是否登录 | |---|---|---|---| | GET | /api/books/ | 小说列表、分类筛选、分页 | 否 | | GET | /api/books/{id}/ | 小说详情 | 否 | | GET | /api/categories/ | 分类列表 | 否 | | GET | /api/recommend/ | 获取推荐结果 | 是 | | POST | /api/records/ | 上报点击/收藏等行为 | 是 | | GET | /api/stats/overview/ | 可视化聚合数据 | 否 | | POST | /api/auth/login/ | 登录获取令牌 | 否 | | GET | /api/user/collections/ | 用户收藏列表 | 是 | 小说列表接口要支持用 query 参数传分类、关键词、排序方式。排序字段允许 title、clicks、score、words 这几个,再利用 Django 的 order_by 动态传入,防止硬编码切换逻辑。 Django REST Framework 的 ModelViewSet 能把这个清单很快落地。关键是 serializer 里加好字段映射,以及权限控制。浏览类接口保持匿名可访问,收藏、推荐这类涉及用户数据的接口加上 IsAuthenticated 校验。 ### 3.3 序列化查询的优化技巧 毕设的数据量一般不会太大,但答辩时老师可能会问"如果数据量上来了怎么办"。所以哪怕是几千条数据,也要把预取优化的姿势写对。查询列表页时要 `select_related` 加载分类,避免逐条查询分类名的 N+1 问题;详情页推荐内容时则用 `prefetch_related` 把标签、相关小说提前取回。 还有一个小点:数据库字段上加 `db_index=True`,尤其是 category 外键和 title 字段。这个改动在几千条数据时看不出差别,但是在文档的数据库设计小节里写"对高频查询字段建立索引",是很加分的规范表述。 ### 3.4 用户鉴权与数据隔离 登录鉴权直接采用 SimpleJWT 方案,前端拿到 access token 后放在请求头里。需要注意 refresh token 的保存位置,本地开发时存在 localStorage 是最简单的,但演示环境如果用的是局域网内其他设备访问,注意清理浏览器缓存,避免上一台设备的登录态残留影响演示。 权限控制上,收藏表和行为表的所有查询都必须按当前登录用户过滤。这不仅是安全问题,也是数据隔离的基本要求。如果用户 A 能通过修改用户 ID 查到用户 B 的收藏列表,答辩时被问出来会非常尴尬。 ## 4. 推荐算法怎么选:内容相似度与协同过滤的落地过程 算法是论文里最有分量的章节,但也是很多同学最容易写虚的地方。写虚的表现是:大谈"深度学习""知识图谱",最后只跑了一个调包的结果。正确的做法是挑两个经典算法做扎实,把推导、实现、评估都讲清楚,就已经完全够用。 ### 4.1 基于内容的推荐:余弦相似度计算 基于内容的推荐核心是把每本小说表示成一个向量,然后计算小说两两之间的相似度。向量可以从分类、作者、简介关键词组合而来。 实际操作时,我建议先把小说简介做分词处理,然后统计关键词权重。分词环节直接用开源分词工具即可,重点在于向量化的思路: ```python import math from collections import Counter def build_vector(text_tokens): # 假设已经完成了分词,输入是词列表 counter = Counter(text_tokens) return counter # 以词频作为向量分量 def cosine_similarity(vec_a, vec_b): common = set(vec_a.keys()) & set(vec_b.keys()) dot = sum(vec_a[k] * vec_b[k] for k in common) norm_a = math.sqrt(sum(v * v for v in vec_a.values())) norm_b = math.sqrt(sum(v * v for v in vec_b.values())) if norm_a == 0 or norm_b == 0: return 0.0 return dot / (norm_a * norm_b)

这个算法计算出的是小说之间的相似度矩阵。矩阵只需要在采集完成或数据更新后计算一次,存进缓存,用户请求推荐时直接读取,而不是每次请求都重算。毕设阶段可以把相似度预计算结果做成一张中间表,论文里能画出清晰的流程图。

4.2 基于用户的协同过滤:行为矩阵与推荐生成

协同过滤的思想是,找到与当前用户行为最相似的一批用户,把这些人读过而当前用户没读过的书推荐出来。

第一步,从阅读行为表里构建 user-item 评分矩阵。评分可以由行为类型加权而来:点击计 1 分,收藏计 5 分,阅读时长超过一定阈值加 2 分。权重值可以在论文里论证一下,核心是表达"不同行为反映的用户偏好强度不同"。

第二步,计算用户相似度。常用的相似度指标是余弦相似度或皮尔逊相关系数。用户向量的维度是小说,两个用户共同读过的书越多,向量方向越接近,相似度越高。

第三步,为目标用户找 TopN 相似用户,把这些用户评分高的小说收集起来,排除当前用户已经读过的,按综合得分排序输出。

这个过程用 Python 写起来大概四五十行,核心代码并不长。我建议把评分矩阵的构建单独抽成一个函数,因为后面评估指标也要复用同一套数据。

4.3 冷启动问题和降级策略

毕设演示时最尴尬的情况是:新注册一个号,点进推荐页,屏幕上什么都刷不出来。原因是这个用户没有任何行为数据,协同过滤无从下手。这就是冷启动问题。

常规解决方案是做一个分层降级:

  1. 如果用户行为记录足够,走基于用户的协同过滤。
  2. 如果用户行为记录很少,走基于内容相似度推荐,用看过的最后一本书找同类。
  3. 如果用户完全没有行为,推荐全局热门前十。

这套逻辑实现起来不复杂,在推荐接口里写一个分支判断就行。关键是要在论文里专门开一小节解释冷启动,这是推荐系统领域的经典问题,讲清楚非常加分。

4.4 用评估指标证明算法"真的有用"

论文最有力的部分是"我做了实验,我的算法有效"。哪怕只是基础 A/B 对比,也比空口说"推荐结果良好"要强得多。标准做法是:把用户行为数据按 8:2 划分训练集和测试集,80% 去构建相似度模型,20% 去验证推荐的准确率。

常用的两个指标是精确率和召回率。精确率表示推荐给用户的小说里有多少是被用户实际点击过的,召回率表示用户实际点击过的小说里有多少出现在了推荐列表中。这两个值算出来可能不高,但不要慌,推荐系统本来天然稀疏。只要算法在数据量相近的前提下比"热门推荐"基线好,就足够写进论文。

5. 可视化看板:用四组图表讲完整个项目的技术故事

可视化是整个系统中最容易"出效果"的一块,也是答辩时老师停留时间最长的地方。它本质上是把数据库中的统计结果用图表呈现,但选图和叙事的逻辑比画图本身更重要。

5.1 看板选哪四类图最合适

不是图越多越好,而是每张图都要解决一个疑问。

  • 分类占比环形图:回答"你的数据覆盖了什么",展示采集到的小说在玄幻、都市、历史等分类下的比例。
  • 热度趋势折线图:回答"数据是否有时间维度",展示小说整体点击量随日期的变化,体现出增量更新在持续运转。
  • 评分分布柱状图:回答"数据质量如何",改善了一堆杂乱数据带来的不可信印象。
  • 简介关键词词云:回答"内容特征长什么样",直接体现内容分析能力。

这四张图合起来,就是一段完整的项目介绍:我采了什么数据,数据长什么样,我能怎么分析它,分析结果能如何支撑推荐算法。答辩时顺着这个顺序讲,评委很少会追问细节。

5.2 后端聚合接口怎么设计

可视化接口不能直接返回整张大表让前端自己算。Django ORM 里一句聚合查询就能算好,然后返回精简 JSON 给前端。

from django.db.models import Count def stats_overview(request): category_data = ( Novel.objects .values("category__name") .annotate(count=Count("id")) .order_by("-count") ) return JsonResponse({ "categories": list(category_data), # 其他统计结果类似 })

热点趋势数据则按日期对点击量求和,返回一个时间序列。词云数据可以在爬虫阶段就把每本书的分词结果存下来,统计全局出现次数最高的词汇,直接把 top 50 返回给前端。这些计算量都非常小,响应用不到几十毫秒。

5.3 前端图表组件的集成姿势

可视化部分用 ECharts 生态,在 Vue 项目里可以直接封装一个图表组件,传入配置项就渲染。关键操作是给图表容器设置一个明确的尺寸,以及监听窗口变化时调用 resize。

拿到后端数据之后,在前端做一层数据转换,把它映射到 ECharts 需要的 series 格式。不要在后端拼图表配置,因为后端聚合适用于多个前端场景,保持数据结构的通用性会更好维护。

提示:词云图不要用太花哨的字体形状,把词频高的关键词放大加粗就够了。答辩投影仪的解析度一般,太精致的视觉效果反而容易糊。

6. Vue.js 前端工程化:组件规划、状态管理与体验细节

前端这部分如果只是把后端的接口数据渲染到页面上,那工作量就太轻了。毕设的前端应该体现出一定的工程化思维,包括路由设计、组件划分、状态管理和交互打磨。

6.1 页面路由与导航结构

整个前端就五大页面,路由层级非常清晰:

路由路径页面功能
/home推荐首页热门推荐、猜你喜欢
/category/:id分类列表分类筛选、分页浏览
/detail/:id小说详情封面、简介、相关推荐
/dashboard数据看板四类可视化图表
/user个人中心收藏记录、退出登录

路由配置用 Vue Router 的懒加载写法,每个页面按需加载。底部导航在移动端和桌面端都要适配,演示时可能在投影仪上用宽屏,也可能直接在手机上展示,不能出现布局错乱。

6.2 状态管理与请求封装

用户登录之后的 token 和个人信息是全局状态。我在项目里用的是 Pinia,store 里只维护 user 和 token 两个字段。登录成功时写入 store,刷新页面时从 localStorage 恢复。

请求封装是最容易踩坑的地方。统一封装 axios 实例,在拦截器里做三件事:附带 Authorization 请求头、统一处理错误状态码、遇到 401 时跳转登录页。这样一来,业务页面里只需要关心成功数据,异常统统交给拦截器处理,代码会干净一大截。

// request.js 的核心拦截逻辑 service.interceptors.request.use((config) => { const token = localStorage.getItem("token"); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }) service.interceptors.response.use( (response) => response.data, (error) => { if (error.response?.status === 401) { // 处理登录失效:清空状态、跳转登录 } return Promise.reject(error); } )

6.3 推荐卡片与详情页的交互打磨

推荐卡片是用户第一眼看到的东西。卡片不一定要复杂,但封面、书名、分类标签、评分、一句简介这五个元素缺一不可。封面临时加载不出来的时候,要有一个默认占位图,不然页面会一块一块地闪白。

详情页除了展示基本信息之外,还要留一个"相似推荐"列表。这里直接用后端基于内容相似度计算出来的结果。前端方面,给推荐区域加个简单的加载动画,用骨架屏效果会比转圈菊花高级不少。

另外,点击行为的上报一定要埋点。我看过不少项目,推荐算法里明明写了要收集行为数据,前端却根本没调上报接口,这个 bug 会让算法部分完全失效。最简单的方式是在详情页的 mounted 钩子里发一个 POST 请求,把当前用户和小说 ID 传给后端。

6.4 移动端适配和加载性能

毕设演示通常都在笔记本上,但如果能顺手支持手机浏览器,体验会好很多。布局上不用额外引入复杂的移动端框架,Flex 布局加 Grid 就能扛住大部分场景。列表页的卡片用 grid 自动填充列数:屏幕宽就排 5 列,窄就自动降为 2 列。

图片懒加载是必须的。小说封面数量大,一次性全部加载会明显拖慢首屏。用 vue-lazyload 或者浏览器原生 loading="lazy" 属性都可以。路由层面的懒加载加上图片懒加载,首屏速度基本不会出问题。

7. 联调、自测与交付整理:毕业设计最容易翻车的三个阶段

功能开发完之后,剩下的时间往往比开发本身还重要。很多项目最后没有拿到期望的分数,问题不是在功能上,而是联调效率低、演示翻车、文档交付不完整。

7.1 前后端联调时的三个约定

联调要高效的唯一法则,就是把约定写下来,而不是靠脑子记。

第一,统一响应结构。后端不管成功失败都返回{ "code": 0, "message": "ok", "data": ... }这种格式,失败的 code 位非零。前端拦截器里统一判断 code,HTTP 状态码反而不作为业务判断依据。这样避免了"接口返回 200 但页面没有数据"的一系列困惑。

第二,统一时间格式。所有的时间字段一律用 ISO 格式字符串传输,不要在前后端各自格式化。展示时如果需要"几小时前"这种文案,前端本地转换即可。

第三,统一命名风格。后端返回的字段统一用小驼峰,前端组件内部可以随意,但对外接口字段别一会儿 snake_case 一会儿 camelCase。这个约定在写文档时也能保持一致,减少答辩时被追问的可能。

如果遇到跨域问题,最常见的解法是后端起用 django-cors-headers 中间件,开发时把允许的来源设成前端的本地端口即可。

7.2 本地环境与演示准备的细节

演示前一定要提前做一次干净环境的全流程测试。我的建议是准备一台没有多余依赖的笔记本,从python -m venv开始安装依赖、跑迁移、手动执行一遍爬虫脚本、启动开发服务器、打开前端页面。这一步能把你项目里的路径写死问题和 Python 版本依赖问题全部暴露出来。

数据库和 Redis 的配置也要在 settings 里区分开发环境与生产环境。演示时直接用开发环境最省事,但要注意服务器地址别写成本机的 127.0.0.1,前端调接口的地址也应改为局域网 IP 或演示机的地址。

还有一个小技巧:演示前先跑一遍增量更新脚本,保证排行榜数据是当天的。宁可多花一分钟,也不要出现图表趋势线上的日期停在三天前的尴尬情况。

7.3 答辩演示的节奏与PPT编排

PPT 的结构一定要和系统演示形成互补,而不是把 PPT 上的内容原样念一遍。推荐的顺序是:先讲痛点引入,再放系统架构图说明技术选型,接着演示可视化看板建立直观印象,然后进入推荐算法讲解和效果验证,最后用一段总结收尾。

演示过程中,务必提前把每个页面打开一遍,确保浏览器没有缓存旧登录态。用访客模式打开浏览器是一个不错的习惯,能够有效避免登录态污染。另外,演示机上提前准备好一个测试账号,最好已经积累了不少行为数据,这样进入推荐页时不会因为冷启动而空白。

7.4 交付物整理:源码、LW文档、PPT一个都不能少

毕业设计交付不是把代码文件夹压缩包发出去就完事。一个规范的交付目录至少要包含下面的结构:

  • 源码目录:后端 Django 项目和前端 Vue 项目分开放,根目录放一个 README,写明启动步骤。
  • LW文档:需求分析、系统设计、数据库设计、核心算法实现、系统测试这几章必须齐。重点是数据库设计的表关系图,以及推荐算法的流程图和公式推导。
  • PPT:控制在 15 页以内,每页只放一个核心观点,代码截图不要超过两处。
  • 演示视频:视学校要求而定。录屏时分辨率不要太高,保证流畅即可,口语解说要提前写逐字稿。

有一点我特别想强调,README 里的启动步骤一定要自己照着从头操作一遍再提交。每年都有同学把依赖清单写少了一个包,或者把启动命令写错,导致评阅老师复现环境时直接跑不起来。这是完全不必要的工作量损失。

最后一个我自己的体会:整套系统从头到尾做下来,真正的难点从来不是某个算法有多深,而是数据、接口、页面这三层能不能顺畅地串起来。爬虫代码写一天,清洗数据可能就要磨三天;接口写半天,联调可能要磨两天。这些看起来不起眼的工程细节,恰恰决定了你的系统是"能演示的完整作品"还是"一堆代码片段"。

如果你正在做类似题目,记得把每个模块运行验证的时间预留够。项目后期列一个清单,从爬虫采集、数据看板、推荐结果三个方向分别验证,每一个方向都跑通之后再进联调,会比一边写一边发现数据问题从容得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询