Skip to content

Instantly share code, notes, and snippets.

@osa1
Created March 8, 2012 12:09
Show Gist options
  • Save osa1/2000733 to your computer and use it in GitHub Desktop.
Save osa1/2000733 to your computer and use it in GitHub Desktop.
find lastfm artist recommendations based on top artists listened by an user
(ns lastfm
(:require [clojure.string :as str]
[clojure.java.io :as io]
[clj-http.client :as client]
[clojure.zip :as zip]
[clojure.xml :as xml])
(:use [clojure.data.zip.xml]))
(defn- parse-str [s]
(zip/xml-zip (xml/parse (org.xml.sax.InputSource.
(java.io.StringReader. s)))))
(defn- build-get-data [attrs]
(let [remove-spaces #(str/replace % #" " "+")]
(str/join "&"
(map (fn [[k v]]
(str (remove-spaces k) "=" (remove-spaces v)))
attrs))))
(def api-addr "http://ws.audioscrobbler.com/2.0/")
(def api-key "133e0a02d0ffc0a34e19c8252a49aba0")
(defn user->top-artists [user]
(let [get-data (build-get-data {"method" "user.gettopartists",
"user" user,
"api_key" api-key})
xml-data (parse-str (:body (client/get (str api-addr "?" get-data))))]
(xml-> xml-data (tag= :topartists) (tag= :artist) (tag= :name) text)))
(defn artist->similar-artists [artist]
(let [get-data (build-get-data {"method" "artist.getsimilar",
"artist" artist,
"api_key" api-key})]
(xml-> (parse-str (:body (client/get (str api-addr "?" get-data))))
(tag= :similarartists) (tag= :artist) (tag= :name) text)))
(defn recommend [user]
(let [top-artists (set (user->top-artists user))
similars (apply concat (pmap artist->similar-artists top-artists))]
(sort #(compare (last %1) (last %2))
(reduce (fn [d artist]
(when (nil? (top-artists artist))
(conj d [artist (inc (get d artist 0))])))
{} similars))))
;;; USAGE:
;;; (recommend user-id)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment