preface

Today, let’s write a netease Cloud music personal playlist downloader, let’s start happily ~

The development tools

Python version: 3.6.4
Related modules:

DecryptLogin module;

The argparse module;

Prettytable module;

Click the module;

And some modules that come with Python.

Environment set up

Install Python and add it to the environment variables. PIP installs the required modules.

See how DecryptLogin is installed (since it is frequently updated, please make sure that you update the DecryptLogin, otherwise it may cause errors in new cases).

Introduction of the principle

Since it is simulated login series, the first nature is to simulate login netease Cloud music, this use of our open source DecrpytLogin library can be easily implemented:

@StaticMethod def login(username, password): lg = login.Login() infos_return, session = lg.music163(username, password) return infos_return.get('userid'), sessionCopy the code

Followed by obtaining the logged in user to create/collect song single table (note that because only a small example, so only support download login of users to create/collect this code should be easy, of course, can be extended to download any song single T_T), by analyzing caught (actually a lot of places can find others online after the analysis of public music netease cloud API, If you need it, you can go to Zhihu or Github and search for the corresponding keywords.) We can find that the list of all the playlists of login users can be obtained by requesting the following API:

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

The value of csrF_Token can be found in the cookies of the session after the user logs in, so we can get the information related to the playlist we need. The code implementation is as follows:

"" 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 = 'I created a playlist' else: Attr = 'all_playlists' [STR (play_id)] = [name, track_count, play_count, attr] return all_playlistsCopy the code

Next, the user will select the playlist ID that he or she wants to download. Based on the playlist ID, we will use the following API to get the playlist details:

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

Specifically, the code is implemented as follows:

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
Copy the code

Among the returned information, BR (which is actually the song bit rate) and song ID are required in the follow-up song download, and other information is extracted mainly for the needs of user interaction. Then, when the user is sure to download all the songs in the playlist, the app starts downloading all the songs. And a song download code in the previous music downloads shared, copy over a little change under the roughly this:

Def downloadSong(self, songid, songname, BRS, savepath='.'): Play_url = 'http://music.163.com/weapi/song/enhance/player/url?csrf_token=' print (' are downloading - > % 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)Copy the code

After reading the article like friends point a like support, follow me every day to share Python simulation login series, the next article to share netease cloud personal playlist download device

All done~ complete source code see profile or private message to obtain related files.