Skip to content

Instantly share code, notes, and snippets.

@antzucaro
Created January 1, 2014 22:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antzucaro/8212369 to your computer and use it in GitHub Desktop.
Save antzucaro/8212369 to your computer and use it in GitHub Desktop.
Pulls listened tracks from a given user's Last.fm account between the provided time bounds, dumping the results to a file "tracks.csv". Usage: go run summarizr.go -user <username> -key <Last.fm API key> -from <Unix timestamp> -to <Unix timestamp>
Generate the data (timestamps represent the entirety of 2013):
go run summarizr.go -user antzucaro -key MY_API_KEY -from 1357016400 -to 1388552340
This produces a file "tracks.csv" with the selected range of data (8173 songs in total for me). One can load these tracks to a database easily with the below steps.
Create the database:
postgres=# create database tracks2013 encoding='utf-8';
CREATE DATABASE
postgres=# \c tracks2013
You are now connected to database "tracks2013".
Create the table for the tracks:
tracks2013=# create table tracks (
tracks2013(# artist character varying(100),
tracks2013(# album character varying(100),
tracks2013(# song character varying(100),
tracks2013(# date int
tracks2013(# );
CREATE TABLE
Load the generated CSV file into the table we just created:
tracks2013=# copy tracks from '/home/ant/tracks.csv' with (format csv);
COPY 8173
From there you can query until your heart is content! Here are some example queries:
Which artists did you listen to the most?
select artist, count(*) from tracks group by artist order by count(*) desc;
How many different artists did you listen to?
select count(distinct artist) from tracks;
How many tracks did you listen to per month?
select extract(month from to_timestamp(date)), count(*)
from tracks
group by extract(month from to_timestamp(date))
order by extract(month from to_timestamp(date));
Which artists did you listen to the most by month?
select artist, mon, plays
from (
select artist, extract(month from to_timestamp(date)) mon, count(*) plays, rank().
over (partition by extract(month from to_timestamp(date)) order by count(*) desc) rank
from tracks group by artist, extract(month from to_timestamp(date))
order by extract(month from to_timestamp(date)), count(*) desc
) trackplays
where rank = 1;
What song did you listen to the most?
select artist, song, count(*) from tracks group by artist, song order by count(*) desc;
How many different artists did we listen to, per month?
select extract(month from to_timestamp(date)), count(distinct artist)
from tracks
group by extract(month from to_timestamp(date))
order by extract(month from to_timestamp(date));)
Enjoy!
-Ant "Antibody" Zucaro
package main
import (
"encoding/csv"
"encoding/xml"
"flag"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
"time"
)
type Date struct {
XMLName xml.Name `xml:"date"`
Uts int `xml:"uts,attr"`
}
type Track struct {
XMLName xml.Name `xml:"track"`
Artist string `xml:"artist"`
Album string `xml:"album"`
Song string `xml:"name"`
Date Date `xml:"date"`
}
type RecentTracks struct {
XMLName xml.Name `xml:"recenttracks"`
User string `xml:"user,attr"`
CurrentPage int `xml:"page,attr"`
TotalPages int `xml:"totalPages,attr"`
Tracks []Track `xml:"track"`
}
type Result struct {
XMLName xml.Name `xml:"lfm"`
Status string `xml:"status,attr"`
RecentTracks RecentTracks
}
func getPage(user string, key string, from int, page int) *Result {
url := fmt.Sprintf("http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=%s&api_key=%s&limit=200&from=%d&page=%d", user, key, from, page)
fmt.Println(url)
r, err := http.Get(url)
defer r.Body.Close()
if err != nil {
panic("Error making the GET request to user.getrecenttracks.")
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
var rt *Result
rt = &Result{}
if err := xml.Unmarshal(body, rt); err != nil {
panic(err)
}
return rt
}
func main() {
var user = flag.String("user", "nobody", "user to summarize")
var key = flag.String("key", "", "API key to use when fetching")
var from = flag.Int("from", 0, "summarize from this time (format: unix timestamp)")
var to = flag.Int("to", 0, "summarize to this time (format: unix timestamp)")
flag.Parse()
f, err := os.Create("tracks.csv")
if err != nil {
panic(err)
}
defer f.Close()
c := csv.NewWriter(f)
page := 1
for rt := getPage(*user, *key, *from, page); page <= rt.RecentTracks.TotalPages; rt = getPage(*user, *key, *from, page) {
for _, v := range rt.RecentTracks.Tracks {
if v.Date.Uts >= *from && v.Date.Uts <= *to {
c.Write([]string{v.Artist, v.Album, v.Song, strconv.Itoa(v.Date.Uts)})
}
}
time.Sleep(500 * time.Millisecond)
page++
}
c.Flush()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment