当前位置: 首页 > news >正文

基于Mysql+Vue+Django的协同过滤和内容推荐算法的智能音乐推荐系统——深度学习算法应用(含全部工程源码)+数据集

目录

  • 前言
  • 总体设计
    • 系统整体结构图
    • 系统流程图
  • 运行环境
    • Python 环境
    • MySQL环境
    • VUE环境
  • 模块实现
    • 1. 数据请求和储存
    • 2. 数据处理
      • 计算歌曲、歌手、用户相似度
      • 计算用户推荐集
    • 3. 数据存储与后台
    • 4. 数据展示
  • 系统测试
  • 工程源代码下载
  • 其它资料下载


在这里插入图片描述

前言

本项目以丰富的网易云音乐数据为基础,运用协同过滤和内容推荐算法作为核心方法,旨在为不同用户量身定制音乐推荐。

首先,我们充分利用网易云音乐的大量用户数据,包括用户的收听历史、喜好歌手、喜欢的歌曲等信息。通过协同过滤算法,我们可以分析不同用户之间的相似性,找到具有相近音乐口味的用户群体。

其次,我们引入内容推荐算法,从音乐的特征、流派、歌手风格等方面进行深入分析。这种算法能够更精准地为用户推荐符合其喜好和兴趣的音乐作品。

综合协同过滤和内容推荐的结果,我们为每位用户打造个性化的音乐推荐列表。这样,不同用户将能够在网易云音乐平台上获得与其音乐喜好相符的歌曲,从而提升他们的音乐体验。

本项目的目标是充分发挥大数据分析和智能推荐算法的优势,为网易云音乐的用户提供更加个性化、多样化的音乐推荐服务。这将为用户带来更多的音乐发现和享受,同时也促进了音乐平台的发展和用户满意度的提升。

总体设计

本部分包括系统整体结构图和系统流程图。

系统整体结构图

系统整体结构如图所示。

在这里插入图片描述

系统流程图

系统流程如图所示。

在这里插入图片描述

运行环境

本部分包括 Python 环境、MySQL 环境和 VUE 环境。

Python 环境

需要Python 3.6以上运行环境,推荐使用PyCharm IDE。Python 包和对应的版本MusicRecSys/MusicRec/z-others/files/requirement.txt文件中,安装命令为:

pip install -r requirement.txt

需要安装的依頼包为: Django 2.1、PyMySQL 0.9.2、jieba 0.39、xlrd 1.1.0、gensim 3.6.0

查看本机的IP地址,修改MusicRecSys/MusicRec/Music Rec/settings.py文件中的ALLOWED_HOSTS 为本地IP地址和MySQL配置信息。

进入MusicRecSys/MusicRec, 执行pythonmanage.pyrunserver0.0.0.0: 8000

Django后台访问地址为http://127.0.0.1:8000/admin/(admin, admin)

MySQL环境

安装MySQL最新版本和Navicat可视化工具,在命令行中创建并连接本机用户的数据库,下载地址为https://pan.baidu.com/s/1dYtKQxnoSZywuRfgCOfPRQ, 提取码为:qw8k

新建musicrec数据库,导入文件MusicRecSys/MusicRec/z-others/fles/musicrec.sql

VUE环境

安装node.js 10.13以上版本和npm包管理器(可以安装淘宝镜像cnpm提高速度),推荐使用VSCODEIDE。

修改MusicRecSys/MusicRec-Vue/config/index.js中的serverUrl为本机IP地址。

修改MusicRecSys/MusicRec-Vue/src/assets/js/linkBase.js中的serverUrl为本机IP地址。

进入MusicRecSys/MusicRec-Vue,执行npminstall/npmrundev自动安装所需要的依赖包并用webpack打包运行。

在浏览器中输入http://127.0.0.1:8001, 访问项目界面。

模块实现

本项目包括包括4个模块:数据请求及存储、数据处理、数据存储与后台、数据展示,下面分别介绍各模块的功能及相关代码。

1. 数据请求和储存

通过请求获取音乐和用户相关的所有数据。网易云API地址为https://api.imjad.cn。选择歌单数据作为出发点,是因为歌单与用户、歌曲、歌手都有联系,包含数据的维度最广,并且是用户的主观行为。歌单URL如下所示。

https://music163.com/playlist?id=2308644764
https://music163.com/playlist?id=2470855457
https://music163.com/playlist?id=2291941158
https://music163.com/playlist?id=2452844647

通过URL处理得到歌单ID,请求所需要的数据,存储每一步请求失败的数据,在后续数据处理时跳过这些请求失败的数据URL。

1)歌单信息

歌单信息如图所示。

在这里插入图片描述

歌单信息包含歌单ID、创建者ID、名字、创建时间、更新时间,包含音乐数、播放次数、分享次数、评论次数、收藏次数、标签和歌单封面等。

2)创建者信息

创建者信息如图所示。

在这里插入图片描述

创建者信息包含用户ID、昵称、生日、性别、省份、城市、类型、标签、头像链接、用户状态、账号状态、djStatus、vipStatus、 签名。

3)歌曲音乐信息

歌曲ID信息如图所示。

在这里插入图片描述

歌曲信息如图所示。

在这里插入图片描述
歌曲信息包含歌曲ID、歌名、专辑ID、出版时间、歌手信息、总评论数、热门评论数、大小、歌曲链接。

4)歌曲对应的歌手信息

歌手信息如图所示。

在这里插入图片描述

歌手信息包含歌手ID、歌名、音乐作品数、MV作品数、专辑数、头像链接等,其数据文件结构如图所示。

在这里插入图片描述

最终获得所需的基础数据和请求失败的数据,获取歌单信息并存储的相关代码如下:

import requests
import traceback
#获取每个歌单的信息类
class PlayList:def __init__(self):self.playlist_file = "./data/playlist_url/playlist_id_name_all.txt"#获取出错的歌单ID保存文件self.error_id_file = "./data/error_playlist_ids.txt"#歌单创造者信息self.creator_mess = "./data/user_mess/"#每个歌单的json信息self.playlist_mess = "./data/playlist_mess/"#歌单包含的歌曲ID信息self.trackid_mess = "./data/song_mess/"self.ids_list = self.getIDs()self.url = "https://api.imjad.cn/cloudmusic/?type=playlist&id="#获得的歌单信息出错的歌单IDself.error_id = list()#由歌单url 获取歌单IDdef getIDs(self):print("根据歌单链接获取歌单ID ...")ids_list = list()for line in open(self.playlist_file,"r",encoding="utf-8").readlines():try:id = line.strip().split("\t")[0].split("id=")[1]ids_list.append(id)except Exception as e:print(e)passprint("获取歌单ID完成 ...")return ids_list
#获取每个歌单的具体信息url #https://api.imjad.cn/cloudmusic/?type=playlist&id=2340739428def getEveryPlayListMess(self):print("获取每个歌单的具体信息")i = 0while self.ids_list.__len__() !=0 :i += 1id = self.ids_list.pop()url = self.url + str(id)try:print("%s - 歌单ID为:%s" % (i,id))r = requests.get(url)#解析信息self.getFormatPlayListMess(r.json())except Exception as e:#将出错ID写入记录及写入文件,出错时进行跳过print(e)traceback.print_exc()print("歌单ID为:%s 获取出错,进行记录" % id)self.error_id.append(id)pass#breakself.writeToFile(self.error_id_file,",".join(self.error_id))print("歌单信息获取完毕,写入文件: %s" % self.playlist_mess)#每个歌单的内容进行格式化处理写入文件#需要获取的信息: 歌单信息、创建者信息、歌单音乐信息def getFormatPlayListMess(self,json_line):#创建者信息:用户ID、昵称、生日、性别、省份、城市、类型、标签、头像链接、用户状态、账号状态、djStatus,vipStatus、签名creator = json_line["playlist"]["creator"]c_list = (str(creator["userId"]),str(creator["nickname"]),str(creator["birthday"]),str(creator["gender"]),str(creator["province"]),str(creator["city"]),str(creator["userType"]),str(creator["expertTags"]),str(creator["avatarUrl"]),str(creator["authStatus"]),str(creator["accountStatus"]),str(creator["djStatus"]),str(creator["vipType"]),str(creator["signature"]).replace("\n",""))self.writeToFile(self.creator_mess + "user_mess_all.txt"," |=| ".join(c_list))#歌单信息#歌单ID、创建者ID、名字、创建时间、更新时间、播放次数、分享次数、评论次数、收藏次数、标签、歌单封面、描述playlist = json_line["playlist"]p_list = [str(playlist["id"]),str(playlist["userId"]),str(playlist["name"]).replace("\n",""),str(playlist["createTime"]),str(playlist["updateTime"]),str(playlist["trackCount"]),str(playlist["playCount"]),str(playlist["shareCount"]),str(playlist["commentCount"]),str(playlist["subscribedCount"]),str(playlist["tags"]),str(playlist["coverImgUrl"]),str(playlist["description"]).replace("\n","")]self.writeToFile(self.playlist_mess + "pl_mess_all.txt"," |=| ".join(p_list))#歌单包含的歌曲信息t_list = list()trackids = json_line["playlist"]["trackIds"]for one in trackids:t_list.append(str(one["id"]))self.writeToFile(self.trackid_mess + "ids_all1.txt",str(playlist["id"])+"\t"+",".join(t_list))#写入文件def writeToFile(self,filename,one):fw = open(filename,"a",encoding="utf8")fw.write(str(one) + "\n")fw.close()
if __name__ == "__main__":  #主函数print("开始获取歌单信息 ..")pl = PlayList()pl.getEveryPlayListMess()print("歌单信息获取完毕 ... Bye !")

2. 数据处理

本部分包含计算歌曲、歌手、用户相似度和计算用户推荐集。

计算歌曲、歌手、用户相似度

用户在创建歌单时指定了标签,系统认为用户对该标签有偏好,遍历用户创建的所有歌单,会给出标签向量。

例如,若系统中有3个标签(日语、嘻哈、沉默),用户张三在歌单中使用的标签为日语和嘻哈,则其对应的标签向量为[1,1,0],根据用户的标签向量使用杰卡德距离算法计算用户相似度。歌单、歌手、歌曲的相似计算逻辑与用户相似度的计算逻辑相同。相关代码如下:

#计算用户相似度,全量用户存储数据量大,所以这里只存储了20个用户,并且要求相似度大于0.8
def getUserSim(self):sim = dict()if os.path.exists("./data/user_sim.json"):  #路径sim = json.load(open("./data/user_sim.json","r",encoding="utf-8"))else:i = 0for use1 in self.userTags.keys():sim[use1] = dict()for use2 in self.userTags.keys():if use1 != use2:j_len = len (self.userTags[use1] & self.userTags[use2] )if j_len !=0:result = j_len / len(self.userTags[use1] | self.userTags[use2])if sim[use1].__len__() < 20 or result > 0.8:sim[use1][use2] = resultelse:#找到最小值并删除minkey = min(sim[use1], key=sim[use1].get)del sim[use1][minkey]i += 1print(str(i) + "\t" + use1)json.dump(sim, open("./data/user_sim.json","w",encoding="utf-8"))print("用户相似度计算完毕!")return sim
#将计算出的相似度转成导入mysql的格式
def transform(self):fw = open("./data/user_sim.txt","a",encoding="utf-8")for u1 in self.sim.keys():for u2 in self.sim[u1].keys():fw.write(u1 + "," + u2 + "," + str(self.sim[u1][u2]) + "\n")fw.close()print("Over!")

计算用户推荐集

