My New “Top Artists Last 7 Days” Widget

Note Redux: I changed my approach, yet again. Scroll farther down to see the latest.

Note: I changed my approach on this, so scroll down to see how I’m doing it now.

I’ve been wanting a widget or an auto-post on the blog for a while that would show my most-listened-to bands over the previous week. Tumblr users have had something like this for a while, and there were efforts to do this for WordPress before, but they either don’t seem to work with the latest versions of WP, or they only pulled top tracks (not artists), or they pulled album covers, instead of text. All of that is to say that I couldn’t find anything pre-made to use.

So, I had to roll my own. I did so in about 10 minutes using the PHP Code Widget and the script on this page. The only drawback to this is you have to get a developer account with last.fm, but it’s free, so no big deal there. I installed the PHP Code Widget , then pasted the script into a new widget. The only changes I had to make were to replace the appropriate bits in the script with my info, and to escape a couple of double-quotes. Now if you look down the right side of the blog, below the Twitter and Facebook links, you’ll see a rolling record of my top-artists. In case you were wondering what I’ve been listening to. 🙂

The only thing I’m not sure about is how this will work with the two levels of caching I use (WP Super Cache and Cloudflare). I suppose we’ll see in the next few days, eh?

11/23/2011 Update: I decided that I didn’t like the way I was doing this, for a couple of reasons. First, each time someone viewed the page, it would be making a call to Last.fm for my stats. This is too often. Also, the values returned using the developer API were at odds with what you can get just going through the web. So what I did was write a Ruby script to pull the feed once a day, parse it and output HTML to a file. I then used the PHP Code Widget to include it. Far simpler, in my opinion.

Here’s the Ruby code:

[ruby]
#!/usr/bin/ruby

require ‘rexml/document’
require ‘open-uri’

include REXML

open("http://ws.audioscrobbler.com/2.0/user/joeyGibson/weeklyartistchart.xml") do |http|
response = http.read
doc = REXML::Document.new response

index = 0

File.open(ARGV[0], "w") do |out|
out.write("<html><head>n")
out.write("<meta charset="UTF-8"/>n")
out.write("<body><ol>n")

doc.elements.each("weeklyartistchart/artist") do |artist|
break if index == 5

out.write "<li><a href="#{artist.elements[‘url’].text}">#{artist.elements[‘name’].text}</a>, Plays: #{artist.elements[‘playcount’].text}</li>n"

index += 1
end

out.puts("</ol></body></html>n")
end
end
[/ruby]

and here’s the PHP that loads it:

[php]
<?php include("/tmp/artists.html"); ?>
[/php]

That’s it.

11/26/2011 Update: Well, I’ve changed it again. I discovered that the RSS feed I was pulling is not updated with any sort of frequency. It certainly doesn’t represent the “last seven days” as it claims to. At any rate, it differs greatly from what Last.fm shows on the web. So I decided to grab the HTML and pull out the interesting bits. I wrote another Ruby script, this time using Hpricot to parse the HTML, which took about 10 minutes. So now, what you see on the right should be the current values for the “last seven days.” Here’s the latest script:

[ruby]
#!/usr/local/bin/ruby

require ‘rubygems’
require ‘hpricot’
require ‘open-uri’

open("http://www.last.fm/user/your-username-here/charts?rangetype=week&subtype=artists&quot;) do |http|
doc = Hpricot.parse(http.read)

count = 0

File.open(ARGV[0], "w") do |out|
out.write("<html><head>n")
out.write("<meta charset="UTF-8"/>n")
out.write("<body><ol>n")

doc.search("td[@class=subjectCell]").each do |subjectCell|
break if count == 5

artistString = subjectCell.get_attribute("title")

artistString =~ /^(.+), played (d+) times$/
artist = $1
playCount = $2

subjectCell.search("a").each do |a|
url = a.get_attribute("href")
url = "http://last.fm#{url}"

str = "#{artist}, #{url}, #{playCount}"

out.write "<li><a href="#{url}">#{artist}</a>, Plays: #{playCount}</li>n"
end

count += 1
end

out.puts("</ol></body></html>n")
end
end
[/ruby]

I’m hopeful this is the last change.