利用Python简单实现网易云用户算法推荐系统

笔者最近面试到了网易新闻推荐部门 , 考了一点推荐系统的知识 , 算是被虐惨了 。 于是乎自己怒补了一些知识 。 记录一点关于推荐系统的知识和实现 。音乐推荐系统 , 这里的简单指的是数据量级才2万条 , 之后会详细解释 。
私信小编01即可获取大量Python编程资源
1. 推荐系统工程师人才成长RoadMap
利用Python简单实现网易云用户算法推荐系统文章插图
2. 1. 数据的获取任何的机器学习算法解决问题 , 首先就是要考虑的是数据 , 数据从何而来? 对于网易云音乐这样的企业而言 , 用户的收藏和播放数据是可以直接获得的 , 我们找一个取巧的方式 , 包含用户音乐兴趣信息 , 同时又可以获取的数据是什么?
对的 , 是热门歌单信息 , 以及歌单内歌曲的详细信息 。
利用Python简单实现网易云用户算法推荐系统文章插图
利用Python简单实现网易云用户算法推荐系统文章插图
利用Python简单实现网易云用户算法推荐系统文章插图
?
3. 数据爬虫脚本代码说明: 1. 网易云音乐网络爬虫由于加了数据包传动态参数的反爬措施 。 拿到歌单数据包的难度很大 。 一大神破解了传参动态密码 , 代码中AES算法 。2. 但是不知道为什么这个python2.7版下脚本只能爬取每个歌单里面的10首歌 , 由于这个原因 , 导致我们的推荐系统原始数据量级骤然降低 。 笔者试了很久 , 也没有办法 。 望大家给点建议 。 不管怎样 , 数据量小 , 那咱们就简单实现就好 。3. 一共1921个歌单(json文件) , 每个歌单里面包含10首歌 , 所以咱们后面建模的数据量实际只有2W左右的实例 。
# -*- coding:utf-8 -*-"""爬虫爬取网易云音乐歌单的数据包保存成json文件python2.7环境"""import requestsimport jsonimport osimport base64import binasciiimport urllibimport urllib2from Crypto.Cipher import AESfrom bs4 import BeautifulSoupclass NetEaseAPI:def __init__(self):self.header = {'Host': 'music.163.com','Origin': '','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0','Accept': 'application/json, text/javascript','Accept-Language': 'zh-CN,zh;q=0.9','Connection': 'keep-alive','Content-Type': 'application/x-www-form-urlencoded',}self.cookies = {'appver': '1.5.2'}self.playlist_class_dict = {}self.session = requests.Session()def _http_request(self, method, action, query=None, urlencoded=None, callback=None, timeout=None):connection = json.loads(self._raw_http_request(method, action, query, urlencoded, callback, timeout))return connectiondef _raw_http_request(self, method, action, query=None, urlencoded=None, callback=None, timeout=None):if method == 'GET':request = urllib2.Request(action, self.header)response = urllib2.urlopen(request)connection = response.read()elif method == 'POST':data = http://kandian.youth.cn/index/urllib.urlencode(query)request = urllib2.Request(action, data, self.header)response = urllib2.urlopen(request)connection = response.read()return connection@staticmethoddef _aes_encrypt(text, secKey):pad = 16 - len(text) % 16text = text + chr(pad) * padencryptor = AES.new(secKey, 2,'0102030405060708')ciphertext = encryptor.encrypt(text)ciphertext = base64.b64encode(ciphertext).decode('utf-8')return ciphertext@staticmethoddef _rsa_encrypt(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)@staticmethoddef _create_secret_key(size):return (''.join(map(lambda xx: (hex(ord(xx))[2:]), os.urandom(size))))[0:16]def get_playlist_id(self, action):request = urllib2.Request(action, headers=self.header)response = urllib2.urlopen(request)html = response.read().decode('utf-8')response.close()soup = BeautifulSoup(html, 'lxml')list_url = soup.select('ul#m-pl-container li div a.msk')for k, v in enumerate(list_url):list_url[k] = v['href'][13:]return list_urldef get_playlist_detail(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._create_secret_key(16)encText = self._aes_encrypt(self._aes_encrypt(text, nonce), secKey)encSecKey = self._rsa_encrypt(secKey, pubKey, modulus)data = http://kandian.youth.cn/index/{'params': encText,'encSecKey': encSecKey}action = ''playlist_detail = self._http_request('POST', action, data)return playlist_detailif __name__ == '__main__':nn = NetEaseAPI()index = 1for flag in range(1, 38):if flag > 1:page = (flag - 1) * 35url = ';cat=%E5%85%A8%E9%83%A8&limit=35&offset=' + str(page)else:url = ''playlist_id = nn.get_playlist_id(url)for item_id in playlist_id:playlist_detail = nn.get_playlist_detail(item_id)with open('{0}.json'.format(index), 'w') as file_obj:json.dump(playlist_detail, file_obj, ensure_ascii=False)index += 1print("写入json文件:", item_id)


推荐阅读