(อัปเดตเมื่อวันที่ 2016-05-09 แข็งแกร่งกว่าคำตอบยอดนิยมปัจจุบัน)
หากคุณต้องการบันทึกเพลย์ลิสต์เพียงไม่กี่คุณก็สามารถใช้ข้อมูลโค้ด Javascript ของฉันด้านล่าง ตัวอย่างนี้สามารถบันทึกทุกรายการตามที่ปรากฏบนหน้าเว็บดังนั้นจึงเหมาะสำหรับมุมมองไลบรารีเพลง / อัลบั้ม / ศิลปินทั้งหมด ฉันได้แสดงอีกสองทางเลือกในตอนท้ายของคำตอบนี้
ไปที่: https://play.google.com/music/listen#/all (หรือเพลย์ลิสต์ของคุณ)
เปิดคอนโซลนักพัฒนาซอฟต์แวร์ (F12 สำหรับ Chrome) วางรหัสด้านล่างลงในคอนโซล
เพลงที่คัดลอกมาทั้งหมดจะถูกเก็บไว้ในallsongs
วัตถุและคัดลอกรายการข้อความไปยังคลิปบอร์ด ฉันขอแนะนำให้ทำงาน
songsToText("all",true)
หลังจากนั้นเพื่อรับข้อมูล CSV ทั้งหมด เรียกใช้copy(outText)
ด้วยตนเองหากการคัดลอกคลิปบอร์ดไม่ทำงานในครั้งแรก
รหัส (เวอร์ชั่นล่าสุด 10 พฤษภาคม 2559, 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);
รหัสล่าสุดบน Github (สรุปสาระสำคัญ) ที่นี่: https://gist.github.com/jmiserez/c9a9a0f41e867e5ebb75
หากคุณต้องการเอาต์พุตในรูปแบบข้อความสามารถเรียกใช้ฟังก์ชั่น songsToText () คุณสามารถเลือกสไตล์เลือกรูปแบบและหากควรส่งออกเพลงที่ชอบ / ยกนิ้ว รายการผลลัพธ์จะถูกวางลงในคลิปบอร์ด รูปแบบที่มีall
, artist
, artistalbum
, ,artistsong
artistalbumsong
CSV จะส่งผลให้เป็นไฟล์ CSV และสามารถปล่อยออกไป (ค่าเริ่มต้นเป็นเท็จ) Likedonly สามารถถูกปล่อยออกมา (ค่าเริ่มต้นเป็นเท็จ) หรือตั้งค่าเป็นจริงและจะกรองเพลงทั้งหมดที่มีคะแนนมากกว่าหรือเท่ากับ 5 เช่น:
songsToText("all",true,false)
จะส่งออกเพลงทั้งหมดในรูปแบบ csv
songsToText("all",true,true)
จะส่งออกเฉพาะเพลงที่ชอบในรูปแบบ CSV
songsToText("artistsong",false,false)
จะส่งออกเพลงทั้งหมดเป็นข้อความ
จากนั้นคุณสามารถวางข้อมูลได้ทุกที่ที่คุณต้องการตัวอย่างเช่นhttp://www.ivyishere.org/หากคุณต้องการเพิ่มเพลงหรืออัลบั้มลงในบัญชี Spotify ของคุณ ในการทำให้ Ivy รู้จักอัลบั้มเต็มให้ใช้สไตล์ "artistalbum" สำหรับเพลงให้ใช้สไตล์ "artistong"
เกี่ยวกับตัวอย่าง:
สิ่งนี้ขึ้นอยู่กับคำตอบดั้งเดิมของ Michael Smith แต่ค่อนข้างแข็งแกร่ง ฉันได้ทำการปรับปรุงต่อไปนี้:
ทำงานบนเพลย์ลิสต์เช่นเดียวกับห้องสมุด คอลัมน์ใด ๆ ที่ขาดหายไปจะถูกละเว้นและคำสั่งจะถูกคิดออกดังนั้นควรทำงานกับเกือบทุกรายการเพลงใน Google Music
มันหยุดอย่างใดอย่างหนึ่งเมื่อมันมาถึงด้านล่าง (ตรวจจับตำแหน่งการเลื่อน) หรือหลังจากหมดเวลาที่ระบุ หมดเวลาใช้งานเพื่อป้องกันการวนซ้ำไม่สิ้นสุดในกรณีที่โค้ดตรวจจับการเลื่อนถูกปิดด้วยพิกเซลไม่กี่พิกเซล
มันเร็วกว่ามาก (ช่วงทุก 1 มิลลิวินาที) แต่รอถ้าข้อมูลยังไม่พร้อม (ขึ้นอยู่กับการหมดเวลาที่ระบุในปัจจุบันคือ 3 วินาที)
ทำการขจัดข้อมูลซ้ำซ้อนระหว่างการดำเนินการและบนเอาต์พุต
รวบรวมการจัดอันดับ: "ไม่ได้กำหนด" ไม่เคยถูกจัดอันดับ "0" ไม่ได้รับการจัดอันดับ (เช่นเมื่อถูกจัดอันดับ แต่ถูกลบออกแล้ว) "1" จะถูกเลื่อนลงและ "5" จะถูกยกระดับ (ชอบ)
นอกเหนือจากการปรับปรุงพื้นฐานแล้วยังจัดรูปแบบข้อความอย่างดีและคัดลอกไปยังคลิปบอร์ด คุณยังสามารถรับข้อมูลเป็น CSV ได้หากต้องการโดยเรียกใช้songsToText
ฟังก์ชันเป็นครั้งที่สอง
ทางเลือก:
หากคุณต้องการหลาม API ตรวจสอบAPI Google Music ทางการโครงการ
หากคุณมีเพลย์ลิสต์จำนวนมากและต้องการส่งออกทั้งหมดในครั้งเดียวลองผู้ส่งออกเพลย์ลิสต์gmusic-สคริปต์ที่สามารถทำได้ (Python ใช้โครงการ API ที่ไม่เป็นทางการ)