(Zaktualizowano 2016-05-09, bardziej solidny niż aktualna najlepsza odpowiedź)
Jeśli chcesz tylko zapisać kilka list odtwarzania, możesz po prostu użyć poniższego fragmentu kodu JavaScript. Ten fragment kodu może zapisać każdą listę, tak jak jest pokazana na stronie internetowej, więc działa również dla wszystkich widoków bibliotek utworów / albumów / artystów. Na końcu tej odpowiedzi wymieniłem dwie inne alternatywy.
Wejdź na: https://play.google.com/music/listen#/all (lub swoją listę odtwarzania)
Otwórz konsolę programisty (F12 dla Chrome). Wklej kod poniżej do konsoli.
Wszystkie zeskrobane utwory są przechowywane w allsongs
obiekcie, a tekstowa wersja listy jest kopiowana do schowka. Polecam uruchomić
songsToText("all",true)
później, aby uzyskać pełne informacje o CSV. Uruchom copy(outText)
ręcznie, jeśli kopiowanie ze schowka nie działało przy pierwszej próbie.
Kod (najnowsza wersja 10 maja 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);
Najnowszy kod na Github (Gist) tutaj: https://gist.github.com/jmiserez/c9a9a0f41e867e5ebb75
Jeśli chcesz otrzymać wynik w formacie tekstowym, możesz wywołać funkcję songsToText (). Możesz wybrać styl, wybrać format, a jeśli tylko polubione / polecone utwory powinny zostać wyeksportowane. Wynikowa lista zostanie następnie wklejona do schowka. Style all
, artist
, artistalbum
, artistsong
,
artistalbumsong
. Plik CSV spowoduje utworzenie pliku CSV i można go pominąć (domyślnie false). Likedonly może zostać pominięty (domyślnie false) lub ustawiony na true, i będzie filtrował wszystkie utwory z ocenami większymi lub równymi 5. Np .:
songsToText("all",true,false)
wyeksportuje wszystkie utwory w formacie csv.
songsToText("all",true,true)
wyeksportuje tylko lubiane utwory w formacie csv.
songsToText("artistsong",false,false)
wyeksportuje wszystkie utwory jako tekst.
Następnie możesz wkleić dane w dowolnym miejscu, na przykład http://www.ivyishere.org/, jeśli chcesz dodać utwory lub albumy do konta Spotify. Aby Ivy rozpoznała pełne albumy, użyj stylu „artistalbum”. W przypadku piosenek użyj stylu „wykonawcy”.
Informacje o fragmencie:
jest on oparty na oryginalnej odpowiedzi Michaela Smitha, ale jest nieco bardziej niezawodny. Wprowadziłem następujące ulepszenia:
Działa na listach odtwarzania, a także w bibliotece. Brakujące kolumny są ignorowane, a kolejność ustalona, więc powinna działać na prawie każdej liście utworów w Google Music.
Zatrzymuje się, gdy osiągnie dno (wykryje pozycję przewijania) lub po upływie określonego czasu. Przekroczono limit czasu, aby zapobiec niekończącej się pętli w przypadku, gdy kod wykrywania przewijania jest wyłączony o kilka pikseli.
Jest znacznie szybszy (interwał co 1ms), ale czeka, jeśli dane nie będą gotowe (do określonego limitu czasu, obecnie 3s).
Wykonuje deduplikację podczas działania i na wyjściu.
Zbiera oceny: „niezdefiniowany” nigdy nie jest oceniany, „0” nie jest oceniany (tzn. Raz oceniany, ale następnie usuwany), „1” oznacza kciuk w dół, a „5” jest kciuk w górę (lubiany).
Oprócz podstawowych ulepszeń ładnie formatuje tekst i kopiuje go do schowka. Możesz także pobrać dane jako CSV, jeśli chcesz, uruchamiając songsToText
funkcję po raz drugi.
Alternatywy:
Jeśli potrzebujesz interfejsu API języka Python, sprawdź nieoficjalny projekt interfejsu Google Music API .
Jeśli masz mnóstwo list odtwarzania i chcesz wyeksportować je wszystkie za jednym razem, wypróbuj eksportera list odtwarzania gmusic-scripts, który może to zrobić (Python, używa nieoficjalnego projektu API).