ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Django在线电影推荐系统毕设实战:从环境搭建到推荐算法与避坑指南

Django在线电影推荐系统毕设实战:从环境搭建到推荐算法与避坑指南 简介这是一套面向高校计算机相关专业学生与Python开发初学者的在线电影推荐系统完整项目源码适用于毕业设计、课程设计及Django入门实战场景。项目以Python与Django为核心技术栈围绕用户观看历史与电影内容展开个性化推荐涵盖数据爬取、数据清洗与预处理、特征提取、余弦相似度计算、基于内容与协同过滤的推荐算法以及网页端可视化结果展示等完整模块可帮助读者理解推荐系统从数据到算法的落地流程。压缩包共392个文件约9.76MB包含28个py源码文件、43个pyc编译文件、62个js脚本、35个css样式、9个html页面以及大量jpg、gif、png图片素材和字体文件前端资源与后端逻辑分层清晰便于按模块阅读与二次开发。目前已有255人学习下载适合需要完整项目参考、算法实现思路与前后端整合范例的读者借鉴使用。1. 在线电影推荐系统拆包一份能跑通的 Django 毕设长什么样很多同学拿到「基于 Python 的在线电影推荐系统.zip」这类压缩包时第一反应是解压、找manage.py、pip install -r requirements.txt然后python manage.py runserver结果浏览器一打开就报 500或者首页能出来但推荐列表永远是空的。这个项目本质上是一个 Django 搭建的 Web 应用核心逻辑集中在movie_recommender.py它把「爬取电影数据 → 清洗入库 → 提取特征 → 算相似度 → 生成推荐 → 页面展示」这条链路串了起来。适合正在做毕业设计、课程设计想找一个结构完整、算法可解释、前后端都能改的推荐系统原型的同学。它不追求工业级性能但胜在链路清晰、代码量可控你能真正看懂每一行在干什么而不是调个库就完事。下面我按「先跑起来、再改算法、最后避坑」的顺序把这份资源拆开讲。2. 环境搭建与项目启动从解压到首页出图2.1 依赖清单与 Python 版本选择这个项目用的是 Django 做后端前端混了 Bootstrap、Layui、animate.css 几套样式数据库默认走 SQLite所以不需要额外装 MySQL 就能跑。Python 版本建议 3.8 到 3.10太新的 3.12 在部分老版本 Django 上会有兼容问题。常见做法是建一个虚拟环境把依赖隔离掉避免和你机器上其他项目的包打架。# 创建虚拟环境python 版本按你本机情况选 python -m venv venv # Windows 激活 venv\Scripts\activate # macOS / Linux 激活 source venv/bin/activate # 安装核心依赖版本号按 requirements.txt 来 pip install django3.2.18 pip install requests beautifulsoup4 pip install pandas numpy scikit-learn pip install pillow这里几个包的分工要说清楚requestsbeautifulsoup4负责爬电影信息pandasnumpy做数据清洗和矩阵运算scikit-learn提供余弦相似度计算pillow是 Django 处理图片字段的依赖。如果你pip install时卡在编译阶段大概率是numpy或scikit-learn没有对应你 Python 版本的预编译 wheel换 Python 3.9 通常能解决。2.2 数据库迁移与初始数据导入解压后先别急着runserver数据库里没表首页一访问就崩。标准流程是三步生成迁移文件、执行迁移、导入初始数据。# 进入项目根目录确认能看到 manage.py cd movie_recommender # 生成迁移文件 python manage.py makemigrations # 执行迁移创建表结构 python manage.py migrate # 创建后台管理员账号方便录入和检查数据 python manage.py createsuperuser # 导入项目自带的初始电影数据如果有 fixtures 目录 python manage.py loaddata movies.jsonmakemigrations是根据models.py里的模型定义生成建表语句migrate才是真正在 SQLite 里建表。loaddata这一步不是每个包都有如果项目里没有movies.json或fixtures目录就跳过改用爬虫脚本或后台手动录入。判断依据很简单看项目根目录有没有fixtures文件夹或者README里有没有提初始数据。2.3 启动服务与静态文件排查# 启动开发服务器默认 8000 端口 python manage.py runserver 0.0.0.0:8000启动后浏览器访问http://127.0.0.1:8000。如果页面样式全丢、按钮错位八成是静态文件没配好。Django 开发模式下DEBUGTrue时会自动找static目录但有些包把 CSS 放在assets或public下需要在settings.py里补STATICFILES_DIRS。# settings.py 里确认这几项 STATIC_URL /static/ STATICFILES_DIRS [ os.path.join(BASE_DIR, static), ] # 如果 CSS 在别的目录把路径加进去改完settings.py要重启服务才生效。首页能正常出图、导航能点说明环境这关过了接下来才是推荐逻辑本身。3. 推荐算法核心movie_recommender.py 里的特征与相似度3.1 数据收集与预处理的实际写法movie_recommender.py的第一段逻辑是数据收集。项目里通常用requests抓取电影列表页再用BeautifulSoup解析标题、导演、演员、类型这些字段。真实场景下目标站点结构会变所以这段代码你要当成模板看而不是拿来即用。import requests from bs4 import BeautifulSoup import pandas as pd def fetch_movies(base_url, pages5): movies [] for page in range(1, pages 1): # 分页参数按目标站点实际规则拼 resp requests.get(f{base_url}?page{page}, timeout10) resp.encoding utf-8 soup BeautifulSoup(resp.text, html.parser) for item in soup.select(.movie-item): movies.append({ title: item.select_one(.title).get_text(stripTrue), director: item.select_one(.director).get_text(stripTrue), actors: item.select_one(.actors).get_text(stripTrue), genres: item.select_one(.genres).get_text(stripTrue), }) return pd.DataFrame(movies) df fetch_movies(https://example.com/movies, pages5) df.drop_duplicates(subset[title], inplaceTrue) df.dropna(inplaceTrue)timeout10是防止某个请求卡死拖垮整个脚本resp.encoding不设的话中文容易乱码。drop_duplicates按标题去重dropna清掉缺字段的行。这两步看着简单但如果你跳过后面算相似度时会出现空值传播整个推荐列表直接变空。3.2 特征提取把文本转成向量推荐系统能不能推得准一半看特征提得好不好。这个项目里常见的做法是把「类型 导演 演员」拼成一个文本字段然后用CountVectorizer或TfidfVectorizer转成向量。from sklearn.feature_extraction.text import TfidfVectorizer # 把多个字段拼成一条特征文本 df[feature_text] ( df[genres].fillna() df[director].fillna() df[actors].fillna() ) # 用 TF-IDF 转成向量矩阵 tfidf TfidfVectorizer(stop_wordsenglish, max_features5000) feature_matrix tfidf.fit_transform(df[feature_text])max_features5000是控制维度上限防止词表太大导致内存爆掉。stop_wordsenglish去掉 the、a 这类无意义词。如果你发现推荐结果总是那几部热门片多半是特征里演员名字权重太高可以调低演员字段的拼接次数或者给类型字段加权。3.3 余弦相似度计算与推荐列表生成拿到特征矩阵后算电影之间的余弦相似度再根据用户看过的电影找最相似的若干部推给他。from sklearn.metrics.pairwise import cosine_similarity # 计算电影之间的相似度矩阵 similarity cosine_similarity(feature_matrix) def recommend(movie_title, top_n10): # 找到目标电影的索引 idx df[df[title] movie_title].index if len(idx) 0: return [] idx idx[0] # 取出相似度分数并排序 scores list(enumerate(similarity[idx])) scores sorted(scores, keylambda x: x[1], reverseTrue) # 跳过自己取前 top_n top_movies [df[title][i] for i, _ in scores[1:top_n 1]] return top_moviesscores[1:top_n1]这个切片是关键scores[0]是电影自己相似度恒为 1必须跳过否则推荐列表第一条永远是当前电影。top_n默认 10你可以按页面展示需求改成 6 或 12。如果推荐结果重复率高说明相似度矩阵区分度不够回到上一步调整特征权重。4. 前后端打通Django 视图、模板与推荐结果展示4.1 视图函数如何调用推荐逻辑推荐算法写好了得让 Web 页面能调它。Django 里一般是在views.py里写一个视图函数接收电影 ID 或标题调recommend()把结果塞进 context 渲染模板。from django.shortcuts import render from .movie_recommender import recommend, df def movie_detail(request, movie_id): # 从数据库或 DataFrame 取当前电影 movie df.iloc[movie_id] # 调用推荐函数 rec_titles recommend(movie[title], top_n6) # 把推荐结果的完整信息查出来 rec_movies df[df[title].isin(rec_titles)].to_dict(records) return render(request, movie_detail.html, { movie: movie.to_dict(), recommendations: rec_movies, })to_dict(records)是把 DataFrame 行转成字典列表模板里就能用for循环渲染。注意df是在模块加载时构建的如果数据量大每次请求都重新算相似度会很慢常见做法是把相似度矩阵缓存到内存或存成.npy文件启动时加载一次。4.2 模板里怎么渲染推荐卡片前端模板用 Django 模板语法遍历recommendations每部电影渲染一张卡片带海报、标题、类型。div classrow {% for movie in recommendations %} div classcol-md-4 div classcard img src{{ movie.poster }} classcard-img-top alt{{ movie.title }} div classcard-body h5 classcard-title{{ movie.title }}/h5 p classcard-text{{ movie.genres }}/p a href/movie/{{ movie.id }}/ classbtn btn-primary查看详情/a /div /div /div {% endfor %} /div海报字段poster如果数据库里存的是相对路径模板里要拼上MEDIA_URL否则图片 404。col-md-4是 Bootstrap 的三列布局一行放三部电影和top_n6配合正好两行。4.3 静态资源与媒体文件的配置差异这个项目里 CSS 文件很多bootstrap.min.css、layui.css、animate.min.css各管一摊。静态资源走STATIC_URL用户上传的海报走MEDIA_URL两者在settings.py和urls.py里都要单独配。# settings.py MEDIA_URL /media/ MEDIA_ROOT os.path.join(BASE_DIR, media) # urls.py 开发模式下追加 from django.conf import settings from django.conf.urls.static import static urlpatterns static(settings.MEDIA_URL, document_rootsettings.MEDIA_ROOT)static()只在DEBUGTrue时生效部署到生产环境要交给 Nginx 处理。很多同学本地跑得好好的一部署海报全裂就是漏了这一步。5. 避坑与排查跑不起来时先看这几条5.1 现象首页 500报 no such table原因数据库迁移没执行或者迁移文件没生成。解决先makemigrations再migrate确认项目根目录出现db.sqlite3文件。如果报「No changes detected」检查models.py里的模型有没有被admin.py或apps.py正确注册。5.2 现象推荐列表为空页面不报错原因recommend()里df[df[title] movie_title]没匹配到索引为空直接返回[]。解决打印df[title].head()看标题格式常见问题是数据库里标题带了空格或年份后缀而传入的标题没有做一次strip()和模糊匹配。5.3 现象中文乱码标题显示成问号原因爬虫抓取时没设resp.encoding或者数据库字符集不对。解决requests里显式设resp.encoding utf-8SQLite 默认支持 UTF-8如果还乱检查settings.py里DATABASES的OPTIONS有没有加charset。5.4 现象相似度计算内存溢出原因电影数量上千后cosine_similarity生成的矩阵是 N×N内存占用平方级增长。解决限制max_features或者改用稀疏矩阵运算只对目标电影算相似度而不是全量矩阵。5.5 现象静态文件 404样式全丢原因STATICFILES_DIRS没配或者 CSS 实际目录和配置不一致。解决在settings.py里打印BASE_DIR确认static目录真实存在路径大小写要和文件系统一致Linux 下区分大小写Windows 下不区分跨平台时容易翻车。6. 进阶技巧把推荐结果做一次离线验证跑通之后别急着截图交差。推荐系统最怕的是「看起来能推实际全是热门片」。我一般会做一个离线验证留出一部分用户评分数据用推荐列表去命中算准确率和召回率。这个项目里没有现成的评估脚本但你可以基于movie_recommender.py快速补一个。import numpy as np def evaluate(similarity, df, test_pairs, top_n10): hits 0 for user_id, true_movie in test_pairs: # 用真实电影反查推荐列表 recs recommend(true_movie, top_ntop_n) if true_movie in recs: hits 1 precision hits / (len(test_pairs) * top_n) recall hits / len(test_pairs) return precision, recall # test_pairs 格式[(user_id, movie_title), ...] precision, recall evaluate(similarity, df, test_pairs) print(fPrecision10: {precision:.4f}, Recall10: {recall:.4f})test_pairs可以从用户观看历史里切 20% 出来当测试集。Precision10衡量推的十部里有多少是用户真正看过的Recall10衡量用户看过的电影有多少被推出来了。两个指标都低说明特征或相似度算法要调只有一个低看是推得太保守还是太发散。还有一个实用技巧把相似度矩阵存成文件启动时加载避免每次重启都重算。import numpy as np # 保存 np.save(similarity_matrix.npy, similarity) # 加载 similarity np.load(similarity_matrix.npy)数据量上千后这一步能省掉几十秒启动时间。改完算法记得重新生成矩阵否则你调了半天参数跑的还是旧结果这种「改了没生效」的玄学问题十有八九是缓存没清。从那以后我每次改完推荐逻辑都强制走一遍「删缓存 → 重算矩阵 → 跑评估脚本 → 再看页面」这个流程不再凭感觉判断效果。希望帮到你。本文还有配套的精品资源点击获取
返回列表