Last active
January 30, 2025 18:07
-
-
Save SamL98/c1200a30cdb19103138308f72de8d198 to your computer and use it in GitHub Desktop.
Python Script for Getting Spotify Listening History
This file contains 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
# To run as a local cron job, edit your crontab like so: | |
# | |
# SPOTIPY_USER_ID=<redacted> | |
# SPOTIPY_CLIENT_ID=<redacted> | |
# SPOTIPY_CLIENT_SECRET=<redacted> | |
# script_path=<redacted> | |
# SPPATH=$script_path | |
# python_path=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3 | |
# | |
# PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin | |
# | |
# 0 8 * * * cd $script_path && $python_path get_recents.py >> $script_path/cron_log.log | |
# 0 12 * * * cd $script_path && $python_path get_recents.py >> $script_path/cron_log.log | |
# 0 16 * * * cd $script_path && $python_path get_recents.py >> $script_path/cron_log.log | |
# 0 20 * * * cd $script_path && $python_path get_recents.py >> $script_path/cron_log.log | |
# 0 23 * * * cd $script_path && $python_path get_recents.py >> $script_path/cron_log.log | |
# Take a look at https://gist.github.com/SamL98/ff1448aa1f92bf671a549357449192e5 if you want to learn about sputil | |
from os.path import join, isfile | |
import sputil as sp | |
import pandas as pd | |
import requests as r | |
from datetime import datetime | |
def get_recent(): | |
root_dir = '<redacted>' | |
params = {'limit': 49} | |
# .next.txt stores a timestamp of the last listened track fetched | |
# we can pass this timestamp to the Spotify API and we will only | |
# get songs listened to after this timestamp | |
next_fname = join(root_dir, '.next.txt') | |
if isfile(next_fname): | |
with open(next_fname) as f: | |
params['after'] = int(f.read()) | |
r = requests.get( | |
sp.base_url + 'me/player/recently-played', | |
params, | |
headers=sp.auth_header) | |
assert r.status_code == 200, 'Request responded with non-200 status %d' % r.status_code | |
assert r.json(), 'No json from request' | |
json = r.json() | |
assert 'cursors' in json(), 'No cursor object in json' | |
cursor_obj = json['cursors'] | |
assert 'after' in cursor_obj, 'No after key in cursor json' | |
after = cursor_obj['after'] | |
with open(next_fname, 'w') as f: | |
f.write(after) | |
assert 'items' in json, 'No item key in json' | |
tracks = [] | |
for track_obj in json['items']: | |
track = sp.format_track(track_obj, True) | |
played_at = track_obj['played_at'] | |
played_at = datetime.strptime(played_at, '%Y-%m-%dT%H:%M:%S.%fZ') | |
track['timestamp'] = played_at.timestamp() | |
tracks.append(track) | |
print('Fetched %d new tracks' % len(tracks)) | |
# reorder the DataFrame so that it is in chronological order | |
df = pd.DataFrame(tracks).iloc[::-1] | |
# if we already have a recently_played.csv file, | |
# then open it in append mode so that previous history isn't overwritten | |
# and header=False so that the header doesn't appear halfway through the file | |
recent_fname = join(root_dir, 'recently_played.csv') | |
fmode = 'w' | |
inc_header = True | |
if isfile(recent_fname): | |
fmode = 'a' | |
inc_header = False | |
with open(recent_fname, fmode) as f: | |
df.to_csv(f, header=inc_header) | |
if __name__ == '__main__': | |
get_recent() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi how quickly will this return the last song you listened to, and can it return the song while it is still being played?