Python Forum
error getting tracks from albums
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
error getting tracks from albums
#1
Im getting the top artists from a sepcific country, albums of that artists and tracks of that albums from lastfm. Im getting the artists and albums without errors but in the tracks it appears:

Quote:for album in album_response['album']['tracks']['track']: KeyError: 'album'

Do you know where is the issue?

The track part where is the issue:

tracks = {}
for i,v in albums.items():
    artist = albums[i]['artist'].replace(" ","+")
    name = albums[i]['name'].replace(" ", "+")
    album_response_data = requests.get('http://ws.audioscrobbler.com/2.0/?method=album.getinfo&format=json&api_key='+api_key+'&artist='+artist+'&album='+name)
    album_response = album_response_data.json()

    print(album_response)

    for album in album_response['album']['tracks']['track']:

        #print(album)

        title = album['name']


        number = album['@attr']['rank']
        duration = album['duration']


        tracks[ID] = {}

        tracks[ID]['title'] = title
        tracks[ID]['number'] = number
        tracks[ID]['artist'] = albums[i]['artist']
        tracks[ID]['album'] = albums[i]['name']
        tracks[ID]['albumID'] = albums[i]['ID']
        tracks[ID]['duration'] = duration

        ID += 1
Full working example:

import requests

api_key = "b088cbedecd40b35dd89e90f55227ac2" #generated for the example
ID = 0
artists = {}
for i in range(2, 3):
    artists_response = requests.get(
        'http://ws.audioscrobbler.com/2.0/?method=geo.gettopartists&country=portugal&format=json&page=' + str(i) + '&api_key=' + api_key)
    artists_data = artists_response.json()
    for artist in artists_data["topartists"]["artist"]:
        name = artist["name"]
        url = artist["url"]
        if ID > 3: continue
        artists[ID] = {}
        artists[ID]['ID'] = ID
        artists[ID]['name'] = name
        artists[ID]['url'] = url

        ID += 1

    for i, v in artists.items():
        chosen = artists[i]['name'].replace(" ", "+")
        artist_response = requests.get(
            'http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&format=json&artist=' + chosen + '&api_key=' + api_key)
        artist_data = artist_response.json()

        for artist in artist_data['artist']['image']:
            if (artist["size"] == "large"):
                if (artist["size"] is not None):
                    image = artist["#text"]
                    artists[i]['image'] = image


        artists[i]['tags'] = []
        for artist in artist_data['artist']['tags']["tag"]:
            tags = artist["name"]
            artists[i]['tags'].append(tags)


        bio = artist_data['artist']['bio']['summary']


albums = {}
for i, v in artists.items():
    chosen = artists[i]['name'].replace(" ", "+")
    topalbums_response = requests.get(
        'http://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&format=json&artist=' + chosen + '&api_key=' + api_key + '&limit=5')
    albums_data = topalbums_response.json()

    #print(albums_data)

    for album in albums_data['topalbums']['album']:
        name = album["name"]
        url = album["url"]



        albums[ID] = {}
        albums[ID]['ID'] = ID
        albums[ID]['artist'] = artists[i]['name']
        albums[ID]['artistID'] = artists[i]['ID']
        albums[ID]['name'] = name
        albums[ID]['url'] = url

        for image in album['image']:
            if (image["size"] == "large"):
                if (image["size"] is not None):
                    image = image["#text"]
                    albums[ID]['image'] = image
        ID += 1

tracks = {}
for i,v in albums.items():
    artist = albums[i]['artist'].replace(" ","+")
    name = albums[i]['name'].replace(" ", "+")
    album_response_data = requests.get('http://ws.audioscrobbler.com/2.0/?method=album.getinfo&format=json&api_key='+api_key+'&artist='+artist+'&album='+name)
    album_response = album_response_data.json()

    print(album_response)

    for album in album_response['album']['tracks']['track']:

        #print(album)

        title = album['name']


        number = album['@attr']['rank']
        duration = album['duration']


        tracks[ID] = {}

        tracks[ID]['title'] = title
        tracks[ID]['number'] = number
        tracks[ID]['artist'] = albums[i]['artist']
        tracks[ID]['album'] = albums[i]['name']
        tracks[ID]['albumID'] = albums[i]['ID']
        tracks[ID]['duration'] = duration

        ID += 1
