Skip to content

Instantly share code, notes, and snippets.

@unaipme
Created May 20, 2019 16:53
Show Gist options
  • Save unaipme/85e344553adf87303ec503b88d91e348 to your computer and use it in GitHub Desktop.
Save unaipme/85e344553adf87303ec503b88d91e348 to your computer and use it in GitHub Desktop.
Java class to get the audio features of some songs from Spotify's official API.
package eus.unai.spotidump;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import com.opencsv.CSVReader;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.*;
import java.util.stream.Collectors;
public class SpotiDump {
private static final String ACCESS_TOKEN = System.getenv("ACCESS_TOKEN");
private static final String TRACK_URL = "https://open.spotify.com/track/";
private static final String GET_TRACKS = "https://api.spotify.com/v1/tracks/?ids=";
private static final String GET_ALBUMS = "https://api.spotify.com/v1/albums/?ids=";
private static final String GET_FEATURES = "https://api.spotify.com/v1/audio-features/";
private static final Integer LOOP_SIZE = 11;
public static void main(String [] args) throws Exception {
Set<String> idSet = new HashSet<>();
try (CSVReader csvReader = new CSVReader(new FileReader("daily-200.csv"))) {
Iterator<String []> it = csvReader.iterator();
while (it.hasNext()) {
String [] songURL = it.next()[4].split("/");
String id = songURL[songURL.length - 1];
if (!"".equals(id)) idSet.add(id);
}
}
String [] ids = idSet.toArray(new String [0]);
HttpClient client = new DefaultHttpClient();
Gson gson = new Gson();
try (PrintWriter writer = new PrintWriter(new FileWriter("spotify.csv"))) {
writer.println("URL,release-date,genres,danceability,energy,speechiness,valence,tempo");
for (int i = 0; i < ids.length; i += LOOP_SIZE) {
int retry = 3;
while (retry > 0) {
try {
String requestIds = String.join(",", Arrays.copyOfRange(ids, i, i + LOOP_SIZE));
System.out.println(requestIds);
HttpGet getSongs = new HttpGet(GET_TRACKS + requestIds);
getSongs.addHeader("Authorization", "Bearer " + ACCESS_TOKEN);
LinkedTreeMap<String, Object> songsResponse = gson.fromJson(EntityUtils.toString(client.execute(getSongs).getEntity(), "UTF-8"), LinkedTreeMap.class);
List<LinkedTreeMap<String, Object>> tracks = (List) songsResponse.get("tracks");
String albumIds = tracks.stream().map(SpotiDump::albumIdFromTracks).collect(Collectors.joining(","));
HttpGet getAlbums = new HttpGet(GET_ALBUMS + albumIds);
getAlbums.addHeader("Authorization", "Bearer " + ACCESS_TOKEN);
LinkedTreeMap<String, Object> albumsResponse = gson.fromJson(EntityUtils.toString(client.execute(getAlbums).getEntity(), "UTF-8"), LinkedTreeMap.class);
List<LinkedTreeMap<String, Object>> albums = (List) albumsResponse.get("albums");
for (int j = i; j < i + LOOP_SIZE; j++) {
String id = ids[j];
System.out.println(id);
HttpGet getFeatures = new HttpGet(GET_FEATURES + id);
getFeatures.addHeader("Authorization", "Bearer " + ACCESS_TOKEN);
LinkedTreeMap<String, Object> featuresResponse = gson.fromJson(EntityUtils.toString(client.execute(getFeatures).getEntity(), "UTF-8"), LinkedTreeMap.class);
String danceability = featuresResponse.getOrDefault("danceability", "").toString();
String energy = featuresResponse.getOrDefault("energy", "").toString();
String speechiness = featuresResponse.getOrDefault("speechiness", "").toString();
String valence = featuresResponse.getOrDefault("valence", "").toString();
String tempo = featuresResponse.getOrDefault("tempo", "").toString();
writer.println(String.format("%s%s,%s,%s,%s,%s,%s,%s,%s",
TRACK_URL, id, releaseDateFromAlbum(albums.get(j - i)), genresFromAlbum(albums.get(j - i)),
danceability, energy, speechiness, valence, tempo));
}
break;
} catch (NullPointerException e) {
e.printStackTrace();
Thread.sleep(5000);
retry--;
}
}
}
}
}
private static String albumIdFromTracks(LinkedTreeMap<String, Object> tracks) {
return ((LinkedTreeMap<String, Object>) tracks.get("album")).get("id").toString();
}
private static String genresFromAlbum(LinkedTreeMap<String, Object> albums) {
List<String> genres = ((List<String>) albums.get("genres"));
if (genres.isEmpty()) return "";
else return genres.get(0);
}
private static String releaseDateFromAlbum(LinkedTreeMap<String, Object> albums) {
return albums.get("release_date").toString();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment