Last.fm Top Tracks Playlist Generator Using Python

This item was filled under [ Uncategorized ]

This is mine and Clive’s(@cliveverghese) latest venture. Allow me to explain this project.

A little bit of history…
I’ve been a last.fm user for more than a year. Recently, I started discovering new music. My busy schedule (okay, laziness) made it impossible for me to check out every song one by one and I wanted a quick way of listening to the good songs. Relying on public opinion seemed a good idea. I discussed about this with Clive and he said he was “in”. And hence kicked off, this project.

This project, being our first real-world problem tackling was given the place it deserved in our schedules. After putting in much of thought, we thought we’d make it in C++. But after vainly trying to use the last.fm API, we had an urge to choose python. This would be the first time we used python in our lives. So the task was a bit more difficult. We thought we’d divide the project into two -

The first one would index all the mp3s present in the computer and store the ID3 details in a database.

The second part would fetch the top tracks list of the required artist from last.fm, search for it in the database and make an m3u playlist out of it.

Clive got to do the former and I got to do the latter due to his interests in core programming and my interests in web development.

The code

Indexing mp3s and storing them into an SQLite DB

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from os import *
from os.path import *
import id3reader
import glob
import os
import sqlite3
 
theList = []
theTitle = []
theArtist = []
theAlbum = []
 
if not os.path.isfile("dump.db"):
        con = sqlite3.connect('dump.db')
        cur = con.cursor()
        cur.execute('CREATE TABLE lastfm (artist VARCHAR(40), album VARCHAR(40), title VARCHAR(40), path VARCHAR(150) PRIMARY KEY)')
        con.commit()
else:
        con = sqlite3.connect('dump.db')
        cur = con.cursor()
        cur.execute('DROP TABLE IF EXISTS lastfm')
        con.commit()
 
def recurse_dir(i):
        path = i+"\\"
        path2 = i+"\\*.mp3"
 
        t = 1
 
        try:
                	directories = os.listdir(path)
        except WindowsError :
                	t = 0
        try:
                	songs  = glob.glob(path2)
        except WindowsError :
                	t = 0	
 
        if t == 1:
                for song in songs:
                                id3r = id3reader.Reader(song)
                                theTitle.append(id3r.getValue('title'))
                                theArtist.append(id3r.getValue('performer'))
                                theAlbum.append(id3r.getValue('album'))
                                theList.append(song)
                for directory in directories:
                                temppath = path+directory
                                if(os.path.isdir(temppath)):
                                        	recurse_dir(temppath)
 
def listing():
        L=[]
        for i in range(ord('a'),ord('z')+1):
                drive=chr(i)
                if(exists(drive+":\\")):
                   L.append(drive)
        #print "Drive Found"
        for l in L:
                l = l+":"
                recurse_dir(l)
 
listing()
 
l=len(theList)-1
for i in range(l):
                artist = theArtist[i]
                album = theAlbum[i]
                title = theTitle[i]
                llist = theList[i]
                cur.execute('INSERT INTO lastfm (artist, album, title, path) VALUES(?,?,?,?)', (artist, album, title, llist))
 
con.commit()
for row in con.execute("SELECT artist, album, title FROM lastfm"):
				print row

Download code in .py format: Indexing

Checking whether the DB has been created

1
2
3
4
5
6
import sqlite3
 
con = sqlite3.connect('dump.db')
cur = con.cursor()
for row in con.execute("select artist, album, title from lastfm"):
				print row

Download code in .py format: Display Database (Optional)

Fetching information from last.fm and generating the playlist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import time
import pylast
import re
import sqlite3
import getpass
 
from md5 import md5
 
con = sqlite3.connect('dump.db')
cur = con.cursor()
 
user_name = raw_input("Enter last.fm username: ")
user_password = raw_input("Enter last.fm password: ")
api_key = 'd90a0d87f51434863f97038a24c7f859'
api_secret = 'ffd90592c48c8f9e232af22e0e43def9'
 
name = raw_input("Enter artist to generate playlist of top tracks: ")
 
top_tracks_file = open(''+name+'+'"toptracks"'.m3u', 'w')
 
# time_periods = ['PERIOD_12MONTHS'] OR ['PERIOD_6MONTHS'] OR ['PERIOD_3MONTHS'] OR ['PERIOD_OVERALL']
time_periods = ['PERIOD_3MONTHS']
 
md5_user_password = md5(user_password).hexdigest()
sg = pylast.SessionKeyGenerator(api_key, api_secret)
session_key = sg.get_session_key(user_name, md5_user_password)
 
artist = pylast.Artist(name, api_key, api_secret, session_key)
 
top_tracks = []
for time_period in time_periods:
    tracks = artist.get_top_tracks()
 
    p = re.compile('.*[\s]-[\s](.*), Weight: [\d]+')
 
    for i in range (0,5):
        m = p.match(str(tracks[i]))
        track = m.groups()[0]
        for result in con.execute('SELECT path FROM lastfm WHERE artist=? AND title=?',(name, track)):
            	result = "\n".join(result)
            	top_tracks_file.write(result+"\n")
 
    top_tracks_file.close()
	time.sleep(5)

Download code in .py format: Generate Playlist

Have fun!

You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a Comment