Skip to content

Instantly share code, notes, and snippets.

@ivystopia
Last active July 14, 2023 20:46
Show Gist options
  • Save ivystopia/ff29f92de0fe53586a2a47f4a8d24b65 to your computer and use it in GitHub Desktop.
Save ivystopia/ff29f92de0fe53586a2a47f4a8d24b65 to your computer and use it in GitHub Desktop.
Save Spotify playlists for a user
#! /usr/bin/env python3
# Need to set SPOTIPY_CLIENT_ID and SPOTIPY_CLIENT_SECRET env vars
# Then run with ./spotispy.py username
# It will save playlists in "data" directory relative to the current directory
import sys
import json
import spotipy
from pathlib import Path
# Idiot proof
if len(sys.argv) < 2:
print("Specify a username as the first argument.")
quit(1)
username = sys.argv[1]
# Create directory for the user
user_dir = "data/{}".format(username)
Path("{}/playlists".format(user_dir)).mkdir(parents=True, exist_ok=True)
class Client(spotipy.Spotify):
"""
Wrapper for Spotipy allowing infinite pagination
"""
def user_playlists(self, username):
offset = 0
while True:
response = super().user_playlists(username, limit=50, offset=offset)
for playlist in response['items']:
# Ignore playlists which were not created by the user themselves
if playlist['owner']['id'] != username:
continue
# Remove snapshot ID as this sometimes changes with no actual track changes
del playlist['snapshot_id']
# Remove images
del playlist['images']
# Replace tracks URL with actual list of tracks
playlist['tracks'] = [track for track in self.playlist_tracks(playlist['id'])]
# Playlist followers
followers = self.playlist(playlist_id=playlist['id'])['followers']['total']
playlist['followers'] = followers if followers else 0
yield playlist
if not response.get('next'):
break
else:
offset = offset + 50
def playlist_tracks(self, playlist_id):
offset = 0
while True:
response = super().playlist_tracks(playlist_id, limit=100, offset=offset)
for item in response['items']:
if not item['track']:
# TODO why?????
continue
# Format track info
track = {}
track['added_at'] = item.get('added_at')
track['title'] = item.get('track').get('name')
track['album'] = item.get('track').get('album').get('name')
track['artist'] = item.get('track').get('artists')[0]['name']
track['uri'] = item.get('track').get('uri')
yield track
if not response.get('next'):
break
else:
offset = offset + 100
# Create client object with our API credentials (already set in env)
client = Client(client_credentials_manager=spotipy.oauth2.SpotifyClientCredentials())
# Grab user overview and save to data/username/username.json
user_overview = client.user(username)
with open("{}/{}.json".format(user_dir, username), 'w') as file:
file.write(json.dumps(user_overview, indent=2))
# Grab playlists and save to data/username/playlist_id.json
for playlist in client.user_playlists(user_overview['id']):
with open("{}/playlists/{}.json".format(user_dir, playlist['id']), 'w') as file:
file.write(json.dumps(playlist, indent=2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment