Browse Source

Use "several" API call to get artist genres

master
Kevin Mok 7 years ago
parent
commit
bd597cdc23
  1. 55
      spotifyvis/utils.py
  2. 4
      spotifyvis/views.py

55
spotifyvis/utils.py

@ -11,6 +11,11 @@ import json
# }}} imports # # }}} imports #
USER_TRACKS_LIMIT = 50
# ARTIST_LIMIT = 50
ARTIST_LIMIT = 25
FEATURES_LIMIT = 100
# parse_library {{{ # # parse_library {{{ #
def parse_library(headers, tracks, user): def parse_library(headers, tracks, user):
@ -24,14 +29,13 @@ def parse_library(headers, tracks, user):
""" """
# TODO: implement importing entire library with 0 as tracks param # TODO: implement importing entire library with 0 as tracks param
# number of tracks to get with each call
limit = 50
# keeps track of point to get songs from # keeps track of point to get songs from
offset = 0 offset = 0
payload = {'limit': str(limit)}
payload = {'limit': str(USER_TRACKS_LIMIT)}
artist_genre_queue = []
# iterate until hit requested num of tracks # iterate until hit requested num of tracks
for _ in range(0, tracks, limit):
for _ in range(0, tracks, USER_TRACKS_LIMIT):
payload['offset'] = str(offset) payload['offset'] = str(offset)
# get current set of tracks # get current set of tracks
saved_tracks_response = requests.get('https://api.spotify.com/v1/me/tracks', headers=headers, params=payload).json() saved_tracks_response = requests.get('https://api.spotify.com/v1/me/tracks', headers=headers, params=payload).json()
@ -48,14 +52,18 @@ def parse_library(headers, tracks, user):
name=artist_dict['name'], name=artist_dict['name'],
) )
if artist_created: if artist_created:
add_artist_genres(headers, artist_obj)
artist_genre_queue.append(artist_obj)
if len(artist_genre_queue) == ARTIST_LIMIT:
add_artist_genres(headers, artist_genre_queue)
artist_genre_queue = []
# update_artist_genre(headers, artist_obj) # update_artist_genre(headers, artist_obj)
# get_or_create() returns a tuple (obj, created) # get_or_create() returns a tuple (obj, created)
track_artists.append(artist_obj) track_artists.append(artist_obj)
top_genre = get_top_genre(headers,
track_dict['track']['artists'][0]['id'])
# top_genre = get_top_genre(headers,
# track_dict['track']['artists'][0]['id'])
top_genre = ""
track_obj, track_created = save_track_obj(track_dict['track'], track_obj, track_created = save_track_obj(track_dict['track'],
track_artists, top_genre, user) track_artists, top_genre, user)
@ -74,8 +82,12 @@ def parse_library(headers, tracks, user):
feature_data_points, library_stats) feature_data_points, library_stats)
""" """
# calculates num_songs with offset + songs retrieved # calculates num_songs with offset + songs retrieved
offset += limit
offset += USER_TRACKS_LIMIT
# pprint.pprint(library_stats) # pprint.pprint(library_stats)
# update artists left in queue since there will be probably be leftover
# artists that didn't hit ARTIST_LIMIT
add_artist_genres(headers, artist_genre_queue)
update_track_genres(user) update_track_genres(user)
# }}} parse_library # # }}} parse_library #
@ -359,30 +371,31 @@ def get_top_genre(headers, top_artist_id):
# }}} # # }}} #
# add_artist_genres {{{ #
def add_artist_genres(headers, artist_obj):
"""Adds genres to artist_obj and increases the count the respective Genre
object. Should be called when a new Artist object is created.
def add_artist_genres(headers, artist_objs):
"""Adds genres to artist_objs and increases the count the respective Genre
object. artist_objs should contain the API limit for a single call
(ARTIST_LIMIT) for maximum efficiency.
:headers: For making the API call. :headers: For making the API call.
:artist_obj: Artist object for which to add/tally up genres for.
:artist_objs: List of Artist objects for which to add/tally up genres for.
:returns: None :returns: None
""" """
artist_response = requests.get('https://api.spotify.com/v1/artists/' +
artist_obj.artist_id, headers=headers).json()
for genre in artist_response['genres']:
artist_ids = str.join(",", [artist_obj.artist_id for artist_obj in artist_objs])
# print(len(artist_objs), artist_ids)
params = {'ids': artist_ids}
artists_response = requests.get('https://api.spotify.com/v1/artists/',
headers=headers, params=params).json()['artists']
for i in range(len(artist_objs)):
for genre in artists_response[i]['genres']:
genre_obj, created = Genre.objects.get_or_create(name=genre, genre_obj, created = Genre.objects.get_or_create(name=genre,
defaults={'num_songs':1}) defaults={'num_songs':1})
if not created: if not created:
genre_obj.num_songs = F('num_songs') +1 genre_obj.num_songs = F('num_songs') +1
genre_obj.save() genre_obj.save()
artist_obj.genres.add(genre_obj)
artist_obj.save()
# }}} add_artist_genres #
artist_objs[i].genres.add(genre_obj)
artist_objs[i].save()
# process_library_stats {{{ # # process_library_stats {{{ #

4
spotifyvis/views.py

@ -19,7 +19,7 @@ from .models import User, Track, AudioFeatures, Artist
# }}} imports # # }}} imports #
TIME_FORMAT = '%Y-%m-%d-%H-%M-%S' TIME_FORMAT = '%Y-%m-%d-%H-%M-%S'
TRACKS_TO_QUERY = 100
TRACKS_TO_QUERY = 50
# generate_random_string {{{ # # generate_random_string {{{ #
@ -65,8 +65,8 @@ def index(request):
# login {{{ # # login {{{ #
# uses Authorization Code flow
def login(request): def login(request):
# use a randomly generated state string to prevent cross-site request forgery attacks # use a randomly generated state string to prevent cross-site request forgery attacks
state_str = generate_random_string(16) state_str = generate_random_string(16)
request.session['state_string'] = state_str request.session['state_string'] = state_str

Loading…
Cancel
Save