def _get_things(self, method, thing, thing_type, params=None, cacheable=True): """Returns a list of the most played thing_types by this thing, in a tuple with the total number of pages of results. Includes an MBID, if found. """ doc = self._request(self.ws_prefix + "." + method, cacheable, params) toptracks_node = doc.getElementsByTagName('toptracks')[0] total_pages = int(toptracks_node.getAttribute('totalPages')) seq = [] for node in doc.getElementsByTagName(thing): title = _extract(node, "name") artist = _extract(node, "name", 1) mbid = _extract(node, "mbid") playcount = _number(_extract(node, "playcount")) thing = thing_type(artist, title, self.network) thing.mbid = mbid seq.append(TopItem(thing, playcount)) return seq, total_pages
def crawl_tag(song_hash_file): network = pylast.LastFMNetwork(api_key=API_KEY) taghash = {} tags = [] taginfo = [] with open(song_hash_file) as fin: for line in fin: [sid, title, artist] = line.strip().split('\t') #if int(sid)>3: # break print line.strip() title = title.replace('\/','/') title = title.replace('w/ ','feat. ') tags.append({}) track = network.get_track(artist, title) try: toptags = track.get_top_tags() except: if title.find('(feat.')!=-1: track = network.get_track(artist, title[:title.find('(feat.')]) elif title.find('feat.')!=-1: track = network.get_track(artist, title[:title.find('feat.')]) else: print sid, ':', title, 'not found' continue try: toptags = track.get_top_tags() except: print sid, ':', title, 'not found' continue for tag in toptags: if tag.item.name is None or tag.weight is None: continue if tag.item.name not in taghash: taghash[tag.item.name] = len(taghash) tags[-1][taghash[tag.item.name]] = int(tag.weight) errlist = [] for k in taghash: print k tag = network.get_tag(k) taginfo.append({'tid':taghash[k], 'name':k}) try: info = tag._request('tag.getInfo', True) reach = pylast._extract(info, 'reach') taggings = pylast._extract(info, 'taggings') if reach is None or taggings is None: errlist.append(k) else: taginfo[-1]['reach'] = reach taginfo[-1]['taggings'] = taggings except: errlist.append(k) print 'errlist',len(errlist),errlist taginfo.sort(key=lambda k:k['tid']) return tags, taginfo
def _extract_track_data(track: Node): track_mbid = pylast._extract(track, "mbid") track_title = pylast._extract(track, "name") timestamp = dt.datetime.fromtimestamp( int(track.getElementsByTagName("date")[0].getAttribute("uts"))) artist_name = pylast._extract(track, "artist") artist_mbid = track.getElementsByTagName("artist")[0].getAttribute("mbid") album_title = pylast._extract(track, "album") album_mbid = track.getElementsByTagName("album")[0].getAttribute("mbid") # TODO: could call track/album/artist.getInfo here, and get more info? # Handle missing titles if album_title is None: album_title = "(unknown album)" # If we don't have mbids, synthesize them if not artist_mbid: artist_mbid = "md5:" + hashlib.md5( artist_name.encode("utf8")).hexdigest() if not album_mbid: h = hashlib.md5() h.update(artist_mbid.encode("utf8")) h.update(album_title.encode("utf8")) album_mbid = "md5:" + h.hexdigest() if not track_mbid: h = hashlib.md5() h.update(album_mbid.encode("utf8")) h.update(track_title.encode("utf8")) track_mbid = "md5:" + h.hexdigest() return { "artist": { "id": artist_mbid, "name": artist_name }, "album": { "id": album_mbid, "title": album_title, "artist_id": artist_mbid }, "track": { "id": track_mbid, "album_id": album_mbid, "title": track_title }, "play": { "track_id": track_mbid, "timestamp": timestamp }, }
def get_similar(self, limit=None): if limit: doc = self._request(self.ws_prefix + '.getSimilar', True, params={'artist': self.artist.name, 'track': self.title, 'limit': limit}) else: doc = self._request(self.ws_prefix + '.getSimilar', True) seq = [] for node in doc.getElementsByTagName(self.ws_prefix): title = pylast._extract(node, 'name') artist = pylast._extract(node, 'name', 1) match = pylast._number(pylast._extract(node, "match")) seq.append(pylast.SimilarItem(pylast.Track(artist, title, self.network), match)) return seq
def check_album(artist, album): album_object = network.get_album(artist, album) corrected_album_name = pylast._extract(album_object._request(album_object.ws_prefix + ".getCorrection"), "name") if not corrected_album_name: print('No suggested album.') return album if (album == corrected_album_name): # No change, return immediately and don't waste server hits return album elif album == "" and not corrected_album_name: # Blank album return album corrected_album_object = network.get_album(artist, corrected_album_name) if (album_object != corrected_album_object): response = input(f'Should album {album} be {corrected_album_name}? (y/N)').lower() if (response == "y"): album = corrected_album_name elif (album != corrected_album_name): print(f"Suggested album name correction {corrected_album_name} does not affect scrobble, recommend changing.") response = input(f'Should album {album} be {corrected_album_name}? (Y/n)').lower() if (response == "n"): pass else: album = corrected_album_name return album
def tag(self, irc, msg, args, tag): """<tag> Returns some info on the tag <tag>.""" try: summaryLength = 260 outputString = "%s%s%s%s" summaryString = "\"%s\" " artistsString = " Top artists: %s." #tracksString = " Top tracks: %s." #tagsString = " Similar tags: %s." sString = "'s%s" nothingString = " has no top artists." urlString = " %s" tagRef = network.get_tag(tag) tag = tagRef.get_name(properly_capitalized = True) tag = tag[0].upper() + tag[1:] summary = pylast._extract(tagRef._request("tag.getInfo", True), "summary") if summary != None and summary != "": summary = re.sub("\<[^<]+\>", "", summary) summary = re.sub("\s+", " ", summary) summary = summary[:summaryLength] + "..." if (summary[:summaryLength] != summary) else summary topArtists = tagRef.get_top_artists() if len(topArtists) > 3: topArtists = topArtists[:3] topArtistsText = commaAndify([x.item.get_name() for x in topArtists]) if len(topArtistsText) > 0: topArtistsText = artistsString % topArtistsText #topTracks = tagRef.get_top_tracks() #if len(topTracks) > 3: # topTracks = topTracks[:3] #topTracksText = commaAndify([x.item.get_artist().get_name() # + " - " + x.item.get_name() for x in topTracks]).encode("utf-8") #if len(topTracksText) > 0: # topTracksText = tracksString % topTracksText #similarTags = tagRef.get_similar() #if len(similarTags) > 3: # similarTags = similarTags[:3] #similarTagsText = commaAndify([x.get_name() for x in similarTags]) #if len(similarTagsText) > 0: # similarTagsText = tagsString % similarTagsText data = sString % (topArtistsText) if len(topArtistsText) is 0: data = nothingString else: data = data[:3] + data[3].lower() + data[4:] url = tagRef.get_url() if len(url) > 0: url = urlString % url summary = summaryString % summary if (summary != None and summary != "") else "" output = outputString % (summary, tag, data, url) irc.reply(output.encode("utf-8")) except pylast.WSError, e: irc.error(str(e))
def get_child(cls, response, field): """ Retrieves child element from response and casts it according to field type in DB model. Parameters ---------- response : XML string Response from Last.fm field : DB attribute. Attribute object contains name, which matches child in XML tree, and db_value, which casts string to appropriate type. """ return field.db_value(pylast._extract(response, field.name))
def _get_things(self, method, thing, thing_type, params=None, cacheable=True): """Returns a list of the most played thing_types by this thing, in a tuple with the total number of pages of results. Includes an MBID, if found. """ doc = self._request(self.ws_prefix + "." + method, cacheable, params) toptracks_node = doc.getElementsByTagName("toptracks")[0] total_pages = int(toptracks_node.getAttribute("totalPages")) seq = [] for node in doc.getElementsByTagName(thing): title = _extract(node, "name") artist = _extract(node, "name", 1) mbid = _extract(node, "mbid") playcount = _number(_extract(node, "playcount")) thing = thing_type(artist, title, self.network) thing.mbid = mbid seq.append(TopItem(thing, playcount)) return seq, total_pages
def scrape_artisttags(self, artist, doc = None): """ Iterator over top tags associated with artist Parameters ---------- artist : pylast.Artist Artist object. doc : xml Answer to artist.getInfo request. Used to aviod repeating request when underlying caching is disabled. """ if not doc: doc = artist._request('artist.getInfo', True) for tag in doc.getElementsByTagName("tag"): yield pylast._extract(tag, "name")