(Aggiornato il 05/05/2016, più robusto dell'attuale risposta principale)
Se hai solo bisogno di salvare alcune playlist, puoi semplicemente usare il mio frammento Javascript qui sotto. Questo frammento può salvare ogni elenco come mostrato nella pagina Web, quindi funziona anche per tutte le visualizzazioni della libreria di brani / album / artisti. Ho elencato altre due alternative alla fine di questa risposta.
Vai a: https://play.google.com/music/listen#/all (o la tua playlist)
Apri una console per sviluppatori (F12 per Chrome). Incolla il codice qui sotto nella console.
Tutte le canzoni raschiate sono memorizzate allsongs
nell'oggetto e una versione di testo dell'elenco viene copiata negli appunti. Raccomando di correre in
songsToText("all",true)
seguito per ottenere le informazioni CSV complete. Esegui copy(outText)
manualmente se la copia degli Appunti non ha funzionato al primo tentativo.
Codice (ultima versione 10 maggio 2016, Rev 30):
var allsongs = []
var outText = "";
var songsToText = function(style, csv, likedonly){
if (style === undefined){
console.log("style is undefined.");
return;
}
var csv = csv || false; // defaults to false
var likedonly = likedonly || false; // defaults to false
if (likedonly) {
console.log("Only selecting liked songs");
}
if (style == "all" && !csv){
console.log("Duration, ratings, and playcount will only be exported with the CSV flag");
}
outText = "";
if (csv) {
if (style == "all") {
//extra line
outText = "artist,album,title,duration,playcount,rating,rating_interpretation" + "\n";
} else if (style == "artist") {
} else if (style == "artistsong") {
} else if (style == "artistalbum") {
} else if (style == "artistalbumsong") {
} else {
console.log("style not defined");
}
}
var numEntries = 0;
var seen = {};
for (var i = 0; i < allsongs.length; i++) {
var curr = "";
var properTitle = allsongs[i].title.replace(/[\n\r!]/g, '').trim();
if (!likedonly || (likedonly && allsongs[i].rating >= 5)){
if (csv) {
if (style == "all") {
//extra line
curr += '"' + allsongs[i].artist.replace(/"/g, '""').trim() + '"' + ",";
curr += '"' + allsongs[i].album.replace(/"/g, '""').trim() + '"' + ",";
curr += '"' + properTitle.replace(/"/g, '""').trim() + '"' + ",";
curr += '"' + allsongs[i].duration.replace(/"/g, '""').trim() + '"' + ",";
curr += '"' + allsongs[i].playcount.replace(/"/g, '""').trim() + '"' + ",";
curr += '"' + allsongs[i].rating.replace(/"/g, '""').trim() + '"' + ",";
curr += '"' + allsongs[i].rating_interpretation.replace(/"/g, '""').trim() + '"';
} else if (style == "artist") {
curr += '"' + allsongs[i].artist.replace(/"/g, '""').trim() + '"';
} else if (style == "artistsong") {
curr += '"' + allsongs[i].artist.replace(/"/g, '""').trim() + '"' + ",";
curr += '"' + properTitle.replace(/"/g, '""').trim() + '"';
} else if (style == "artistalbum") {
curr += '"' + allsongs[i].artist.replace(/"/g, '""').trim() + '"' + ",";
curr += '"' + allsongs[i].album.replace(/"/g, '""').trim() + '"';
} else if (style == "artistalbumsong") {
curr += '"' + allsongs[i].artist.replace(/"/g, '""').trim() + '"' + ",";
curr += '"' + allsongs[i].album.replace(/"/g, '""').trim() + '"' + ",";
curr += '"' + properTitle.replace(/"/g, '""').trim() + '"';
} else {
console.log("style not defined");
}
} else {
if (style == "all"){
curr = allsongs[i].artist + " - " + allsongs[i].album + " - " + properTitle + " [[playcount: " + allsongs[i].playcount + ", rating: " + allsongs[i].rating_interpretation + "]]" ;
} else if (style == "artist"){
curr = allsongs[i].artist;
} else if (style == "artistalbum"){
curr = allsongs[i].artist + " - " + allsongs[i].album;
} else if (style == "artistsong"){
curr = allsongs[i].artist + " - " + properTitle;
} else if (style == "artistalbumsong"){
curr = allsongs[i].artist + " - " + allsongs[i].album + " - " + properTitle;
} else {
console.log("style not defined");
}
}
if (!seen.hasOwnProperty(curr)){ // hashset
outText = outText + curr + "\n";
numEntries++;
seen[curr] = true;
} else {
//console.log("Skipping (duplicate) " + curr);
}
}
}
console.log("=============================================================");
console.log(outText);
console.log("=============================================================");
try {
copy(outText);
console.log("copy(outText) to clipboard succeeded.");
} catch (e) {
console.log(e);
console.log("copy(outText) to clipboard failed, please type copy(outText) on the console or copy the log output above.");
}
console.log("Done! " + numEntries + " lines in output. Used " + numEntries + " unique entries out of " + allsongs.length + ".");
};
var scrapeSongs = function(){
var intervalms = 1; //in ms
var timeoutms = 3000; //in ms
var retries = timeoutms / intervalms;
var total = [];
var seen = {};
var topId = "";
document.querySelector("#mainContainer").scrollTop = 0; //scroll to top
var interval = setInterval(function(){
var songs = document.querySelectorAll("table.song-table tbody tr.song-row");
if (songs.length > 0) {
// detect order
var colNames = {
index: -1,
title: -1,
duration: -1,
artist: -1,
album: -1,
playcount: -1,
rating: -1
};
for (var i = 0; i < songs[0].childNodes.length; i++) {
colNames.index = songs[0].childNodes[i].getAttribute("data-col") == "index" ? i : colNames.index;
colNames.title = songs[0].childNodes[i].getAttribute("data-col") == "title" ? i : colNames.title;
colNames.duration = songs[0].childNodes[i].getAttribute("data-col") == "duration" ? i : colNames.duration;
colNames.artist = songs[0].childNodes[i].getAttribute("data-col") == "artist" ? i : colNames.artist;
colNames.album = songs[0].childNodes[i].getAttribute("data-col") == "album" ? i : colNames.album;
colNames.playcount = songs[0].childNodes[i].getAttribute("data-col") == "play-count" ? i : colNames.playcount;
colNames.rating = songs[0].childNodes[i].getAttribute("data-col") == "rating" ? i : colNames.rating;
}
// check if page has updated/scrolled
var currId = songs[0].getAttribute("data-id");
if (currId == topId){ // page has not yet changed
retries--;
scrollDiv = document.querySelector("#mainContainer");
isAtBottom = scrollDiv.scrollTop == (scrollDiv.scrollHeight - scrollDiv.offsetHeight)
if (isAtBottom || retries <= 0) {
clearInterval(interval); //done
allsongs = total;
console.log("Got " + total.length + " songs and stored them in the allsongs variable.");
console.log("Calling songsToText with style all, csv flag true, likedonly false: songsToText(\"all\", false).");
songsToText("artistalbumsong", false, false);
}
} else {
retries = timeoutms / intervalms;
topId = currId;
// read page
for (var i = 0; i < songs.length; i++) {
var curr = {
dataid: songs[i].getAttribute("data-id"),
index: (colNames.index != -1 ? songs[i].childNodes[colNames.index].textContent : ""),
title: (colNames.title != -1 ? songs[i].childNodes[colNames.title].textContent : ""),
duration: (colNames.duration != -1 ? songs[i].childNodes[colNames.duration].textContent : ""),
artist: (colNames.artist != -1 ? songs[i].childNodes[colNames.artist].textContent : ""),
album: (colNames.album != -1 ? songs[i].childNodes[colNames.album].textContent : ""),
playcount: (colNames.playcount != -1 ? songs[i].childNodes[colNames.playcount].textContent : ""),
rating: (colNames.rating != -1 ? songs[i].childNodes[colNames.rating].getAttribute("data-rating") : ""),
rating_interpretation: "",
}
if(curr.rating == "undefined") {
curr.rating_interpretation = "never-rated"
}
if(curr.rating == "0") {
curr.rating_interpretation = "not-rated"
}
if(curr.rating == "1") {
curr.rating_interpretation = "thumbs-down"
}
if(curr.rating == "5") {
curr.rating_interpretation = "thumbs-up"
}
if (!seen.hasOwnProperty(curr.dataid)){ // hashset
total.push(curr);
seen[curr.dataid] = true;
}
}
songs[songs.length-1].scrollIntoView(true); // go to next page
}
}
}, intervalms);
};
scrapeSongs();
// for the full CSV version you can now call songsToText("all", true);
Codice più recente su Github (Gist) qui: https://gist.github.com/jmiserez/c9a9a0f41e867e5ebb75
Se desideri un output in formato testo, puoi chiamare la funzione songsToText (). Puoi selezionare uno stile, scegliere il formato e, se solo i brani piaciuti / sfogliati, dovrebbero essere esportati. L'elenco risultante verrà quindi incollato negli Appunti. Gli stili sono all
, artist
, artistalbum
, artistsong
,
artistalbumsong
. CSV genererà un file CSV e può essere lasciato fuori (il valore predefinito è false). Likedonly può essere escluso (il valore predefinito è false) o impostato su true e filtrerà tutti i brani con voti maggiori o uguali a 5. Ad esempio:
songsToText("all",true,false)
esporterà tutte le canzoni in formato CSV.
songsToText("all",true,true)
esporterà solo le canzoni piaciute in formato CSV.
songsToText("artistsong",false,false)
esporterà tutti i brani come testo.
Puoi quindi incollare i dati ovunque tu voglia, ad esempio http://www.ivyishere.org/ se desideri aggiungere brani o album al tuo account Spotify. Per fare in modo che Ivy riconosca gli album completi, usa lo stile "artistalbum". Per le canzoni, usa lo stile "artistong".
Informazioni sullo snippet:
si basa sulla risposta originale di Michael Smith, ma è un po 'più robusto. Ho apportato i seguenti miglioramenti:
Funziona su playlist e sulla biblioteca. Eventuali colonne mancanti vengono ignorate e l'ordine viene capito, quindi dovrebbe funzionare su quasi tutti gli elenchi di brani all'interno di Google Music.
Si ferma quando raggiunge il fondo (rileva la posizione di scorrimento) o dopo il timeout specificato. Il timeout è lì per impedire un ciclo infinito nel caso in cui il codice di rilevamento scorrimento sia disattivato di alcuni pixel.
È molto più veloce (intervallo ogni 1 ms), ma attende se i dati non sono pronti (fino al timeout specificato, attualmente 3 secondi).
Esegue la deduplicazione durante il funzionamento e sull'output.
Raccoglie le valutazioni: "undefined" non viene mai valutato, "0" non viene valutato (ovvero una volta valutato ma poi rimosso), "1" è il pollice in giù e "5" è il pollice in alto (piaciuto).
Oltre ai miglioramenti di base, formatta anche il testo e lo copia negli Appunti. Se lo desideri, puoi anche ottenere i dati come CSV, eseguendo la songsToText
funzione una seconda volta.
alternative:
Se hai bisogno di un'API Python, dai un'occhiata al progetto non ufficiale dell'API di Google Music .
Se hai tonnellate di playlist e vuoi esportarle tutte in una volta, prova l' esportatore di playlist gmusic-script che può farlo (Python, usa il progetto API non ufficiale).