#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Created on Sat Apr 3 22:42:36 2021 @author: fish Try to get and parse spotify playlists spotify:playlist:7hGGMcWOPgXj2qFw5DQyXP - likes_2021 spotify:playlist:2etpNxusBBUoXoxb3BOsF3 - likes_2020 Todo: ---- - extract the wanted info (track name, artist(s), picture url, track URI, etc) more elegantly - handle multiple artists - access token timeout? check if check is needed - find alternative to the kludge to prevent skipping first list Done: ---- 2021-04-04: handle longer playlists Outline: ------- - get playlist - extract playlist metadata - create playlist dictionary (---) - extract tracks & store - check if done, else iterate over next set of tracks (---) - store completed list, clean up. Playlist format: --------------- Playlist = {'name': '', 'image': '', 'uri': '', 'tracks': [ {'artist': '', 'name': '' }, {'artist': '' 'name': '' } ] } """ import json import requests # GLOBALS # kludge to avoid storing secrets in git repo with open('spotifyids') as f: CLIENT_ID, CLIENT_SECRET = f.readline().rstrip().split(',') AUTH_URL = 'https://accounts.spotify.com/api/token' BASE_URL = 'https://api.spotify.com/v1/' # base URL of all Spotify API endpoints PLAYLIST_ID = '37i9dQZF1EMdXVibVNv347' # temp def get_access_token(): """ Get the temporary access token from the Spotify servers (POST request) """ auth_response = requests.post(AUTH_URL, { 'grant_type': 'client_credentials', 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, }) # convert the response to JSON auth_response_data = auth_response.json() # save the access token access_token = auth_response_data['access_token'] return access_token def get_playlist(access_token): """ Get playlist from the servers with this request: GET https://api.spotify.com/v1/playlists/{playlist_id} """ headers = {'Authorization': 'Bearer {token}'.format(token=access_token)} # actual GET request with proper header playlist = requests.get(BASE_URL + 'playlists/' + PLAYLIST_ID, headers=headers) playlist = playlist.json() return playlist # playlist ID from the URI # playlist_id = '7hGGMcWOPgXj2qFw5DQyXP' # 2021 - shorter than 100 (for now) # playlist_id = '2etpNxusBBUoXoxb3BOsF3' # 2020 - longer than 100 # %% create playlist dict playlist = get_playlist(get_access_token()) my_playlist = {'name': playlist['name'], 'uri': playlist['uri'], 'image': playlist['images'][0]['url'], 'tracks': [] } # %% strip down to the tracks work_playlist = playlist['tracks'] work_playlist['next'] = BASE_URL + 'playlists/' + PLAYLIST_ID + '/tracks' # kludge def do_work(access_token): """ extract info from playlist """ headers = {'Authorization': 'Bearer {token}'.format(token=access_token)} while True: work_playlist = requests.get(work_playlist['next'], headers=headers) work_playlist = work_playlist.json() print('url is: ', work_playlist['next']) # Extract and store playlist items playlist_tracks = [] for track in work_playlist['items']: playlist_tracks.append({ 'artist': track['track']['artists'][0]['name'], 'name': track['track']['name']}) playlist['tracks'] = playlist['tracks'] + playlist_tracks # break loop if no next url if not work_playlist['next']: break return # %% store list & clean up def cleanup(): """ store list to file and cleanup etc """ playlist_name = playlist['name'] + '-' + playlist_id + '.json' with open(playlist_name, 'w') as outfile: json.dump(playlist, outfile, indent=4) return def setup(): pass def main(): setup() do_work(access_token) cleanup() return main()