Экспорт понравившихся треков YouTube Music | Cododel [RU]
CODODELDEV
EN / RU
Back to Deck
[snippet]

Экспорт понравившихся треков YouTube Music

ИСХОДНИК YouTube Music
ВЕРСИЯ 1.0.0
АВТОР Cododel

Одноразовый скрипт для консоли браузера на странице плейлиста Понравившаяся музыка в YouTube Music. Он прокручивает список, собирает видимые пары «исполнитель — название» и после завершения показывает кнопки копирования и скачивания .txt.

Как использовать

  1. Откройте плейлист Понравившаяся музыка на music.youtube.com и дождитесь появления первых треков.
  2. Откройте консоль разработчика браузера, вставьте весь код ниже и запустите его.
  3. Оставьте вкладку открытой, пока скрипт прокручивает список. После завершения скопируйте или скачайте результат кнопкой на экране.
  4. Чтобы остановить сбор раньше, выполните в консоли window.__stopScraper = true. Уже собранные треки сохранятся.

В результате каждая строка имеет вид Исполнитель — Название. Одинаковые пары удаляются. Скрипт останавливается примерно через десять секунд без новых уникальных пар, поэтому при медленной загрузке плейлиста проверьте число собранных треков. Он читает текущую разметку страницы; изменения интерфейса YouTube Music могут повлиять на результат.

Исходный код

// YouTube Music Liked Songs Scraper & Exporter
;(async () => {
window.__stopScraper = false
const tracks = new Set()
let lastSize = 0
let stagnantTurns = 0
const maxStagnant = 12
console.log('🚀 Scraping started. Please wait while the playlist scrolls to the end...')
console.log('ℹ️ To stop early, run: window.__stopScraper = true;')
while (stagnantTurns < maxStagnant && !window.__stopScraper) {
// Collect tracks from currently mounted DOM nodes in the virtual list
document.querySelectorAll('ytmusic-responsive-list-item-renderer').forEach((row) => {
const title = row.querySelector('.title')?.innerText?.trim()
const artist = row.querySelector('.secondary-flex-columns')?.innerText?.split('•')[0]?.trim()
if (title && artist) tracks.add(`${artist} — ${title}`)
})
if (tracks.size === lastSize) {
stagnantTurns++
} else {
stagnantTurns = 0
lastSize = tracks.size
console.log(`Unique tracks collected: ${tracks.size}`)
}
// Scroll to the last mounted element to trigger the next batch
const items = document.querySelectorAll('ytmusic-responsive-list-item-renderer')
if (items.length) {
items[items.length - 1].scrollIntoView({ behavior: 'instant', block: 'end' })
}
window.scrollTo(0, document.documentElement.scrollHeight)
await new Promise((res) => setTimeout(res, 850))
}
const result = Array.from(tracks).join('\n')
window.__collectedTracks = result
// DevTools provides copy() in some browsers
try {
copy(result)
} catch (e) {}
document.getElementById('ytm-scraper-result')?.remove()
const banner = document.createElement('div')
banner.id = 'ytm-scraper-result'
banner.style.cssText = `
position: fixed; top: 20px; right: 20px; z-index: 999999;
background: #181818; color: #fff; border: 2px solid #ff0000;
border-radius: 12px; padding: 16px 20px; font-family: sans-serif;
box-shadow: 0 10px 30px rgba(0,0,0,0.8); display: flex; flex-direction: column; gap: 10px;
`
banner.innerHTML = `
<div style="font-size: 15px; font-weight: bold; color: #4ade80;">
✅ Scraping complete! Found: ${tracks.size} tracks
</div>
<div style="display: flex; gap: 8px;">
<button id="ytm-copy-btn" style="
background: #ff0000; color: #fff; border: none; border-radius: 6px;
padding: 8px 14px; font-weight: bold; cursor: pointer;">
📋 Copy to clipboard
</button>
<button id="ytm-dl-btn" style="
background: #333; color: #fff; border: 1px solid #555; border-radius: 6px;
padding: 8px 14px; cursor: pointer;">
💾 Download .txt
</button>
<button id="ytm-close-btn" style="
background: transparent; color: #888; border: none; padding: 8px; cursor: pointer;">
✕
</button>
</div>
`
document.body.appendChild(banner)
document.getElementById('ytm-copy-btn').onclick = async () => {
const btn = document.getElementById('ytm-copy-btn')
try {
await navigator.clipboard.writeText(window.__collectedTracks)
btn.innerText = 'Copied! ✓'
btn.style.background = '#16a34a'
} catch (error) {
btn.innerText = 'Copy failed — use Download .txt'
console.error('Clipboard copy failed:', error)
}
}
document.getElementById('ytm-dl-btn').onclick = () => {
const blob = new Blob([window.__collectedTracks], { type: 'text/plain;charset=utf-8' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = `liked_tracks_${tracks.size}.txt`
a.click()
setTimeout(() => URL.revokeObjectURL(url), 1000)
}
document.getElementById('ytm-close-btn').onclick = () => banner.remove()
console.log(
`🎉 Done! Collected ${tracks.size} tracks. Use the on-screen buttons to copy or download.`,
)
})()
[ ▲ 0 ]