Last active
September 25, 2024 17:16
-
-
Save Rynaro/eb3db0e10dbed1bb0009b9ac0a975c32 to your computer and use it in GitHub Desktop.
Spotify Playlist Track + Artist Scraper
This file contains 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
// Script to extract track names and artists from your current playlist page and export them in CSV format. | |
// This script is intended for personal use to manage playlists efficiently. | |
// Any misuse of this script is not the responsibility of the author. | |
(async function() { | |
// Map to store tracks using `aria-rowindex` as the key | |
const tracksMap = new Map(); | |
// Adjust these parameters if needed | |
const scrollDelay = 800; // Delay between scrolls in milliseconds | |
const scrollAmount = 300; // Scroll increment in pixels | |
const maxScrollAttempts = 1000; // Maximum number of scroll attempts to prevent infinite loops | |
// Target the identified scrollable container | |
const scrollableElement = document.querySelector('div.main-view-container [data-overlayscrollbars-viewport]'); | |
if (!scrollableElement) { | |
console.error('Scrollable container not found.'); | |
return; | |
} | |
// Helper function to pause execution | |
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); | |
// Scroll and collect tracks | |
for (let attempt = 0; attempt < maxScrollAttempts; attempt++) { | |
// Scroll down by the specified amount | |
scrollableElement.scrollBy(0, scrollAmount); | |
// Wait for the DOM to update | |
await sleep(scrollDelay); | |
// Extract tracks currently in the DOM | |
const trackRows = scrollableElement.querySelectorAll('div[role="row"]'); | |
trackRows.forEach(row => { | |
row.querySelector('[data-testid="tracklist-row"]'); | |
const ariaRowIndex = row.getAttribute('aria-rowindex'); | |
if (ariaRowIndex && !tracksMap.has(ariaRowIndex)) { | |
// Extract the song title | |
const songTitleElement = row.querySelector('a[data-testid="internal-track-link"] div[data-encore-id="text"]'); | |
const songTitle = songTitleElement ? songTitleElement.textContent.trim() : 'Unknown Title'; | |
// Extract the artist names | |
const artistElements = row.querySelectorAll('span.encore-text-body-small a'); | |
const artistNames = artistElements.length > 0 | |
? Array.from(artistElements).map(artist => artist.textContent.trim()).join(', ') | |
: 'Unknown Artist'; | |
tracksMap.set(ariaRowIndex, { title: songTitle, artist: artistNames }); | |
} | |
}); | |
// Log progress | |
console.log(`Collected ${tracksMap.size} tracks so far...`); | |
// Check if all tracks are collected (stop scrolling) | |
// Assuming we know the total track count, break if collected all | |
const totalTracks = 336; // Replace with actual total if available | |
if (tracksMap.size >= totalTracks) { | |
console.log('All tracks have been collected.'); | |
break; | |
} | |
} | |
// Convert the collected data to an array and sort by track index | |
const tracksArray = Array.from(tracksMap.entries()) | |
.sort((a, b) => a[0] - b[0]) // Sort by track index | |
.map(entry => entry[1]); // Extract the track details | |
// Output the collected tracks | |
console.table(tracksArray); | |
// Optional: Export the data to a CSV file with UTF-8 BOM encoding | |
const exportToCSV = true; // Set to true if you want to export the data | |
if (exportToCSV) { | |
// Add BOM (Byte Order Mark) for UTF-8 encoding to handle special characters | |
const BOM = '\uFEFF'; | |
let csvContent = 'Index,Title,Artist\n' + Array.from(tracksMap.entries()) | |
.sort((a, b) => a[0] - b[0]) | |
.map(entry => `${entry[0]},"${entry[1].title.replace(/"/g, '""')}","${entry[1].artist.replace(/"/g, '""')}"`) | |
.join('\n'); | |
// Create Blob with UTF-8 BOM | |
let blob = new Blob([BOM + csvContent], { type: 'text/csv;charset=utf-8;' }); | |
let url = URL.createObjectURL(blob); | |
let link = document.createElement('a'); | |
link.setAttribute('href', url); | |
link.setAttribute('download', 'spotify_playlist.csv'); | |
document.body.appendChild(link); | |
link.click(); | |
document.body.removeChild(link); | |
console.log('CSV file has been downloaded.'); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment