#!/usr/bin/env python2 #-*- coding: utf-8 -*- # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # """ Script for exporting tracks through audioscrobbler API. Usage: lastexport.py -u USER [-o OUTFILE] [-p STARTPAGE] [-s SERVER] """ import urllib2, urllib, sys, time from xml.dom import minidom from optparse import OptionParser def get_options(parser): """ Define command line options.""" parser.add_option("-u", "--user", dest="username", default=None, help="User name.") parser.add_option("-o", "--outfile", dest="outfile", default="exported_tracks.txt", help="Output file, default is exported_tracks.txt") parser.add_option("-p", "--page", dest="startpage", type="int", default="1", help="Page to start fetching tracks from, default is 1") parser.add_option("-s", "--server", dest="server", default="last.fm", help="Server to fetch track info from, default is last.fm") options, args = parser.parse_args() if not options.username: sys.exit("User name not specified, see --help") return options.username, options.outfile, options.startpage, options.server def connect_server(username, startpage): """ Connect to server and get a XML page.""" if server == "libre.fm": baseurl = 'http://alpha.libre.fm/2.0/?' urlvars = dict(method='user.getrecenttracks', api_key='ohaiderthisisthelastexportscript', user=username, page=startpage, limit=200) elif server == "last.fm": baseurl = 'http://ws.audioscrobbler.com/2.0/?' urlvars = dict(method='user.getrecenttracks', api_key='e38cc7822bd7476fe4083e36ee69748e', user=username, page=startpage, limit=50) else: sys.exit("No config exist for this server, valid servers are: last.fm, libre.fm") url = baseurl + urllib.urlencode(urlvars) try: f = urllib2.urlopen(url) except: print "Failed to open page %s" % urlvars['page'] response = None return response response = f.read() f.close() return response def get_pageinfo(response): """Check how many pages of tracks the user have.""" xmlpage = minidom.parseString(response) totalpages = xmlpage.getElementsByTagName('recenttracks')[0].attributes['totalPages'].value return int(totalpages) def get_tracklist(response): """Read XML page and get a list of tracks and their info.""" xmlpage = minidom.parseString(response) tracklist = xmlpage.getElementsByTagName('track') return tracklist def parse_track(tracklist, i): """Extract info from every track entry and output to list.""" track = tracklist[i].getElementsByTagName try: artistname = track('artist')[0].childNodes[0].data except: artistname = '' try: artistmbid = track('artist')[0].attributes['mbid'].value except: artistmbid = '' try: trackname = track('name')[0].childNodes[0].data except: trackname = '' try: trackmbid = track('mbid')[0].childNodes[0].data except: trackmbid = '' try: albumname = track('album')[0].childNodes[0].data except: albumname = '' try: albummbid = track('album')[0].attributes['mbid'].value except: albummbid = '' try: date = track('date')[0].attributes['uts'].value except: date = '' output = [date, trackname, artistname, albumname, trackmbid, artistmbid, albummbid] return output def write_tracks(trackdict, outfile, startpage, page, totalpages): """Write dictionary content with all tracks to file.""" #create a sorted list from track dictionary. sortlist = [] for v in trackdict.values(): sortlist.append(v) sortlist.sort(reverse=True) #open output file and write tracks. f = open(outfile, 'a') for i in sortlist: #sys.stdout.write(("\t".join(trackdict[i]) + "\n").encode('utf-8')) f.write(("\t".join(i) + "\n").encode('utf-8')) print "Wrote page %s-%s of %s to file %s, exiting." % (startpage, page, totalpages, outfile) f.close() def main(username, startpage, outfile): trackdict = dict() page = startpage response = connect_server(username, page) totalpages = get_pageinfo(response) #totalpages = 2 if startpage > totalpages: sys.exit("First page (%s) is higher than total pages (%s), exiting." % (startpage, totalpages)) while page <= totalpages: #Skip connect if on first page, already have that one stored. if page > startpage: response = connect_server(username, page) #If empty response, something went wrong, write tracks to file and exit. if not response: write_tracks(trackdict, outfile, startpage, page-1, totalpages) sys.exit() tracklist = get_tracklist(response) for i in range(len(tracklist)): track = parse_track(tracklist, i) trackdict.setdefault(track[0], track) if (page % 10) == 0: print "Getting page %s of %s.." % (page, totalpages) page += 1 time.sleep(.5) write_tracks(trackdict, outfile, startpage, page-1, totalpages) if __name__ == "__main__": parser = OptionParser() username, outfile, startpage, server = get_options(parser) main(username, startpage, outfile)