Created
July 20, 2017 13:58
-
-
Save brynedwards/de55f52dc5eaee50472eb414b67a1b74 to your computer and use it in GitHub Desktop.
Script to dump Spotify playlists to xspf files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Script to dump Spotify playlists to xspf files. Replace the | |
playlists list and username string with your values. File name | |
format is <today_filename.xspf>; see line 65. You'll also need | |
to auth with the Spotify web API; see the Spotipy API docs: | |
https://spotipy.readthedocs.io/en/latest/#authorization-code-flow | |
""" | |
from datetime import date | |
import xml.etree.ElementTree as ET | |
import spotipy | |
import spotipy.util as util | |
limit = 100 | |
# Each tuple is (filename, playlist_owner, playlist_id) | |
# Discover Weekly and Release Radar playlists are actually controlled by | |
# Spotify hence the 2nd value. | |
playlists = [ | |
('discover_weekly', 'spotify', '37i9dQZEVXcCOH2b4uaCom'), | |
('release_radar', 'spotify', '37i9dQZEVXbvrKDaLca5Ap'), | |
] | |
scope = 'user-library-read' | |
username = 'brynser' | |
token = util.prompt_for_user_token(username, scope) | |
def get_tracks_from_playlist(client, username, playlist): | |
def load(offset, tracks): | |
response = client.user_playlist_tracks(username, playlist, limit=limit, | |
offset=offset) | |
if len(response['items']) == 0: | |
return tracks | |
else: | |
tracks = tracks + [i['track'] for i in response['items']] | |
return load(offset + limit, tracks) | |
return load(0, []) | |
def write_playlist(name, tracks): | |
def to_element(track): | |
kv = [ | |
('location', track['uri']), | |
('title', track['name']), | |
('creator', ', '.join([a['name'] for a in track['artists']])), | |
('album', track['album']['name']), | |
('duration', str(track['duration_ms'])), | |
('trackNum', str(track['track_number'])) | |
] | |
def el(tag, text): | |
e = ET.Element(tag) | |
e.text = text | |
return e | |
elements = [el(tag, text) for (tag, text) in kv] | |
parent = ET.Element('track') | |
parent.extend(elements) | |
return parent | |
root = ET.Element( | |
'playlist', | |
attrib={ | |
'version': '1', | |
'xmlns': 'http://xspf.org/ns/0'}) | |
track_list = ET.SubElement(root, 'trackList') | |
track_list.extend([to_element(t) for t in tracks]) | |
tree = ET.ElementTree(element=root) | |
tree.write(date.today().isoformat() + '_' + name + '.xspf') | |
def main(): | |
token = util.prompt_for_user_token('brynser', scope) | |
if token: | |
client = spotipy.Spotify(auth=token) | |
loaded_playlists = [ | |
(name, get_tracks_from_playlist( | |
client, username, id)) for ( | |
name, username, id) in playlists] | |
[write_playlist(*p) for p in loaded_playlists] | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment