python利用网易云音乐接口搭建的音乐推荐,根据单曲歌名推荐相关用户喜爱的歌曲
2017-07-29 17:34
856 查看
一、网易云音乐的相关接口
这边我想要的数据接口有:
* 网易的搜索功能,根据歌名获取歌曲的id
* 歌曲相关的评论用户接口
* 用户的相关数据包括歌单或听歌记录,这边听歌记录的接口好像不能用,所以我就用的歌单接口
关于每个接口大家可以自己F12网易官网看看是长什么样子,网易的新接口加密方式我也是在网上找的资料。
这边就是接口部分的代码:
这边我获取这首歌的所有热门评论用户以及他们的歌单,在获取所有歌单的数据,将歌单中的所有歌曲根据歌单的听取次数、订阅人数、歌曲的听取次数等等进行加权评分,奖所有的歌曲按照分数高低选取其中前30首进行推荐
下面就是评分的代码:
为了可以方便输入某首歌名从而进行推荐,我写了一个简单的操作界面,tkinter库,比较丑,这个库不怎么会用,没有怎么写过界面
界面以及事件代码:
这边我想要的数据接口有:
* 网易的搜索功能,根据歌名获取歌曲的id
* 歌曲相关的评论用户接口
* 用户的相关数据包括歌单或听歌记录,这边听歌记录的接口好像不能用,所以我就用的歌单接口
关于每个接口大家可以自己F12网易官网看看是长什么样子,网易的新接口加密方式我也是在网上找的资料。
这边就是接口部分的代码:
import requests import json import os import base64 import binascii from Crypto.Cipher import AES class NetEaseAPI: def __init__(self): self.header = { 'Accept': '*/*', 'Accept-Encoding': 'gzip,deflate,sdch', 'Accept-Language': 'zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4', 'Connection': 'keep-alive', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'music.163.com', 'Referer': 'http://music.163.com/search/', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36' # NOQA } self.cookies = {'appver': '1.5.2'} self.playlist_class_dict = {} self.session = requests.Session() def httpRequest(self, method, action, query=None, urlencoded=None, callback=None, timeout=None): connection = json.loads(self.rawHttpRequest(method, action, query, urlencoded, callback, timeout)) return connection def rawHttpRequest(self, method, action, query=None, urlencoded=None, callback=None, timeout=None): if method == 'GET': url = action if query is None else action + '?' + query connection = self.session.get(url) elif method == 'POST': connection = self.session.post(action, query, self.header) elif method == 'Login_POST': connection = self.session.post(action, query, self.header) self.session.cookies.save() connection.encoding = 'UTF-8' return connection.text def search(self, s, stype=1, offset=0, total='true', limit=1): action = 'http://music.163.com/api/search/get' data = { 's': s, 'type': stype, 'offset': offset, 'total': total, 'limit': limit } return self.httpRequest('POST', action, data) def aesEncrypt(self, text, secKey): pad = 16 - len(text) % 16 text = text + chr(pad) * pad encryptor = AES.new(secKey, 2, '0102030405060708') ciphertext = encryptor.encrypt(text) ciphertext = base64.b64encode(ciphertext).decode('utf-8') return ciphertext def rsaEncrypt(self, text, pubKey, modulus): text = text[::-1] rs = pow(int(binascii.hexlify(text), 16), int(pubKey, 16), int(modulus, 16)) return format(rs, 'x').zfill(256) def createSecretKey(self,size): return (''.join(map(lambda xx: (hex(ord(xx))[2:]), os.urandom(size))))[0:16] def encrypted_request(self, text): modulus = ('00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7' 'b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280' '104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932' '575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b' '3ece0462db0a22b8e7') nonce = '0CoJUm6Qyw8W8jud' pubKey = '010001' text = json.dumps(text) secKey = binascii.hexlify(os.urandom(16))[:16] encText = self.aesEncrypt(self.aesEncrypt(text, nonce), secKey) encSecKey = self.rsaEncrypt(secKey, pubKey, modulus) data = {'params': encText, 'encSecKey': encSecKey} return data def getComment(self, songId, offset=0, total='fasle', limit=100): action = 'http://music.163.com/api/v1/resource/comments/R_SO_4_{}/?rid=R_SO_4_{}&\ offset={}&total={}&limit={}'.format(songId, songId, offset, total, limit) comments = self.httpRequest('GET', action) return comments['hotComments'] def getPlaylist(self, uid): text = { 'uid': uid, 'limit':100 } text = json.dumps(text) nonce = '0CoJUm6Qyw8W8jud' pubKey = '010001' modulus = ('00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7' 'b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280' '104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932' '575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b' '3ece0462db0a22b8e7') secKey = self.createSecretKey(16) encText = self.aesEncrypt(self.aesEncrypt(text, nonce), secKey) encSecKey = self.rsaEncrypt(secKey, pubKey, modulus) data = { 'params': encText, 'encSecKey': encSecKey } action = 'http://music.163.com/weapi/user/playlist?csrf_token=' playlist = self.httpRequest('POST', action, data) res = list() for play in playlist['playlist']: res.append({'id':play['id'],'subscribedCount':play['subscribedCount'],'playCount':play['playCount']}) return res def getPlaylistDetail(self, id): text = { 'id': id, 'limit':100, 'total':True } text = json.dumps(text) nonce = '0CoJUm6Qyw8W8jud' pubKey = '010001' modulus = ('00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7' 'b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280' '104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932' '575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b' '3ece0462db0a22b8e7') secKey = self.createSecretKey(16) encText = self.aesEncrypt(self.aesEncrypt(text, nonce), secKey) encSecKey = self.rsaEncrypt(secKey, pubKey, modulus) data = { 'params': encText, 'encSecKey': encSecKey } action = 'http://music.163.com/weapi/v3/playlist/detail?csrf_token=' playlistDetail = self.httpRequest('POST', action, data) music = list() musicCount = dict() for count in playlistDetail['playlist']['trackIds']: musicCount[count['id']] = count['v'] for detail in playlistDetail['playlist']['tracks']: singer = '' for author in detail['ar']: singer += author['name']+',' music.append({'id':detail['id'],'name':detail['name'],'singer':singer, 'playCount':musicCount[detail['id']]}) return music二、推荐的逻辑
这边我获取这首歌的所有热门评论用户以及他们的歌单,在获取所有歌单的数据,将歌单中的所有歌曲根据歌单的听取次数、订阅人数、歌曲的听取次数等等进行加权评分,奖所有的歌曲按照分数高低选取其中前30首进行推荐
下面就是评分的代码:
from __future__ import division import time from NetEaseAPI import * class musicRecom(): def getSongId(self,musicTitle): res = NetEaseAPI().search(musicTitle) return res[' 4000 result']['songs'][0]['id'] def musicRank(self,musicDict): maxSubCount = 0 maxLsitCount = 0 maxMusicCount = 0 for music in musicDict: if musicDict[music]['listSubscribedCount'] > maxSubCount : maxSubCount = musicDict[music]['listSubscribedCount'] if musicDict[music]['listCount'] > maxLsitCount : maxLsitCount = musicDict[music]['listCount'] if musicDict[music]['musicPlayCount'] > maxMusicCount : maxMusicCount = musicDict[music]['musicPlayCount'] for music in musicDict: musicDict[music]['score'] = musicDict[music]['listSubscribedCount'] / maxSubCount + musicDict[music]['listCount'] / maxLsitCount + musicDict[music]['musicPlayCount'] / maxMusicCount return sorted(musicDict.items(), key = lambda d:d[1]['score'], reverse = True)三、界面
为了可以方便输入某首歌名从而进行推荐,我写了一个简单的操作界面,tkinter库,比较丑,这个库不怎么会用,没有怎么写过界面
界面以及事件代码:
from __future__ import division from Tkinter import * import Tkinter import ttk from musicRecom import * import threading class GUI(Frame): def __init__(self, master = None): Frame.__init__(self, master) self.pack() self.create() def progress(self,count1,count2): self.len1.set(count1) self.len2.set(count2) def search(self): musicTitle = self.musicTitle.get() if musicTitle == '': print "Please input the music title!" else: self.len1 = StringVar() self.len2 = StringVar() self.scale1 = Scale(self,from_ = 0, to = 100, resolution = 0.1, orient = HORIZONTAL, variable = self.len1, length = 500 ).grid(row = 2,column=0, columnspan=4, padx = 5) self.scale2 = Scale(self,from_ = 0, to = 100, resolution = 0.1, orient = HORIZONTAL, variable = self.len2, length = 500 ).grid(row = 3,column=0, columnspan=4, padx = 5) threading.Thread(target = self.musicRecom).start() def musicRecom(self): self.searchButton.destroy() musicTitle = self.musicTitle.get() res = dict() songId = musicRecom().getSongId(musicTitle) time.sleep(1) comment = NetEaseAPI().getComment(songId) time.sleep(1) count1 = 0 for user in comment: count1 = count1 + 1 uid = user['user']['userId'] playlist = NetEaseAPI().getPlaylist(uid) time.sleep(1) count2 = 0 for table in playlist: count2 = count2 + 1 musicDetail = NetEaseAPI().getPlaylistDetail(table['id']) time.sleep(1) self.progress(count1/len(comment)*100,count2/len(playlist)*100) for music in musicDetail: res[music['id']]={'id':music['id'],'name':music['name'],'singer':music['singer'],'musicPlayCount':int(music['playCount']),'listCount':int(table['playCount']),'listSubscribedCount':int(table['subscribedCount'])} self.res = musicRecom().musicRank(res) self.maxPage = 4 self.page = 1 self.nextButton = Button(self, text='Pre', command=self.Pre) self.nextButton.grid(row = 4,column = 1, padx=5, pady=5) self.nextButton = Button(self, text='Next', command=self.Next) self.nextButton.grid(row = 4,column = 2, padx=5, pady=5) self.frame = Frame(self) self.frame.grid(row = 5,columnspan=4) self.getCont() def getCont(self): index = 1 num = 0 self.frame.destroy() self.frame = Frame(self) self.frame.grid(row = 5,columnspan=4) for item in self.res: num = num + 1 if num > self.page * 15: break if num <= self.page * 15 and num > (self.page - 1) * 15: Label(self.frame, text=index + (self.page - 1) * 15).grid(row = index + 4,column=0) Label(self.frame, text=item[1]['name'].encode('utf8')).grid(row = index + 4,column=1) Label(self.frame, text=item[1]['id']).grid(row = index + 4,column=2) Label(self.frame, text=item[1]['singer'].encode('utf8')).grid(row = index + 4,column=3) index = index + 1 def Next(self): if self.page < self.maxPage: self.page = self.page + 1 else: self.page = 1 self.getCont() def Pre(self): if self.page > 1: self.page = self.page - 1 else: self.page = self.maxPage self.getCont() def create(self): self.labelName = Label(self, text = "Please input the music name:") self.labelName.grid(row = 0, column = 0) self.musicTitle = StringVar() self.inputName = Entry(self, textvariable = self.musicTitle, width=50) self.inputName.grid(row = 0, column = 1, columnspan=3, padx=5, pady=5) self.searchButton = Button(self, text='Search', command=self.search) self.searchButton.grid(row = 1,column = 1, padx=5, pady=5)四、主调度
#!/usr/bin/env python # -*- coding: UTF-8 -*- # from Crawler import * import sys from GUI import * default_encoding = 'utf-8' if sys.getdefaultencoding() != default_encoding: reload(sys) sys.setdefaultencoding(default_encoding) def main(): root = Tkinter.Tk() app = GUI(root) root.geometry('640x560') root.resizable(False, False) app.master.title('网易云音乐的歌曲推荐') app.mainloop() if __name__ == "__main__": main()五、测试结果
相关文章推荐
- 利用python对新浪微博用户标签进行分词并推荐相关用户
- 利用python对新浪微博用户标签进行分词并推荐相关用户
- 利用python对新浪微博用户标签进行分词并推荐相关用户
- 【Python】寻找电影品味相似的用户并推荐相关电影
- 使用python一步一步搭建微信公众平台(三)----添加用户关注后的欢迎信息与听音乐功能
- 利用Python搭建用户画像系统
- 利用Rsyslog集中收集系统日志和用户操作记录以及相关处理方法 推荐
- 【Python】寻找电影品味相似的用户并推荐相关电影
- JINGFM: 根据用户描述推荐音乐的创新型WEB APP
- [置顶] 利用Python爬取基于AES对称加密算法的网易云音乐用户评论数据
- Python文件夹与文件的相关操作(推荐)
- 基于用户协同过滤的推荐系统算法,python 实现
- 利用docker搭建gitlab代码仓库 推荐
- 使用AsyncTask弹出进度条ProgressDialog,利用网上的某音乐地址下载歌曲
- 一个利用python从中科大音乐网站下载mp3的程序
- 推荐系统方法(利用用户行为数据)
- python爬虫----网易云音乐歌曲爬取并存入Excel
- centos 音乐相关软件(timidity,ffmpeg,lame),Python相关(music21)安装及使用
- python 相关的书籍推荐
- python 根据菜单对tar进行相关操作