VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > python入门教程 >
  • Python爬虫实战,DecryptLogin模块,Python模拟登录实现网易云个人歌单下载器

前言

今天来写个网易云音乐个人歌单下载器呗,让我们愉快地开始吧~

 

开发工具

** Python版本:**3.6.4

** 相关模块:**

DecryptLogin模块;

argparse模块;

prettytable模块;

click模块;

以及一些python自带的模块。

环境搭建

安装Python并添加到环境变量,pip安装需要的相关模块即可。

DecryptLogin安装方式参见(因为经常更新,已经安装过的小伙伴麻烦记得更新一下,否则可能会在新的案例中报错)

原理简介

既然是模拟登录系列,首先自然是先模拟登录网易云音乐啦,这个利用我们开源的DecrpytLogin库可以轻松地实现:

'''利用DecryptLogin实现模拟登录'''
@staticmethod
def login(username, password):
  lg = login.Login()
  infos_return, session = lg.music163(username, password)
  return infos_return.get('userid'), session

接着就是获取登录用户创建/收藏的歌单列表(注意,因为只是一个小例子,所以仅支持下载登录用户自己创建/收藏的歌单,当然这代码应该很容易可以扩展到下载任意歌单T_T),通过抓包分析(其实网上很多地方可以找到别人分析完后公开的网易云音乐api,需要的可以去知乎或者Github之类的网站上搜索一下对应关键字)我们可以发现登录用户所有歌单的列表可以通过请求以下API获取:

https://music.163.com/weapi/user/playlist?csrf_token=

其中csrf_token的值在用户登录后的session的cookies中可以找到,由此我们可以获得我们需要的歌单相关的信息,代码实现如下:

'''获得所有歌单'''
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 not 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

接着,用户将选择想要下载的歌单id,根据歌单id,我们将利用以下api来获得该歌单的详细信息:

https://music.163.com/weapi/v6/playlist/detail?csrf_token=

具体而言,代码实现如下:

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

其中返回的信息中br(其实就是歌曲比特率)和歌曲id在后续的歌曲下载中是必须要的,其他信息的提取主要是为了用户交互的需要。接着,当用户确定是下载该歌单中的所有歌曲时,程序就开始下载所有歌曲啦。而某首歌曲下载的代码在之前的音乐下载器里分享过,copy过来稍微改下大概就是这个这样了:

'''下载某首歌曲'''
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)

文章到这里就结束了,感谢你的观看,下篇文章分享网抑云个人听歌排行榜爬取

为了感谢读者们,我想把我最近收藏的一些编程干货分享给大家,回馈每一个读者,希望能帮到你们。

出处:https://www.cnblogs.com/daimubai/p/15002267.html


相关教程