Reply
#2
The print(album_respose) have this format:

{'album': {'name': 'Achtung Baby', 'artist': 'U2', 'mbid': 'a3cb23fc-acd3-4ce0-8f36-1e5aa6a18432',
'listeners': '3390992', 'playcount': '136035640', 'tracks': {'track': [{'name': 'One', 'url': 'https://www.last.fm/pt/music/U2/Achtung+Baby/One', 'duration': '276', '@attr':
{'rank': '3'}, 'streamable': {'#text': '0', 'fulltrack': '0'}


The error just appear in some artists that have space but some artists work like The Rolling Stones:

http://ws.audioscrobbler.com/2.0/?method...ormat=json

But others not for example Bruno Mars:

http://ws.audioscrobbler.com/2.0/?method...ormat=json

But works with a "+":

http://ws.audioscrobbler.com/2.0/?method...ormat=json

Do you know how to solve this issue?
Reply
#3
But for Rolling Stones I get a better response with "+".
So you should always use "+".

Instead of space " ", you can also try "%20".

>>> for album in album_response['album']['tracks']['track']:
KeyError: 'album'

The error means: There is no album
You can not trust data from the internet.
You have to check each key for existence

if 'album' in album_response:
    if 'tracks' in album_resonse['album']:
        ...
else:
    print error or warning or ....

Or you do not check for the keys
and catch the error with:

try:
    ...
except ...:
    ...
Reply
#4
heiner55 is right you should always use +,which replace space.
Example with f-string(3.6),which make building string nicer.
lower() and join() with +,should work for most search word.
import requests

api_key = "b088cbedecd40b35dd89e90f55227ac2"
artists_search = 'the rolling stone'
artists_search = '+'.join(artists_search.lower().split())
artists_response = requests.get(f'http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist={artists_search}&api_key={api_key}&format=json')
try:
    print(artists_response.json()['artist']['url'])
except KeyError:
    print('Artists not found')
Output:
https://www.last.fm/music/+noredirect/The+Rolling+Stone
If search for Bruno Mars same as over,and take out url used see that + is used.
Output:
https://www.last.fm/music/Bruno+Mars
Reply
#5
Thanks, but #chosen = artists[i]['name'].replace(" ", "+") already replace spaces for "+" no? With the code below as you said it is appearing the same error:

for i, v in artists.items():
        #chosen = artists[i]['name'].replace(" ", "+")
        chosen = '+'.join(artists[i]['name'].lower().split())

        artist_response = requests.get(f'http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist={chosen}&api_key={api_key}&format=json')
        artist_data = artist_response.json()
Error: for album in album_response['album']['tracks']['track']:
KeyError: 'album'
Reply
#6
Could you post a minimal working code example.
Your code with 100 lines and without any structure(like eg function).
Make code harder to read and spot error,
i could break it down and fix it but that should be your job Wink
Reply
#7
Thanks for your answer. I delete some things that should not be important for the issue and add some comments. The code is basically divided in 3 parts: get information about artists from a specific country, then get top albums info of that artists and then get the tracks info of that albums. The issue seems to be in the 3rd part, on getting tracks info of the albums.


import requests

api_key = "b088cbedecd40b35dd89e90f55227ac2"
ID= 0

#Get artists from specific country

artists = {}
for i in range(2, 3):
    artists_response = requests.get(
        'http://ws.audioscrobbler.com/2.0/?method=geo.gettopartists&country=spain&format=json&page=' + str(i) + '&api_key=' + api_key)
    artists_data = artists_response.json()
    for artist in artists_data["topartists"]["artist"]:

        name = artist["name"]

        url = artist["url"]
        #if ID > 3 continue
        artists[ID] = {}
        artists[ID]['ID'] = ID
        artists[ID]['name'] = name

        ID += 1


#Get TopAlbums info from above artists

albums = {}
for i, v in artists.items():
    chosen = artists[i]['name'].replace(" ", "+")
    topalbums_response = requests.get(
        'http://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&format=json&artist=' + chosen + '&api_key=' + api_key + '&limit=5')
    albums_data = topalbums_response.json()

    for album in albums_data['topalbums']['album']:
        name = album["name"]
        url = album["url"]

        albums[ID] = {}
        albums[ID]['ID'] = ID
        albums[ID]['artist'] = artists[i]['name']
        albums[ID]['artistID'] = artists[i]['ID']
        albums[ID]['name'] = name
        albums[ID]['url'] = url

        ID += 1

#Get tracks info of the above albums

tracks = {}
for i,v in albums.items():
    artist = albums[i]['artist'].replace(" ","+")
    name = albums[i]['name'].replace(" ", "+")
    album_response_data = requests.get('http://ws.audioscrobbler.com/2.0/?method=album.getinfo&format=json&api_key='+api_key+'&artist='+artist+'&album='+name)
    album_response = album_response_data.json()


    for album in album_response['album']['tracks']['track']:  

            title = album['name']

            number = album['@attr']['rank']
            duration = album['duration']

            tracks[ID] = {}

            tracks[ID]['trackID'] = ID

            tracks[ID]['title'] = title
            tracks[ID]['number'] = number
            tracks[ID]['artist'] = albums[i]['artist']
            tracks[ID]['album'] = albums[i]['name']
            tracks[ID]['albumID'] = albums[i]['ID']
            tracks[ID]['duration'] = duration

            ID += 1
Reply
#8
To be honest how you have done this is bad Dodgy
Quote:The issue seems to be in the 3rd part, on getting tracks info of the albums.
Then it should be at least 3 function.

To break it down to make make it easier test.
Here 3 album id,not 598(do you really need this before going on further?).
import requests

api_key = "b088cbedecd40b35dd89e90f55227ac2"
albums =\
     {100: {'ID': 100,
           'artist': 'David Bowie',
           'artistID': 0,
           'name': 'Best of Bowie',
           'url': 'https://www.last.fm/music/David+Bowie/Best+of+Bowie'},
     101: {'ID': 101,
           'artist': 'David Bowie',
           'artistID': 0,
           'name': 'Hunky Dory',
           'url': 'https://www.last.fm/music/David+Bowie/Hunky+Dory'},
     102: {'ID': 102,
           'artist': 'David Bowie',
           'artistID': 0,
           'name': "Let's Dance",
           'url': 'https://www.last.fm/music/David+Bowie/Let%27s+Dance'}}

tracks = {}
for i, v in albums.items():
    print(i, v)
Output:
100 {'ID': 100, 'artist': 'David Bowie', 'artistID': 0, 'name': 'Best of Bowie', 'url': 'https://www.last.fm/music/David+Bowie/Best+of+Bowie'} 101 {'ID': 101, 'artist': 'David Bowie', 'artistID': 0, 'name': 'Hunky Dory', 'url': 'https://www.last.fm/music/David+Bowie/Hunky+Dory'} 102 {'ID': 102, 'artist': 'David Bowie', 'artistID': 0, 'name': "Let's Dance", 'url': 'https://www.last.fm/music/David+Bowie/Let%27s+Dance'}
So now is easier to see what going on.
See that url work(past in browser),so can delete this two lines.
artist = albums['artist'].replace(" ", "+")
name = albums['name'].replace(" ", "+")
Now you can test with this and see if you can get it to work,
i have stop here.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  mido MIDI-file; how to distinguis tracks? philipbergwerf 2 2,253 Dec-10-2021, 05:06 PM
Last Post: philipbergwerf
  If statement not separating Albums giddyhead 5 2,520 Feb-26-2021, 11:31 PM
Last Post: giddyhead
  Getting top albums from last.fm ozzyk 1 3,005 Nov-19-2017, 09:40 PM
Last Post: heiner55

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020