Scrape playlist artists
The following script retrieves all tracks of your playlists and aggregates the most common artists by total track count.
It assumes that your credentials are saved in the environment and
you have followed or created at least one playlist.
For this example, the artist of podcast episodes is the name of the show.
To avoid errors when hitting rate limits, a RetryingSender
is used.
import asyncio
import tekore as tk
from collections import Counter
conf = tk.config_from_environment()
scope = tk.scope.playlist_read_private
token = tk.prompt_for_user_token(*conf, scope=scope)
def get_artist(track) -> str:
if track.episode:
return track.show.name
else:
return track.artists[0].name
Asynchronous functions can be used to achieve a faster runtime
when making lots of parallelisable calls to the API.
A series of asynchronous calls alone does not help much, but the calls can be
parallelised with asyncio.gather()
.
The code is more complex, but with bigger workloads more time is saved.
async def count_artists(spotify: tk.Spotify, playlist_id: str):
tracks = await spotify.playlist_items(playlist_id)
tracks = spotify.all_items(tracks)
return Counter([get_artist(t.track) async for t in tracks])
async def main() -> Counter:
sender = tk.RetryingSender(sender=tk.AsyncSender())
spotify = tk.Spotify(token, sender=sender, max_limits_on=True)
playlists = await spotify.followed_playlists()
playlists = spotify.all_items(playlists)
counts = [await count_artists(spotify, p.id) async for p in playlists]
await spotify.close()
return sum(counts, Counter())
artists = asyncio.run(main())
for name, count in artists.most_common(3):
print(count, name)
async def count_artists(spotify: tk.Spotify, playlist_id: str):
tracks_paging = await spotify.playlist_items(playlist_id)
paging_len = len(tracks_paging.items)
track_calls = [
spotify.playlist_items(playlist_id, offset=ofs)
for ofs in range(paging_len, tracks_paging.total, paging_len)
]
pages = [tracks_paging] + await asyncio.gather(*track_calls)
tracks = sum([page.items for page in pages], [])
return Counter([get_artist(t.track) for t in tracks])
async def main() -> Counter:
sender = tk.RetryingSender(sender=tk.AsyncSender())
spotify = tk.Spotify(token, sender=sender, max_limits_on=True)
playlists_paging = await spotify.followed_playlists()
paging_len = len(playlists_paging.items)
playlist_calls = [
spotify.followed_playlists(offset=ofs)
for ofs in range(paging_len, playlists_paging.total, paging_len)
]
pages = [playlists_paging] + await asyncio.gather(*playlist_calls)
playlists = sum([page.items for page in pages], [])
count_calls = [count_artists(spotify, p.id) for p in playlists]
counts = await asyncio.gather(*count_calls)
await spotify.close()
return sum(counts, Counter())
artists = asyncio.run(main())
for name, count in artists.most_common(3):
print(count, name)