Created
May 20, 2019 16:53
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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