(2016-05-09 güncellendi, en güncel yanıtlardan daha sağlam)
Birkaç şarkı listesini kaydetmeniz gerekiyorsa, aşağıdaki Javascript snippet'imi kullanabilirsiniz. Bu pasaj, her listeyi web sayfasında gösterildiği gibi kaydedebilir, böylece tüm şarkılar / albümler / sanatçılar kitaplık görünümleri için de çalışır. Bu cevabın sonunda iki alternatif daha listeledik.
Git: https://play.google.com/music/listen#/all (veya çalma listeniz)
Bir geliştirici konsolu açın (Chrome için F12). Aşağıdaki kodu konsola yapıştırın.
Alınan tüm şarkılar allsongs
nesnede saklanır ve listenin bir metin sürümü panoya kopyalanır. songsToText("all",true)
CSV'nin tam bilgilerini almak için daha sonra çalıştırmanızı öneririm
. copy(outText)
Pano kopyalama ilk denemede işe yaramadıysa el ile çalıştırın .
Kod (en son sürüm 10 Mayıs 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);
Buradaki Github (Gist) hakkındaki en son kod: https://gist.github.com/jmiserez/c9a9a0f41e867e5ebb75
Çıktının bir metin biçiminde olmasını istiyorsanız, songsToText () işlevini çağırabilirsiniz. Bir stil seçebilir, formatı seçebilir ve yalnızca sevilen / küçük şarkılar dışa aktarılmalıdır. Sonuçta ortaya çıkan liste panoya yapıştırılır. Stiller vardır all
, artist
, artistalbum
, artistsong
,
artistalbumsong
. CSV, CSV dosyasıyla sonuçlanır ve bırakılabilir (varsayılan olarak yanlış). Benzer şekilde, bırakılabilir (varsayılan olarak false olur) veya true olarak ayarlanabilir ve tüm şarkıları 5'ten büyük veya 5'e eşit derecelendirir.
songsToText("all",true,false)
tüm şarkıları csv biçiminde dışa aktaracaktır.
songsToText("all",true,true)
csv formatında sadece sevilen şarkıları vereceğiz.
songsToText("artistsong",false,false)
tüm şarkıları metin olarak dışa aktaracaktır.
Daha sonra verileri istediğiniz yere yapıştırabilirsiniz, örneğin şarkıları veya albümleri Spotify hesabınıza eklemek istiyorsanız, http://www.ivyishere.org/ . Ivy'nin tüm albümleri tanımasını sağlamak için "artistalbum" tarzını kullanın. Şarkılar için "artistsong" tarzını kullanın.
Snippet hakkında:
Bu, Michael Smith'in orijinal cevabına dayanıyor, ancak biraz daha sağlam. Aşağıdaki iyileştirmeleri yaptım:
Kütüphanede olduğu gibi çalma listelerinde de çalışır. Eksik sütunlar yoksayılır ve sipariş çözülür, bu nedenle Google Müzik içindeki neredeyse tüm şarkı listelerinde çalışması gerekir.
Dibe ulaştığında (kaydırma konumunu algılar) veya belirtilen zaman aşımından sonra durur. Zaman aşımı, kaydırma algılama kodunun birkaç piksel kapalı olması durumunda sonsuz bir döngüyü önlemek için oradadır.
Çok daha hızlı (her 1ms aralıklarla), ancak verilerin hazır olmaması durumunda bekler (belirtilen zaman aşımına kadar, şu anda 3s).
İşlem sırasında ve çıktıda tekilleştirme yapar.
Toplar derecelendirmeleri: "tanımsız" hiçbir zaman derecelendirilmez, "0" derecelendirilmez (yani bir kez derecelendirilir ancak sonra kaldırılır), "1" yaşasın düşer ve "5" yaşlanır (beğenilir).
Temel gelişmelere ek olarak, metni güzel bir şekilde biçimlendirir ve panoya kopyalar. İsterseniz, songsToText
işlevi ikinci kez çalıştırarak da verileri CSV olarak alabilirsiniz .
Alternatifler:
Bir Python API'sine ihtiyacınız varsa, resmi olmayan Google Music API projesini inceleyin.
Tonlarca çalma listeniz varsa ve tümünü bir kerede dışa aktarmak istiyorsanız , bunu yapabilecek gmusic-script çalma listesi ihracatçısı deneyin (Python, resmi olmayan API projesini kullanır).