您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在 B 站收藏夹页提取本页所有视频标题 + 链接到浮动窗口,支持一键复制与导出 TXT
// ==UserScript== // @name B站收藏夹批量提取视频链接/Bilibili Favlist Extractor // @namespace ChatGPT // @version 0.3 // @author GPT // @description 在 B 站收藏夹页提取本页所有视频标题 + 链接到浮动窗口,支持一键复制与导出 TXT // @match https://space.bilibili.com/*/favlist* // @icon https://www.bilibili.com/favicon.ico // @grant GM_setClipboard // @grant GM_download // @run-at document-idle // @license MIT // ==/UserScript== (function () { 'use strict'; /** 计算当前页码(URL 参数 page= 或 pn=,默认 1) */ function getPageNumber() { const u = new URL(location.href); return parseInt(u.searchParams.get('page') || u.searchParams.get('pn') || '1', 10); } /** 导出为 TXT 文件 */ function exportTxt(content) { const now = new Date(); const y = now.getFullYear(); const m = String(now.getMonth() + 1).padStart(2, '0'); const d = String(now.getDate()).padStart(2, '0'); const name = `${y}${m}${d}_第${getPageNumber()}页.txt`; GM_download({ url: URL.createObjectURL(new Blob([content], { type: 'text/plain;charset=utf-8' })), name, saveAs: true }); } /** 收集当前 DOM 中已渲染的视频标题+链接 */ function collectVideos() { const anchors = [...document.querySelectorAll('a[href*="/video/"]')]; const map = new Map(); // 去重(以 BV 号为键) anchors.forEach(a => { const url = new URL(a.href, location.origin); const m = url.pathname.match(/\/video\/(BV\w+)/); if (!m) return; const bv = m[1]; const title = (a.innerText || '').trim(); map.set(bv, `${title} ${url.origin}${url.pathname}`); }); return [...map.values()]; } /** 创建浮窗 */ function createPanel() { const panel = document.createElement('div'); panel.id = 'fav-extractor-panel'; panel.innerHTML = ` <div id="fav-extractor-header"> <span>🎬 收藏夹视频列表</span> <button id="fav-extractor-refresh">刷新</button> <button id="fav-extractor-copy">复制全部</button> <button id="fav-extractor-export">导出TXT</button> <button id="fav-extractor-close">✕</button> </div> <textarea id="fav-extractor-output" readonly></textarea> <style> #fav-extractor-panel{ position:fixed; right:24px; bottom:24px; z-index:999999; width:360px; height:150px; max-height:90vh; background:#fff; border:1px solid #888; box-shadow:0 6px 12px rgba(0,0,0,.2); border-radius:8px; font-size:14px; display:flex; flex-direction:column; resize:both; overflow:hidden; } #fav-extractor-header{ display:flex; align-items:center; justify-content:space-between; background:#00AEEC; color:#fff; padding:6px 8px; cursor:move; user-select:none; } #fav-extractor-header button{ margin-left:6px; border:none; border-radius:4px; padding:2px 6px; background:#fff; color:#00AEEC; cursor:pointer; font-size:12px; } #fav-extractor-header button:hover{opacity:.8;} #fav-extractor-output{ flex:1; width:100%; border:none; padding:8px; box-sizing:border-box; font-family:monospace; white-space:pre; overflow:auto; } </style> `; document.body.appendChild(panel); /** 拖动支持 */ (function () { const header = panel.querySelector('#fav-extractor-header'); let sx, sy, sl, st, dragging = false; header.addEventListener('mousedown', e => { dragging = true; sx = e.clientX; sy = e.clientY; const r = panel.getBoundingClientRect(); sl = r.left; st = r.top; e.preventDefault(); }); document.addEventListener('mousemove', e => { if (!dragging) return; panel.style.left = sl + (e.clientX - sx) + 'px'; panel.style.top = st + (e.clientY - sy) + 'px'; panel.style.right = 'auto'; panel.style.bottom = 'auto'; }); document.addEventListener('mouseup', () => dragging = false); })(); /** 填充文本框 */ function fillTextarea() { const output = panel.querySelector('#fav-extractor-output'); output.value = collectVideos().join('\n'); } /** 按钮事件 */ panel.querySelector('#fav-extractor-refresh').onclick = fillTextarea; panel.querySelector('#fav-extractor-copy').onclick = () => { const txt = panel.querySelector('#fav-extractor-output').value; GM_setClipboard(txt, { type: 'text', mimetype: 'text/plain' }); alert(`已复制 ${txt.split('\\n').length} 条链接到剪贴板!`); }; panel.querySelector('#fav-extractor-export').onclick = () => { const txt = panel.querySelector('#fav-extractor-output').value; exportTxt(txt); }; panel.querySelector('#fav-extractor-close').onclick = () => panel.remove(); /** 初始填充 & 动态监听 */ fillTextarea(); const root = document.querySelector('.fav-video-list,.be-pager'); if (root) { new MutationObserver(fillTextarea).observe(root, { childList: true, subtree: true }); } } /* 等 DOM 就绪后创建浮窗 */ if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', createPanel); } else { createPanel(); } })();