本部分主要介绍用户的协同过滤算法,为用户产生歌曲推荐,与歌单、用户、歌手的推荐算法相似。

(1)创建RecSong类

相关代码如下:

class RecSong:def __init__(self):self.playlist_mess_file = "../tomysql/data/pl_mess_all.txt"self.playlist_song_mess_file = "../tomysql/data/pl_sing_id.txt"self.song_mess_file = "../tomysql/data/song_mess_all.txt"
# 在__init__(self)中指定了所使用的文件

2)构建用户和歌曲的对应关系

用户创建了歌单,歌单中包含歌曲。当用户将一首歌曲归档到歌单中,则认为该首歌曲的评分值为1;如果对同一首歌多次归档,则每次归档评分值加1。相关代码如下:

#加载数据 =>用户对歌曲的对应关系
def load_data(self):#所有用户user_list = list()#歌单和歌曲对应关系playlist_song_dict = dict()for line in open(self.playlist_song_mess_file, "r", encoding="utf-8"):#歌单 \t 歌曲splaylist_id, song_ids = line.strip().split("\t")playlist_song_dict.setdefault(playlist_id, list())for song_id in song_ids.split(","):playlist_song_dict[playlist_id].append(song_id)#print(playlist_sing_dict)print("歌单和歌曲对应关系!")#用户和歌曲对应关系user_song_dict = dict()for line in open(self.playlist_mess_file, "r", encoding="utf-8"):pl_mess_list = line.strip().split(" |=| ")playlist_id, user_id = pl_mess_list[0], pl_mess_list[1]if user_id not in user_list:user_list.append(user_id)user_song_dict.setdefault(user_id, {})for song_id in playlist_song_dict[playlist_id]:user_song_dict[user_id].setdefault(song_id, 0)user_song_dict[user_id][song_id] += 1#print(user_song_dict)print("用户和歌曲对应信息统计完毕 !")return user_song_dict, user_list

3)计算用户相似度

为用户推荐歌曲采用的是基于协同过滤算法,需要计算出用户相似度。计算分为两步:构建倒排表和构建相似度矩阵,计算公式为:

w u v = ∑ i ∈ N ( u ) ∩ N ( v ) 1 lg ⁡ ( 1 + ∣ N ( i ) ∣ ) ∣ N ( u ) ∥ N ( v ) ∣ {w_{u v}}=\frac{\sum_{i \in N(u) \cap N(v)} \frac{1}{\lg (1+|N(i)|)}}{\sqrt{|N(u) \| N(v)|}} wuv=N(u)N(v) iN(u)N(v)lg(1+N(i))1

相关代码如下:

#计算用户之间的相似度,采用惩罚热门商品和优化复杂度的算法
def UserSimilarityBest(self):#得到每个item被哪些user评价过tags_users = dict()for user_id, tags in self.user_song_dict.items():for tag in tags.keys():tags_users.setdefault(tag,set())if self.user_song_dict[user_id][tag] > 0:tags_users[tag].add(user_id)#构建倒排表C = dict()N = dict()for tags, users in tags_users.items():for u in users:N.setdefault(u,0)N[u] += 1C.setdefault(u,{})for v in users:C[u].setdefault(v, 0)if u == v:continueC[u][v] += 1 / math.log(1+len(users))#构建相似度矩阵W = dict()for u, related_users in C.items():W.setdefault(u,{})for v, cuv in related_users.items():if u==v:continueW[u].setdefault(v, 0.0)W[u][v] = cuv / math.sqrt(N[u] * N[v])print("用户相似度计算完成!")return W

4)计算用户对歌曲的可能偏好

遍历所有的相似用户,对于未产生过归档行为的歌曲,计算用户对他们的偏好。相关代码如下:

#为每个用户推荐歌曲
def recommend_song(self):#记录用户对歌手的评分user_song_score_dict = dict()if os.path.exists("./data/user_song_prefer.json"):user_song_score_dict = json.load(open("./data/user_song_prefer.json", "r", encoding="utf-8"))print("用户对歌手的偏好从文件加载完毕!")return user_song_score_dictfor user in self.user_song_dict.keys():print(user)user_song_score_dict.setdefault(user, {})#遍历所有用户for user_sim in self.user_sim[user].keys():if user_sim == user:continuefor song in self.user_song_dict[user_sim].keys():user_song_score_dict[user].setdefault(song,0.0)user_song_score_dict[user][song] += self.user_sim[user][user_sim] * self.user_song_dict[user_sim][song]json.dump(user_song_score_dict, open("./data/user_song_prefer.json", "w", encoding="utf-8"))print("用户对歌曲的偏好计算完成!")return user_song_score_dict

5)写入文件

对每首歌曲的偏好进行排序,将用户最可能产生归档行为的前100首歌曲写入文件,便于导入数据库,供系统使用。相关代码如下:

#写入文件
def write_to_file(self):fw = open("./data/user_song_prefer.txt","a",encoding="utf-8")for user in self.user_song_score_dict.keys():sort_user_song_prefer = sorted(self.user_song_score_dict[user].items(), key=lambda one:one[1], reverse=True)for one in sort_user_song_prefer[:100]:fw.write(user+','+one[0]+','+str(one[1])+'\n')fw.close()print("写入文件完成")

user_song_prefer.txt文件内容如图所示。
在这里插入图片描述

同样,歌单、歌手、用户的推荐结果也通过类似的方式进行计算。

3. 数据存储与后台

在PyCharm中创建新的Django项目及5个模板,即主页、歌单、歌手、歌曲和用户。模板为文本文件,用于分离表现形式和内容。下面以歌单模板为例,介绍各文件用途。Django项目结构如图所示。

在这里插入图片描述

部分文件数据大,使用Navicat软件工具导入,其余部分使用Python代码连接数据库导入。以歌单信息导入数据库为例,Django中创建的Model层相关代码如下:

