Skip to content

Instantly share code, notes, and snippets.

@SamL98
Last active March 9, 2024 01:54
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SamL98/c1200a30cdb19103138308f72de8d198 to your computer and use it in GitHub Desktop.
Save SamL98/c1200a30cdb19103138308f72de8d198 to your computer and use it in GitHub Desktop.
Python Script for Getting Spotify Listening History
# 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()
@Ben-Purnell
Copy link

Hi how quickly will this return the last song you listened to, and can it return the song while it is still being played?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment