Skip to content

Instantly share code, notes, and snippets.

@tzengyuxio
Last active July 15, 2025 10:19
Show Gist options
  • Save tzengyuxio/668251bdba67b9180ac3f96c39227208 to your computer and use it in GitHub Desktop.
Save tzengyuxio/668251bdba67b9180ac3f96c39227208 to your computer and use it in GitHub Desktop.
Extract Release Data from Ditto Music to JSON
/**
* 使用方式:
* 1. 開啟「Release Details」頁面。
* 2. 貼上此腳本於瀏覽器開發者工具 Console 執行。
* 3. 將會:
* - 擷取專輯資訊與歌曲清單
* - 加入 SmartLink 連結
* - 自動下載 JSON 檔案
* - 同時複製到剪貼簿(需視窗聚焦)
*/
(async () => {
const album = {};
// 🔍 專輯基本資料區塊
const meta = document.querySelector('.release-metadata');
if (meta) {
album.title = meta.querySelector('.release-title')?.innerText.trim() || '';
album.artist = meta.querySelector('.artist')?.innerText.trim() || '';
album.language = meta.querySelector('.language')?.innerText.trim() || '';
album.label = meta.querySelector('.record-label')?.innerText.trim() || '';
album.explicit = meta.querySelector('.explicit')?.innerText.trim() || '';
album.copyright = meta.querySelector('.copyright')?.innerText.trim() || '';
album.upc = meta.querySelector('.barcode')?.innerText.trim() || '';
const genres = meta.querySelectorAll('.genre');
album.primaryGenre = genres[0]?.innerText.trim() || '';
album.secondaryGenre = genres[1]?.innerText.trim() || '';
}
// 📅 發行與日期資訊
const status = document.querySelector('.release-status');
if (status) {
album.receivedDate = status.querySelector('.received-date')?.innerText.trim() || '';
album.releaseDate = status.querySelector('.release-date')?.innerText.trim() || '';
album.originalReleaseDate = status.querySelector('.original-release-date')?.innerText.trim() || '';
}
// 🔗 SmartLink
const smartLinkEl = document.querySelector('a.button.secondary[href*="ditto.fm"]');
if (smartLinkEl) {
album.smartLink = smartLinkEl.href;
}
// 🎵 歌曲資料
const tracks = Array.from(document.querySelectorAll('.release-track-item')).map(el => {
return {
title: el.querySelector('.track-title span')?.innerText.trim() || '',
artist: el.querySelector('.track-artist span:last-child')?.innerText.trim() || '',
duration: el.querySelector('.track-duration')?.innerText.trim() || '',
copyright: el.querySelector('.track-copyright')?.innerText.trim() || '',
year: el.querySelector('[data-header="year published"]')?.innerText.trim() || '',
isrc: el.querySelector('[data-header="isrc"]')?.innerText.trim() || '',
soundRecording: el.querySelector('[data-header="sound recording"] span')?.innerText.trim() || '',
audioUrl: el.querySelector('audio source')?.getAttribute('src') || ''
};
});
const result = { album, tracks };
const jsonStr = JSON.stringify(result, null, 2);
// ✅ 複製到剪貼簿
try {
await navigator.clipboard.writeText(jsonStr);
console.log('📋 已複製 JSON 到剪貼簿');
} catch (e) {
console.warn('⚠️ 無法複製剪貼簿(可能需手動點擊頁面使其聚焦)');
}
// 💾 自動下載 JSON
const blob = new Blob([jsonStr], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${album.title || 'release'}.json`;
a.click();
URL.revokeObjectURL(url);
console.log('✅ JSON 檔案已下載');
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment