def run(username, password): try: lg = login.Login() _, session = lg.music163(username, password) csrf = re.findall('__csrf=(.*?) for', str(session.cookies))[0] cracker = Cracker() headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36', 'Content-Type': 'application/x-www-form-urlencoded', 'Referer': 'http://music.163.com/discover', 'Accept': '*/*' } signin_url = 'https://music.163.com/weapi/point/dailyTask?csrf_token=' + csrf # 模拟签到(typeid为0代表APP上签到, 为1代表在网页上签到) typeids = [0, 1] for typeid in typeids: client_name = 'Web端' if typeid == 1 else 'APP端' # --构造请求获得响应 data = {'type': typeid} data = cracker.get(data) res = session.post(signin_url, headers=headers, data=data) res_json = res.json() # --判断签到是否成功 if res_json['code'] == 200: print('账号%s在%s签到成功...' % (username, client_name)) else: print('账号%s在%s签到失败, 原因: %s...' % (username, client_name, res_json.get('msg'))) except Exception as e: requests.get( 'https://sc.ftqq.com/sever酱密钥.send?text=网易云签到脚本运行失败&desp=具体情况未知')
def __init__(self, username, password, **kwargs): self.userid, self.session = NeteaseSongListDownloader.login(username, password) self.csrf = re.findall('__csrf=(.*?) for', str(self.session.cookies))[0] self.cracker = Cracker() self.headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36' }
def __init__(self, username, password, **kwargs): self.session = NeteaseEveryday.login(username, password) self.csrf = re.findall('__csrf=(.*?) for', str(self.session.cookies))[0] self.cracker = Cracker() self.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36', 'Accept': '*/*' } os.system('cls')
def __init__(self, username, password, **kwargs): self.username = username self.session = NeteaseSignin.login(username, password) self.csrf = re.findall('__csrf=(.*?) for', str(self.session.cookies))[0] self.cracker = Cracker() self.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36', 'Content-Type': 'application/x-www-form-urlencoded', 'Referer': 'http://music.163.com/discover', 'Accept': '*/*' }
class NeteaseSignin(): def __init__(self, username, password): self.username = username self.session = NeteaseSignin.login(username, password) self.csrf = re.findall('__csrf=(.*?) for', str(self.session.cookies))[0] self.cracker = Cracker() self.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36', 'Content-Type': 'application/x-www-form-urlencoded', 'Referer': 'http://music.163.com/discover', 'Accept': '*/*' } '''外部调用''' def run(self): # 签到接口 signin_url = 'https://music.163.com/weapi/point/dailyTask?csrf_token=' + self.csrf # 模拟签到(typeid为0代表APP上签到, 为1代表在网页上签到) typeids = [0, 1] msg_response = '' for typeid in typeids: client_name = 'Web端' if typeid == 1 else 'APP端' # --构造请求获得响应 data = {'type': typeid} data = self.cracker.get(data) res = self.session.post(signin_url, headers=self.headers, data=data) res_json = res.json() # --判断签到是否成功 if res_json['code'] == 200: msg = '[INFO]: 账号%s在%s签到成功...' % (self.username, client_name) print(msg) else: msg = '[INFO]: 账号%s在%s签到失败, 原因: %s...' % ( self.username, client_name, res_json.get('msg')) print(msg) msg_response = msg_response + msg + '\n' return msg_response # 模拟登陆 @staticmethod def login(username, password): lg = login.Login() _, session = lg.music163(username, password) return session
class NeteaseEveryday(): def __init__(self, username, password, **kwargs): self.session = NeteaseEveryday.login(username, password) self.csrf = re.findall('__csrf=(.*?) for', str(self.session.cookies))[0] self.cracker = Cracker() self.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36', 'Accept': '*/*' } os.system('cls') '''外部调用''' def run(self): daily_recommend_infos = self.getdailyrecommend() keys, values = list(daily_recommend_infos.keys()), list( daily_recommend_infos.values()) title = '你的网易云每日歌曲推荐如下:' options = [v[0] for v in values] while True: option, index = pick(options, title, indicator='=>') self.downloadSong(keys[index], option, values[index][1]) try: os.system('cls') except: os.system('clear') '''下载某首歌曲''' def downloadSong(self, songid, songname, brs, savepath='.'): play_url = 'http://music.163.com/weapi/song/enhance/player/url?csrf_token=' print('正在下载 ——> %s' % songname) for br in brs: data = {'ids': [songid], 'br': br, 'csrf_token': self.csrf} res = self.session.post(play_url + self.csrf, headers=self.headers, data=self.cracker.get(data)) if res.json()['code'] == 200: download_url = res.json()['data'][0].get('url', '') if download_url: break with closing( self.session.get(download_url, headers=self.headers, stream=True, verify=False)) as res: total_size = int(res.headers['content-length']) if res.status_code == 200: label = '[FileSize]:%0.2f MB' % (total_size / (1024 * 1024)) with click.progressbar(length=total_size, label=label) as progressbar: with open( os.path.join( savepath, songname + '.' + download_url.split('.')[-1]), "wb") as f: for chunk in res.iter_content(chunk_size=1024): if chunk: f.write(chunk) progressbar.update(1024) '''获得每日歌曲推荐''' def getdailyrecommend(self): url = 'http://music.163.com/weapi/v2/discovery/recommend/songs?csrf_token=' data = { 'crsf_token': self.csrf, 'limit': '999', 'offset': '0', 'total': 'true' } data = self.cracker.get(data) response = self.session.post(url, headers=self.headers, data=data) response_json = response.json() daily_recommend_infos = {} if response_json['code'] == 200: for item in response_json['recommend']: songname = item['name'] songid = item['id'] singer = item['artists'][0]['name'] h = item['hMusic'].get('bitrate', 320000) if item['hMusic'] else 320000 m = item['mMusic'].get('bitrate', 192000) if item['mMusic'] else 192000 l = item['lMusic'].get('bitrate', 128000) if item['lMusic'] else 128000 brs = [h, m, l] daily_recommend_infos[songid] = [ '%s By %s' % (songname, singer), brs ] return daily_recommend_infos else: raise RuntimeError('获取每日歌曲推荐失败, 请检查网络并重新运行程序...') '''模拟登录''' @staticmethod def login(username, password): lg = login.Login() infos_return, session = lg.music163(username, password) return session
class NeteaseSongListDownloader(): def __init__(self, username, password, **kwargs): self.userid, self.session = NeteaseSongListDownloader.login( username, password) self.csrf = re.findall('__csrf=(.*?) for', str(self.session.cookies))[0] self.cracker = Cracker() self.headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36' } '''外部调用''' def run(self): # 获取并打印所有歌单 all_playlists = self.getPlayLists() tb = prettytable.PrettyTable() tb.field_names = ['歌单ID', '歌单名', '歌曲数量', '播放次数', '歌单属性'] for key, value in all_playlists.items(): tb.add_row([key] + value) print('您创建/收藏的所有歌单如下:') print(tb) # 根据用户输入获取指定歌单的详情信息 while True: playlist_id = input('请输入想要下载的歌单ID:') if playlist_id in list(all_playlists.keys()): song_infos = self.getPlayListSongs( playlist_id, all_playlists[playlist_id][1]) tb = prettytable.PrettyTable() tb.field_names = ['歌曲ID', '歌曲名', '歌手'] for key, value in song_infos.items(): tb.add_row([key] + value[:-1]) print('您输入的歌单ID为<%s>, 该歌单的所有歌曲信息如下:' % playlist_id) print(tb) user_choice = input('是否下载该歌单的所有歌曲(y/n, yes by default):') if (not user_choice) or (user_choice == 'y') or (user_choice == 'yes'): savepath = all_playlists[playlist_id][0] if not os.path.exists(savepath): os.mkdir(savepath) for key, value in song_infos.items(): self.downloadSong(key, value[0], value[-1], savepath) print('歌单ID为<%s>中的所有歌曲下载完成, 保存在 ——> %s' % (playlist_id, savepath)) '''下载某首歌曲''' def downloadSong(self, songid, songname, brs, savepath='.'): play_url = 'http://music.163.com/weapi/song/enhance/player/url?csrf_token=' print('正在下载 ——> %s' % songname) for br in brs: data = { 'ids': [songid], 'br': br.get('br'), 'csrf_token': self.csrf } res = self.session.post(play_url + self.csrf, headers=self.headers, data=self.cracker.get(data)) if res.json()['code'] == 200: download_url = res.json()['data'][0].get('url', '') if download_url: break with closing( self.session.get(download_url, headers=self.headers, stream=True, verify=False)) as res: total_size = int(res.headers['content-length']) if res.status_code == 200: label = '[FileSize]:%0.2f MB' % (total_size / (1024 * 1024)) with click.progressbar(length=total_size, label=label) as progressbar: with open( os.path.join( savepath, songname + '.' + download_url.split('.')[-1]), "wb") as f: for chunk in res.iter_content(chunk_size=1024): if chunk: f.write(chunk) progressbar.update(1024) '''获得某歌单的所有歌曲信息''' def getPlayListSongs(self, playlist_id, num_songs): detail_url = 'https://music.163.com/weapi/v6/playlist/detail?csrf_token=' offset = 0 song_infos = {} while True: data = { 'id': playlist_id, 'offset': offset, 'total': True, 'limit': 1000, 'n': 1000, 'csrf_token': self.csrf } res = self.session.post(detail_url + self.csrf, headers=self.headers, data=self.cracker.get(data)) tracks = res.json()['playlist']['tracks'] for track in tracks: name = track.get('name') songid = track.get('id') artists = ','.join([i.get('name') for i in track.get('ar')]) brs = [track.get('h')] + [track.get('m')] + [track.get('l')] song_infos[songid] = [name, artists, brs] offset += 1 if len(list(song_infos.keys())) >= num_songs: break return song_infos '''获得所有歌单''' def getPlayLists(self): playlist_url = 'https://music.163.com/weapi/user/playlist?csrf_token=' playlists = [] offset = 0 while True: data = { "offset": offset, "uid": self.userid, "limit": 50, "csrf_token": self.csrf } res = self.session.post(playlist_url + self.csrf, headers=self.headers, data=self.cracker.get(data)) playlists += res.json()['playlist'] offset += 1 if res.json()['more'] == False: break all_playlists = {} for item in playlists: name = item.get('name') track_count = item.get('trackCount') play_count = item.get('playCount') play_id = item.get('id') if item.get('creator').get('userId') == self.userid: attr = '我创建的歌单' else: attr = '我收藏的歌单' all_playlists[str(play_id)] = [name, track_count, play_count, attr] return all_playlists '''利用DecryptLogin实现模拟登录''' @staticmethod def login(username, password): lg = login.Login() infos_return, session = lg.music163(username, password) return infos_return.get('userid'), session
class NeteaseListenLeaderboard(): def __init__(self, username, password, **kwargs): _, self.session = login.Login().music163(username, password) self.csrf = re.findall('__csrf=(.*?) for', str(self.session.cookies))[0] self.cracker = Cracker() self.headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36' } def run(self): while True: userid = input('网易云个人听歌排行榜爬取, 请输入目标用户id(例如:268390054) ——> ') leader_board = self.getLeaderboard(userid) print('用户%s的最近一周听歌榜:' % userid) tb = prettytable.PrettyTable() tb.field_names = ['歌曲ID', '歌单名', '播放次数'] for each in leader_board.get('weekData'): tb.add_row(each) print(tb) print('用户%s的所有时间听歌榜:' % userid) tb = prettytable.PrettyTable() tb.field_names = ['歌曲ID', '歌单名', '播放次数'] for each in leader_board.get('allData'): tb.add_row(each) print(tb) '''获得某用户的听歌排行榜''' def getLeaderboard(self, uid): url = 'https://music.163.com/weapi/v1/play/record?csrf_token=' + self.csrf data = { 'type': '-1', 'uid': uid, 'limit': '1000', 'offset': '0', 'total': 'true', 'csrf_token': self.csrf } res = self.session.post(url, headers=self.headers, data=self.cracker.get(data)) res_json = res.json() leader_board = {'weekData': [], 'allData': []} if res_json['code'] == 200: all_data = res_json.get('allData') for item in all_data: songname = item.get('song').get('name') songid = item.get('song').get('id') play_count = item.get('playCount') leader_board['allData'].append([songid, songname, play_count]) week_data = res_json.get('weekData') for item in week_data: songname = item.get('song').get('name') songid = item.get('song').get('id') play_count = item.get('playCount') leader_board['weekData'].append([songid, songname, play_count]) else: raise RuntimeError('Fail to get leaderboard for %s...' % uid) return leader_board