#歌单信息:歌单ID、创建者ID、名字、创建时间、更新时间、包含音乐数
#播放次数、分享次数、评论次数、收藏次数、标签、歌单封面、描述
class PlayList(models.Model):pl_id = models.CharField(blank=False, max_length=64, verbose_name="ID", unique=True)pl_creator = models.ForeignKey(User, related_name="创建者信息", on_delete=False)pl_name = models.CharField(blank=False, max_length=64, verbose_name="歌单名字")pl_create_time = models.DateTimeField(blank=True, verbose_name="创建时间")pl_update_time = models.DateTimeField(blank=True, verbose_name="更新时间")pl_songs_num = models.IntegerField(blank=True,verbose_name="包含音乐数")pl_listen_num = models.IntegerField(blank=True,verbose_name="播放次数")pl_share_num = models.IntegerField(blank=True,verbose_name="分享次数")pl_comment_num = models.IntegerField(blank=True,verbose_name="评论次数")pl_follow_num = models.IntegerField(blank=True,verbose_name="收藏次数")pl_tags = models.CharField(blank=True, max_length=1000, verbose_name="歌单标签")pl_img_url = models.CharField(blank=True, max_length=1000, verbose_name="歌单封面")pl_desc = models.TextField(blank=True, verbose_name="歌单描述")def __str__(self):return self.pl_idclass Meta:db_table = 'playList'verbose_name_plural = "歌单信息"
#歌单信息写入数据库  
def playListMessToMysql(self):i=0for line in open("./data/pl_mess_all.txt", "r", encoding="utf-8"):pl_id, pl_creator, pl_name, pl_create_time, pl_update_time, pl_songs_num, pl_listen_num, \pl_share_num, pl_comment_num, pl_follow_num, pl_tags, pl_img_url, pl_desc = line.split(" |=| ")try:user = User.objects.filter(u_id=pl_creator)[0]except:user = User.objects.filter(u_id=pl_creator)[0]pl = PlayList(pl_id = pl_id,pl_creator = user,pl_name = pl_name,pl_create_time = self.TransFormTime(int(pl_create_time)/1000),pl_update_time = self.TransFormTime(int(pl_update_time)/1000),pl_songs_num = int (pl_songs_num),pl_listen_num = int( pl_listen_num ),pl_share_num = int( pl_share_num) ,pl_comment_num = int (pl_comment_num),pl_follow_num = int(pl_follow_num),pl_tags = str(pl_tags).replace("[","").replace("]","").replace("\'",""),pl_img_url = pl_img_url,pl_desc = pl_desc)pl.save()i+=1print(i)

执行完毕后,在数据库可视化管理软件Navicat和Django自带的后台管理中可查看对应的数据表,如图1和图2所示。

在这里插入图片描述

图1 Navicat中歌单信息表

在这里插入图片描述

图2 Django后台管理中歌单信息表

最终得到全部数据表,如下两图所示。

在这里插入图片描述

图3 Django后台管理页面一

在这里插入图片描述

图4 Django后台管理页面二

4. 数据展示

前端实现的功能包括:用户登录和选择偏好歌曲、歌手;为你推荐(用户行为不同,推荐也不同) ;进入各页面时基于内容的推荐算法为用户推荐歌单,协同过滤算法为用户推荐歌曲、歌手;单击时获取详细信息,提供单个歌单、歌曲、歌手、用户的推荐;个性化排行榜(将相似度由大到小排序);我的足迹,展示用户在站内的行为(单击时记录)。

(1)Django后台处理前端请求获取推荐标签,View层相关代码。

#首页推荐标签
"""由于标签个数原因,且歌单、歌手、歌曲共用一套标签,这里标签推荐基于1)用户进入系统时的选择2)用户在站内产生的单击行为3)热门标签进行补数
"""
def GetRecTags(request, base_click):#从接口中获取传入的歌手和歌曲IDsings = request.session["sings"].split(",")songs = request.session["songs"].split(",")#歌手标签sings_tags = getSingRecTags(sings, base_click)#歌曲标签songs_tags,pl_tags = getSongAndPlRecTags(songs, base_click)return {"code": 1,"data": {"playlist": {"cateid": 2, "tags": list(pl_tags)},"song": {"cateid": 3, "tags": list(songs_tags)},"sing": {"cateid": 4, "tags": list(sings_tags)},}}
#获得歌曲、歌单标签推荐
def getSongAndPlRecTags(songs, base_click):song_tags = list()pl_tags =  list()#base_click =1 表示用户是在站内产生行为后返回推荐,此时用户行为对象对应的标签排序在前#否则基于用户选择的标签排序在前if base_click == 1: #表示前端是基于单击行为进入为你推荐模块click_songs = UserBrowse.objects.filter(click_cate="3").values("click_id")if click_songs.__len__() != 0:for one in click_songs:filter_one = SongTag.objects.filter(song_id=one["click_id"])if filter_one.__len__() != 0 and filter_one[0].tag not in song_tags:song_tags.append(filter_one[0].tag)#歌单tagpl_one = PlayListToSongs.objects.filter( song_id=filter_one[0].song_id )if pl_one.__len__() !=0:for pl_tag_one in PlayListToTag.objects.filter(pl_id=pl_one[0].song_id):if pl_tag_one.tag not in pl_tags:pl_tags.append(pl_tag_one.tag)if songs.__len__() != 0:  #表示前端选择了相关歌曲for sing in songs:choose_one = SongTag.objects.filter(song_id=sing)if choose_one.__len__() != 0 and choose_one[0].tag not in song_tags:song_tags.append(choose_one[0].tag)#歌单tagpl_one= layListToSongs.objects.filter(song_id=choose_one[0].song_id)if pl_one.__len__() != 0:for pl_tag_one in PlayListToTag.objects.filter(pl_id=pl_one[0].song_id):if pl_tag_one.tag not in pl_tags:pl_tags.append(pl_tag_one.tag)#print("songs_tags_by_click %s" % songs_tags_by_click)#print("pl_tags_by_click %s" % pl_tags_by_click)else:     #表示用户是首次进入为你推荐模块if songs.__len__() != 0:  #表示前端选择了相关歌曲for sing in songs:choose_one = SongTag.objects.filter(song_id=sing)if choose_one.__len__() != 0 and choose_one[0].tag not in song_tags:song_tags.append(choose_one[0].tag)#歌单tagpl_one = PlayListToSongs.objects.filter(song_id=choose_one[0].song_id)if pl_one.__len__() != 0:for pl_tag_one in PlayListToTag.objects.filter(pl_id=pl_one[0].song_id):if pl_tag_one.tag not in pl_tags:pl_tags.append(pl_tag_one.tag)#print("songs_tags_by_choose: %s" % songs_tags_by_choose)#print("pl_tags_by_choose: %s" % pl_tags_by_choose)#如果click和choose的tag不够以hot来补充if song_tags.__len__() < 15:hot_tag_dict = dict()for one in SongTag.objects.all():hot_tag_dict.setdefault(one.tag, 0)hot_tag_dict[one.tag] += 1tag_dict_song = sorted(hot_tag_dict.items(), key=lambda k: k[1], reverse=True)[:15-song_tags.__len__()]for one in tag_dict_song:if one[0] not in song_tags:song_tags.append(one[0])#print("songs_tags_by_hot: %s" % songs_tags_by_hot)#如果 click 和 choose的tag不够,以 hot来补充if pl_tags.__len__() < 15:hot_tag_dict = dict()for one in PlayListToTag.objects.all():hot_tag_dict.setdefault(one.tag, 0)hot_tag_dict[one.tag] += 1tag_dict_pl = sorted(hot_tag_dict.items(), key=lambda k: k[1], reverse=True)[:15-pl_tags.__len__()]for one in tag_dict_pl:if one[0] not in pl_tags:pl_tags.append(one[0])#print("pl_tags_by_hot: %s" % pl_tags_by_hot)return song_tags,pl_tags

