跳到主要内容基于用户画像的 Python 音乐推荐系统:Django 协同过滤与 SVD 算法 | 极客日志PythonAI算法
基于用户画像的 Python 音乐推荐系统:Django 协同过滤与 SVD 算法
综述由AI生成基于 Python 与 Django 框架构建的音乐推荐系统,集成 Last.fm 公开数据集。核心采用基于用户的协同过滤算法与 SVD 矩阵分解技术,结合用户画像(流派、语种订阅)优化推荐精度。功能涵盖音乐播放、偏好管理、后台数据维护及搜索检索。代码层面实现了用户认证、行为记录及分页渲染逻辑,旨在解决海量音乐库中的个性化发现难题,提升听歌体验。
接口猎人18 浏览 基于用户画像的 Python 音乐推荐系统
技术架构
本系统采用 Python 3.x 开发,后端基于 Django 框架构建前后端分离架构,数据存储选用 MySQL 或 SQLite3。开发环境为 PyCharm,运行于 Windows 平台。数据集源自 Last.fm Dataset-360K Users 公开数据集。核心算法结合了基于用户的协同过滤与 SVD 矩阵分解,通过用户评分行为预测潜在喜好,生成个性化推荐列表。
功能模块
- 首页展示:提供全部、推荐、正在播放导航及搜索功能,卡片式展示音乐信息(时长、歌手、流派)。
- 交互操作:支持播放、喜欢、不喜欢、收藏等操作,实时反馈用户偏好。
- 用户画像:首次登录后订阅音乐流派和语种,优化后续推荐精度。
- 后台管理:管理员可对歌曲信息进行增删改查,维护音乐库完整性。
- 认证体系:注册登录界面,保障用户身份验证安全。
界面概览
系统主界面顶部设有导航栏,主体区域展示音乐卡片列表。用户中心页面标注了用户已标记的喜好状态。播放界面聚焦当前歌曲信息与进度控制。后台管理以表格形式清晰呈现音乐库数据,支持筛选操作。

核心逻辑实现
推荐逻辑主要依赖 recommend 视图函数,结合用户画像构建推荐集。以下是关键代码片段,展示了如何处理用户偏好及分页渲染。
@login_required(login_url='/sign_in')
@cold_boot
def recommend(request):
page_number = request.GET.get('page', 1)
recommend_set = build_recommend(request, request.user)
paginator = Paginator(recommend_set, 20)
musics = paginator.page(page_number)
context = {'musics': musics, 'user_likes': [], 'user_dislikes': []}
user_profile = UserProfile.objects.filter(user=request.user)
if user_profile.exists():
user_profile = user_profile.first()
context['user_likes'] = user_profile.likes.all()
context['user_dislikes'] = user_profile.dislikes.all()
return render(request, 'list.html', context)
@login_required(login_url='/sign_in')
def like(request, pk: int):
user_obj = UserProfile.objects.get(user=request.user)
music_obj = get_object_or_404(Music.objects.all(), pk=pk)
user_obj.likes.add(music_obj)
user_obj.dislikes.remove(music_obj)
messages.add_message(request, messages.INFO, '已经添加到我喜欢')
redirect_url = request.GET.get('from', '/')
if 'action' in request.GET:
redirect_url += f'&action={request.GET["action"]}'
return HttpResponseRedirect(redirect_url)
@login_required(login_url='/sign_in')
def dislike(request, pk: int):
user_obj = UserProfile.objects.get(user=request.user)
music_obj = get_object_or_404(Music.objects.all(), pk=pk)
user_obj.dislikes.add(music_obj)
user_obj.likes.remove(music_obj)
messages.add_message(request, messages.INFO, '已经添加到我不喜欢')
redirect_url = request.GET.get('from', '/')
if 'action' in request.GET:
redirect_url += f'&action={request.GET["action"]}'
return HttpResponseRedirect(redirect_url)
def play(request, pk: int=0):
global current_play
if pk > 0:
music_obj = Music.objects.filter(pk=pk)
if music_obj.exists():
current_play = music_obj.first()
if current_play is None:
messages.error(request, '当前没有正在播放的音乐')
return HttpResponseRedirect('/')
return render(request, 'play.html', context={'music': current_play})
@login_required(login_url='/sign_in')
def user_center(request):
user_profile = UserProfile.objects.filter(user=request.user)
if user_profile.exists():
profile_obj: UserProfile = user_profile.first()
else:
messages.error(request, '找不到用户资料,请重新登录')
logout(request)
return HttpResponseRedirect('/')
if request.method == 'POST':
genres = request.POST.getlist('genres', '')
languages = request.POST.getlist('languages', '')
profile_obj.first_run = False
if len(genres) > 0:
profile_obj.genre_subscribe = ','.join(genres)
profile_obj.save()
messages.success(request, '修改流派订阅成功!')
elif not profile_obj.first_run:
profile_obj.genre_subscribe = ''
profile_obj.save()
if len(languages) > 0:
profile_obj.language_subscribe = ','.join(languages)
profile_obj.save()
messages.success(request, '修改语言订阅成功!')
elif not profile_obj.first_run:
profile_obj.language_subscribe = ''
profile_obj.save()
context = {
'user_likes': profile_obj.likes.all(),
'user_dislikes': profile_obj.dislikes.all(),
'genres': build_genre_ids(),
'languages': build_languages(),
'genre_subscribe': profile_obj.genre_subscribe.split(','),
'language_subscribe': []
}
for lang in profile_obj.language_subscribe.split(','):
lang = lang.strip()
context['language_subscribe'].append(lang)
return render(request, 'user.html', context=context)
def search(request):
if 'keyword' not in request.GET:
messages.error(request, '请输入搜索关键词')
return HttpResponseRedirect('/')
keyword = request.GET.get('keyword')
action = request.GET.get('action')
musics = []
if action == 'song_name':
musics = Music.objects.filter(song_name__contains=keyword)
if action == 'artist_name':
musics = Music.objects.filter(artist_name__contains=keyword)
messages.info(request, f'搜索关键词:{keyword},找到 {len(musics)} 首音乐')
context = {'musics': musics, 'user_likes': [], 'user_dislikes': []}
if request.user.is_authenticated:
user_profile = UserProfile.objects.filter(user=request.user)
if user_profile.exists():
user_profile = user_profile.first()
context['user_likes'] = user_profile.likes.all()
context['user_dislikes'] = user_profile.dislikes.all()
return render(request, 'list.html', context)
上述代码涵盖了推荐分发、用户偏好记录(喜欢/不喜欢)、播放状态管理及个人中心设置等核心流程。通过 UserProfile 模型关联用户行为,配合 build_recommend 函数调用 SVD 算法进行相似度计算,实现了动态更新推荐列表的效果。
总结
该系统利用 Django 框架快速搭建,结合协同过滤与 SVD 算法解决冷启动问题。用户画像的引入使得推荐结果更具针对性,后台管理模块则保障了数据的可维护性。整体设计兼顾了用户体验与工程实现的可行性,适合用于计算机专业毕业设计或相关教学演示。
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- RSA密钥对生成器
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
- Mermaid 预览与可视化编辑
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
- 随机西班牙地址生成器
随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- curl 转代码
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online