(2)进入各页面是基于内容的推荐算法给用户推荐歌单、协同过滤算法推荐歌曲、歌手,这里以歌单为例:

def rec_right_playlist(request):  #推荐歌单user = request.GET.get("username")u_id = User.objects.filter(u_name=user)[0].u_idrec_all = UserPlayListRec.objects.filter(user=u_id).order_by("-sim")[:12]_list = list()for rec in rec_all:one = PlayList.objects.filter(pl_id=rec.related)[0]_list.append({"pl_id": one.pl_id,"pl_creator": one.pl_creator.u_name,"pl_name": one.pl_name,"pl_img_url": one.pl_img_url})return {"code": 1,"data": {"recplaylist": _list}}

(3)单击时获取详细信息,并基于标签进行单个歌单、歌曲、歌手、用户的推荐,这里以用户为例:

def all(request):#接口传入的tag参数tag = request.GET.get("tag")#接口传入的page参数_page_id = int(request.GET.get("page"))print("Tag : %s, page_id: %s" % (tag,_page_id))_list = list()#全部用户if tag == "all":sLists = User.objects.all().order_by("-u_id")#拼接用户信息for one in sLists[(_page_id - 1) * 30:_page_id * 30]:_list.append({"u_id": one.u_id,"u_name": one.u_name,"u_img_url": one.u_img_url})#指定标签下的用户else:sLists = UserTag.objects.filter(tag=tag).values("user_id").order_by("user_id")for sid in sLists[(_page_id - 1) * 30:_page_id * 30]:one = User.objects.filter(u_id=sid["user_id"])if one.__len__() == 1:one = one[0]else:continue_list.append({"u_id": one.u_id,"u_name": one.u_name,"u_img_url": one.u_img_url})total = sLists.__len__()return {"code": 1,"data": {"total": total,"sings": _list,"tags": getAllUserTags()}}
#获取所有用户标签
def getAllUserTags():tags = set()for one in UserTag.objects.all().values("tag").distinct().order_by("user_id"):tags.add(one["tag"])return list(tags)
def one(request):  #处理用户请求u_id = request.GET.get("id")one = User.objects.filter(u_id=u_id)[0]
wirteBrowse(user_name=request.GET.get("username"),click_id=u_id,click_cate="5", user_click_time=getLocalTime(), desc="查看用户")return JsonResponse({"code": 1,"data": [{"u_id": one.u_id,"u_name": one.u_name,"u_birthday":one.u_birthday,"u_gender":one.u_gender,"u_province":one.u_province,"u_city":one.u_city,"u_tags":one.u_tags,"u_img_url": one.u_img_url,"u_sign":one.u_sign,"u_rec": getRecBasedOne(u_id),"u_playlist":getUserCreatePL(u_id)}]})
#获取单个用户的推荐
def getRecBasedOne(u_id):result = list()sim_users = UserSim.objects.filter(user_id=u_id).order_by("-sim").values("sim_user_id")[:10]for user in sim_users:one = User.objects.filter(u_id= user["sim_user_id"])[0]result.append({"id": one.u_id,"name": one.u_name,"img_url": one.u_img_url,"cate":"5"})return result
#获取用户创建的歌单
def getUserCreatePL(uid):pls = PlayList.objects.filter(pl_creator__u_id=uid)result = list()for one in pls:result.append({"pl_id": one.pl_id,"pl_name":one.pl_name,"pl_creator": one.pl_creator.u_name,"pl_create_time": one.pl_create_time,"pl_img_url": one.pl_img_url,"pl_desc":one.pl_desc})return result
#用户浏览信息进行记录
"""user_name = models.CharField(blank=False, max_length=64, verbose_name="用户名")click_id = models.CharField(blank=False, max_length=64, verbose_name="ID")click_cate = models.CharField(blank=False, max_length=64, verbose_name="类别")user_click_time = models.DateTimeField(blank=False, verbose_name="浏览时间")desc = models.CharField(blank=False, max_length=1000, verbose_name="备注",default="Are you ready!")
"""
def wirteBrowse(user_name="",click_id="",click_cate="",user_click_time="",desc=""):if "12797496" in click_id: click_id = "12797496"UserBrowse(user_name=user_name,click_id=click_id,click_cate=click_cate,user_click_time = user_click_time,desc=desc).save()print("用户【 %s 】的行为记录【 %s 】写入数据库" % (user_name, desc))
#获取当前格式化的系统时间
def getLocalTime():return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

系统测试

本部分包括系统流程和测试效果。

(1)选择用户进入系统。每次随机从数据库中返回部分作为系统用户,使用不同的用户是为了区分行为偏好,如图所示。

在这里插入图片描述

(2)选择歌手、歌曲(3个及以上,可以跳过)。用户与系统交互的过程,解决系统的冷启动。当然用户也可以不选择歌手,直接跳过,此时系统中“为你推荐歌手标签部分为热度标签数据。界面如下两图所示。

在这里插入图片描述

在这里插入图片描述

(3)根据用户创建歌单的偏好,推荐用户偏好的歌单、歌曲的。单击标签可以查看相应标签下的所有歌曲,分别进入歌单、歌曲、歌手推荐页面,如图所示。

在这里插入图片描述

(4)歌单推荐页面。左侧为按照标签分类的全部歌单,右侧为基于内容的推荐算法为用户推荐的歌单,如图所示。

在这里插入图片描述

(5) 歌单详情页。包含歌单的详细信息和歌单内的歌曲,右侧为基于标签相似度提供的歌单推荐,如图所示。

在这里插入图片描述

(6) 歌曲推荐页面。左侧为按照标签分类的全部歌曲,右侧为基于协同过滤算法为用户推荐的歌曲,如图所示。

在这里插入图片描述

(7)歌曲详情页。包含歌曲的信息和歌词,右侧为基于标签相似度提供的歌单推荐,如图所示 。

在这里插入图片描述

(8)歌手推荐页面。左侧为按照标签分类的全部歌手,右侧为基于协同过滤算法为用户推荐的歌曲,如图所示。

在这里插入图片描述

(9)歌手详情页。包含歌手的信息和歌曲,右侧为基于标签相似度提供的歌手推荐,如图所示。

在这里插入图片描述

(10)用户推荐页面。左侧为按照标签分类的全部用户,右侧为基于协同过滤算法为用户推荐的用户,如图所示。

在这里插入图片描述

(11) 用户详情页。包含用户的信息和创建的歌单,右侧为基于标签相似度提供的推荐,如图所示 。

在这里插入图片描述

(12) 个性化排行榜。基于用户的偏好程度(协同过滤算法计算的结果)进行排序展示,不同用户看到的显示界面不同,如图5~图8所示。

在这里插入图片描述

图5 个性化推荐排行榜页面

在这里插入图片描述

图6 歌单推荐排行榜页面

在这里插入图片描述

图7 歌曲推荐排行榜页面

在这里插入图片描述

图8 歌手推荐排行榜页面

(13) 我的足迹。浏览歌单、歌曲、歌手时用户在系统中产生的行为记录,如图所示。

在这里插入图片描述

工程源代码下载

详见本人博客资源下载页


其它资料下载

如果大家想继续了解人工智能相关学习路线和知识体系,欢迎大家翻阅我的另外一篇博客《重磅 | 完备的人工智能AI 学习——基础知识学习路线,所有资料免关注免套路直接网盘下载》
这篇博客参考了Github知名开源平台,AI技术平台以及相关领域专家:Datawhale,ApacheCN,AI有道和黄海广博士等约有近100G相关资料,希望能帮助到所有小伙伴们。

相关文章:

基于Mysql+Vue+Django的协同过滤和内容推荐算法的智能音乐推荐系统——深度学习算法应用(含全部工程源码)+数据集

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境MySQL环境VUE环境 模块实现1. 数据请求和储存2. 数据处理计算歌曲、歌手、用户相似度计算用户推荐集 3. 数据存储与后台4. 数据展示 系统测试工程源代码下载其它资料下载 前言 本项目以丰富的网易云音乐数据为基…...

Python Web开发 Django 简介

今天来为大家介绍 Python 另一个 Web 开发框架 Django&#xff0c;它是一个基于 Python 定制的开源 Web 应用框架&#xff0c;最早源于一个在线新闻 Web 网站&#xff0c;后于2005年开源。Django 的功能大而全&#xff0c;它提供的一站式解决的思路&#xff0c;能让开发者不用在…...

HAproxy搭建web集群

目录 一、HAproxy 概述 二、HAproxy 主要特性 三、HAproxy 负载均衡策略(八种) 四、LVS、Nginx、HAproxy区别 Nginx LVS HAproxy 五、HAproxy部署实战 问题总结&#xff1a; 一、HAproxy 概述 HAProxy是可提供高可用性、负载均衡以及基于TCP和HTTP应用的代理&#xff0…...

临时用工小程序:一款便捷的用工管理软件

随着企业对人力资源需求的不断增长&#xff0c;临时用工需求也日益旺盛。为了满足这一需求&#xff0c;我们研发了一款名为“临时用工小程序”的软件系统&#xff0c;旨在帮助企业实现临时用工的高效管理。 一、技术栈介绍 后端技术栈 本系统采用Java语言作为开发语言&#…...

Android Studio 之 Android 中使用 HanLP 进行句子段落的分词处理(包括词的属性处理)的简单整理

Android Studio 之 Android 中使用 HanLP 进行句子段落的分词处理&#xff08;包括词的属性处理&#xff09;的简单整理 目录 Android Studio 之 Android 中使用 HanLP 进行句子段落的分词处理&#xff08;包括词的属性处理&#xff09;的简单整理 一、简单介绍 二、实现原理…...

CSDN编程题-每日一练(2023-08-20)

CSDN编程题-每日一练(2023-08-19) 一、题目名称:等差数列二、题目名称:喜水青蛙三、题目名称:括号匹配一、题目名称:等差数列 时间限制:1000ms内存限制:256M 题目描述: 给定一已排序的正整数组成的数组,求需要在中间至少插入多少个数才能将其补全成为一等差数列。 “…...

大数据:NumPy进阶应用详解

专栏介绍 结合自身经验和内部资料总结的Python教程&#xff0c;每天3-5章&#xff0c;最短1个月就能全方位的完成Python的学习并进行实战开发&#xff0c;学完了定能成为大佬&#xff01;加油吧&#xff01;卷起来&#xff01; 全部文章请访问专栏&#xff1a;《Python全栈教…...

new String创建几个对象

在java17中 &#xff1a; 问题1&#xff1a;new String("abc")会产生多少个对象&#xff1f; 分两种情况&#xff1a; 情况1&#xff1a; 如果”abc”这个字符串常量不存在&#xff0c;则创建两个对象&#xff0c;分别是“abc”这个字符串常量&#xff0c;以及ne…...

【路由协议】使用按需路由协议和数据包注入的即时网络模拟传递率(PDR)、总消耗能量和节点消耗能量以及延迟研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

c#实现依赖注入

当谈到C#中的依赖注入(Dependency Injection,DI)时,我们可以使用一个简单的示例来说明它是如何工作的。依赖注入是一种设计模式,用于将依赖关系从一个类传递到另一个类,以实现松耦合和可测试性。 假设我们有一个简单的订单处理应用程序,其中包含两个主要类:OrderServi…...

算法通关村十一关 | 位运算实现加法和乘法

1.位实现加法和乘法 在计算机中&#xff0c;位运算的效率要比加减乘除的效率更高&#xff0c;因此在高性能软件中源码中大量使用&#xff0c;计算机里各种运算基本上都是位运算。 学习下面内容之前建议先学习位运算规则&#xff1a;算法通关村十一关 | 位运算的规则_我爱学算…...

C++笔记之条件变量(Condition Variable)与cv.wait 和 cv.wait_for的使用

C笔记之条件变量&#xff08;Condition Variable&#xff09;与cv.wait 和 cv.wait_for的使用 参考博客&#xff1a;C笔记之各种sleep方法总结 code review! 文章目录 C笔记之条件变量&#xff08;Condition Variable&#xff09;与cv.wait 和 cv.wait_for的使用1.条件变量&…...

Dubbo之DubboBootstrap源码解析

功能描述 DubboBootstrap是Dubbo的启动类&#xff0c;包含服务启动、初始化、预处理配置、销毁清理等核心功能 功能分析 核心DubboBootstrap类分析 主要成员变量分析 private static volatile DubboBootstrap instance; //缓存者启动类的实例对象&#xff0c;以static形式…...

SpringBoot + Vue 微人事 项目 (第八天)

基础信息设置 在该页面添加一个大div&#xff0c;然后添加一个tab选项卡&#xff0c;Element UI里面有 把代码复制到大div里面&#xff0c;把里面的label和name属性改成我们想要的&#xff0c;再把tab-click"handleClick"去掉 <div><el-tabs v-model"a…...

人工智能引领图文扫描新趋势

1. 背景和影响 近日&#xff0c;中国大学生服务外包创新创业大赛决赛在江南大学圆满落幕。为满足现代服务产业企业的现实需求&#xff0c;本次竞赛内容设计充分聚焦企业发展中所面临的技术、管理等现实问题&#xff0c;与产业的结合度更紧密&#xff0c;智能文字识别技术是大赛…...

ChatGPT在智能城市规划和交通优化中的应用如何?

智能城市规划和交通优化是应对城市化挑战、提高城市可持续性的重要领域。在这方面&#xff0c;ChatGPT作为一种强大的自然语言处理模型&#xff0c;可以发挥重要作用&#xff0c;帮助实现更智能、高效的城市规划和交通管理。本文将详细探讨ChatGPT在智能城市规划和交通优化中的…...

探索Perfetto:开源性能追踪工具的未来之光

探索Perfetto&#xff1a;开源性能追踪工具的未来之光 1. 引言 A. 介绍Perfetto的背景和作用 随着移动应用、桌面软件和嵌入式系统的不断发展&#xff0c;软件性能优化变得愈发重要。在这个背景下&#xff0c;Perfetto作为一款开源性能追踪工具&#xff0c;日益引起了开发者…...

A*算法图文详解

基本概念 A*算法最早于1964年在IEEE Transactions on Systems Science and Cybernetics中的论文《A Formal Basis for the Heuristic Determination of Minimum Cost Paths》中首次提出。其属于一种经典的启发式搜索方法&#xff0c;所谓启发式搜索&#xff0c;就在于当前搜索…...

[MySQL] — 数据类型和表的约束

目录 数据类型 数据类型分类 数值类型 tinyint类型 bit类型 小数类型 float decimal 字符串类型 char varchar char和varchar的区别 日期和时间类型 enum 和 set 表的约束 空属性 默认值 列描述 zeorfill 主键 创建表时在字段上指定主键 删除主键&#xff1a; 追…...

JetBrains IDE远程开发功能可供GitHub用户使用

JetBrains与GitHub去年已达成合作&#xff0c;提供GitHub Codespaces 与 JetBrains Gateway 之间的集成。 GitHub Codespaces允许用户创建安全、可配置、专属的云端开发环境&#xff0c;此集成意味着您可以通过JetBrains Gateway使用在 GitHub Codespaces 中运行喜欢的IDE进行…...

LVS 负载均衡集群

集群 集群&#xff08;Cluster&#xff09;是一组相互连接的计算机或服务器&#xff0c;它们通过网络一起工作以完成共同的任务或提供服务。集群的目标是通过将多台计算机协同工作&#xff0c;提高计算能力、可用性、性能和可伸缩性&#xff0c;适用于大量高并发的场景。 集群…...

Mongodb Ubuntu安装

Mongodb Ubuntu安装 1.更新软件源导入MongoDB的GPG密钥 sudo apt update sudo apt install -y dirmngr wget gnupg apt-transport-https ca-certificates software-properties-common gnupgwget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add…...

【Spring Boot 源码学习】自动装配流程源码解析(下)

自动装配流程源码解析&#xff08;下&#xff09; 引言往期内容主要内容4. 排除指定自动配置组件5. 过滤自动配置组件6. 触发自动配置事件 总结 引言 上篇博文&#xff0c;笔者带大家了解了自动装配流程中有关自动配置加载的流程&#xff1b; 本篇将介绍自动装配流程剩余的内…...

基于微信小程序的毕业设计题目200例

个人简介&#xff1a;7 年大厂程序员经历&#xff0c;擅长Java、微信小程序、Python、Android等&#xff0c;大家有这一块的问题可以一起交流&#xff01; 各类成品 java毕设 。javaweb&#xff0c;ssh&#xff0c;ssm&#xff0c;springboot等等项目框架&#xff0c;源码丰富&…...

【数据管理】什么是数据管理?

文章目录 前言常见内容主题领域数据类型元数据引用数据主数据交易数据 数据类型的特点数据类型之间的关系GIGO数据质量评估 数据质量管理数据治理数据安全 前言 数据管理&#xff0c;即对数据资源的管理。按照 DAMA &#xff08;国际数据管理协会&#xff09;的定义&#xff1…...

[oneAPI] 手写数字识别-LSTM

[oneAPI] 手写数字识别-LSTM 手写数字识别参数与包加载数据模型训练过程结果 oneAPI 比赛&#xff1a;https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517 Intel DevCloud for oneAPI&#xff1a;https://devcloud.intel.com/oneapi/get_started/aiAnalyticsToolk…...

通过css设置filter 属性,使整个页面呈现灰度效果,让整个网页变灰

通过css设置filter 属性设置页面整体置灰 效果图: 通过设置 filter 属性为 grayscale(100%)&#xff0c;页面中的所有元素都会被应用灰色滤镜效果&#xff0c;使整个页面呈现灰度效果。 <style type"text/css"> html { filter: grayscale(100%); -webkit-f…...

ahooks.js:一款强大的React Hooks库及其API使用教程(一)

一、ahooks.js简介二、ahooks.js安装三、ahooks.js API介绍与使用教程1. useRequest2. useAntdTable3. useSize4. useBoolean5. useToggle6. useHover7. useDebounce8. useEventListener9. useFusionTable10. useKeyPress11. useLoading12. usePrevious13. useForm14. useUpdat…...

拟合圆算法源码(商业)

1、输入一些点 2、执行fitCircle算法 3、输出圆心(x,y)及半径r Box fitCircle(const std::vector<cv::Point2f>& points) {Box box;box.x = 0.0f;box.y = 0.0f;box.r = 0.0f;if (points.size() < 3){return box;}int i = 0;double X1 = 0;double Y1 = 0;doubl…...

第一章 IRIS 编程简介

文章目录 第一章 IRIS 编程简介简介ClassesRoutines 第一章 IRIS 编程简介 简介 IRIS 是一个高性能多模型数据平台&#xff0c;具有内置的通用编程语言 ObjectScript&#xff0c;以及对 Python 的内置支持。 IRIS 支持多进程并提供并发控制。每个进程都可以直接、高效地访问…...

企业为什么需要手机网站/2022今日最新军事新闻

简介 概述&#xff1a;哨兵模式是主从的升级版&#xff0c;因为主从的出现故障后&#xff0c;不会自动恢复&#xff0c;需要人为干预&#xff0c;这就很麻烦。在主从的基础上&#xff0c;实现哨兵模式就是为了监控主从的运行状况&#xff0c;对主从的健壮进行监控&#xff0c;就…...

做360手机网站快/百度入口网页版

在 Linux 或者 macOS 的命令行环境下运行下面的命令安装 rustup&#xff1a; curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh已经安装 rustc 到 ~/.cargo/bin 目录 source $HOME/.cargo/env查看rustc 版本 rustc --version2. rust 配置清华镜像 新建&#x…...

品牌网站设计哪家好/北京网络营销

C语言中求绝对值的函数为abs(),在C中对函数abs()进行了重载。 这个函数被封装进了cmath&#xff0c;在使用的时候需要把它包含进来&#xff1a; 例如&#xff1a;#include<cmath> //C语言是math.h...

电力建设监理招聘网站/青岛seo网络推广

实现思路&#xff1a;1、 v-model 一个收集所有input(除全选框外)数组checkModel &#xff0c;vue会动态将其checked为true的input的value值存入数组checkModel里2 、watch函数来监听checkModel 属性&#xff0c;当其长度input元素时 全选按钮选中 否则取消3 、全选按钮v-model…...

域名备案的网站名称/网站开发的基本流程

我没有能够得到任何这些解决方案的工作。我的目标是在一个笔记本上生成地块&#xff0c;并将它们发布到另一个笔记本中&#xff0c;因此坚持HTML的情节对于我来说并不重要&#xff0c;因为它只是有一些将剧情序列化到磁盘以在其他地方重建的方法。 我想出的解决方案是将fig对象…...

十大流量平台/百度seo引流

Quartz中时间表达式的设置-----corn表达式时间格式: , 分别对应: 秒>分>小时>日>月>周>年,举例:1.每天什么时候执行:0 59 23 * * ?: 如下为每天23:59:00开始执行0 1,2,3 11,12 * * ? : 每天11:01,11:02,11:03; 12:01,12:02,12:03分执行任务2.每隔多久执行…...