您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在Bilibili动态页(t.bilibili.com)右侧创建一个可收起的工具面板,使用图标按钮扫描并提取视频的标题和链接,支持按“标题链接”格式批量复制。
// ==UserScript== // @name Bilibili 动态视频提取器 // @namespace http://tampermonkey.net/ // @version 2.5 // @description 在Bilibili动态页(t.bilibili.com)右侧创建一个可收起的工具面板,使用图标按钮扫描并提取视频的标题和链接,支持按“标题链接”格式批量复制。 // @author Gemini Code Assist // @match https://t.bilibili.com/* // @icon https://www.bilibili.com/favicon.ico // @grant GM_addStyle // @grant GM_setClipboard // @license MIT // ==/UserScript== (function() { 'use strict'; // --- Icon Definitions --- const ICONS = { scan: `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>`, copy: `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>`, check: `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>` }; let extractedVideos = []; // 用于存储提取的视频信息 /** * 扫描当前页面的视频并更新UI */ function scanAndDisplayVideos() { const resultsContainer = document.getElementById('bili-feed-extractor-results'); const statusElement = document.getElementById('bili-feed-extractor-status'); const copyButton = document.getElementById('bili-feed-copy-button'); if (!resultsContainer || !statusElement) return; // 清空上一次的结果 resultsContainer.innerHTML = ''; extractedVideos = []; const seenLinks = new Set(); // 用于链接去重 // B站动态页视频卡的CSS选择器,改为选择包含链接的<a>标签 const videoCards = document.querySelectorAll('a.bili-dyn-card-video'); videoCards.forEach(card => { // 'card' is now the <a> element const titleElement = card.querySelector('.bili-dyn-card-video__title'); // 如果没有找到标题元素,则跳过 if (!titleElement) { return; } const title = titleElement.innerText.trim(); let link = card.href; // 健壮性检查。如果获取不到有效的链接,则跳过此卡片。 if (typeof link !== 'string' || !link) { return; // 相当于 forEach 循环中的 'continue' } // 清理链接,去掉跟踪参数 link = link.split('?')[0]; // 去重 if (title && !seenLinks.has(link)) { seenLinks.add(link); // Bug fix: was adding object instead of link string extractedVideos.push({ title, link }); // 根据您的要求,此处不再将视频信息添加到面板的列表中。 // 数据仍然会收集,以便“一键复制”功能可以正常工作。 } }); // 更新状态 if (extractedVideos.length > 0) { statusElement.innerText = `扫描到 ${extractedVideos.length} 个视频。`; copyButton.disabled = false; copyButton.style.opacity = '1'; } else { statusElement.innerText = '未扫描到视频。请尝试向下滚动页面再试。'; copyButton.disabled = true; copyButton.style.opacity = '0.5'; } } /** * 复制所有结果到剪贴板 */ function copyAllResults() { if (extractedVideos.length === 0) return; // 按照 "标题链接" 格式拼接,每个视频占一行 const textToCopy = extractedVideos.map(v => `${v.title} ${v.link}`).join('\n'); GM_setClipboard(textToCopy, 'text'); const copyButton = document.getElementById('bili-feed-copy-button'); copyButton.innerHTML = ICONS.check; copyButton.title = '已复制!'; copyButton.disabled = true; // 暂时禁用以防重复点击 setTimeout(() => { copyButton.innerHTML = ICONS.copy; copyButton.title = '一键复制所有信息'; copyButton.disabled = false; }, 2000); } /** * 创建并注入UI面板 */ function createPanel() { const container = document.createElement('div'); container.id = 'bili-feed-extractor-container'; container.innerHTML = ` <div id="bili-feed-extractor-header"> <button id="bili-feed-toggle-button" title="收起/展开面板">收起</button> </div> <div id="bili-feed-extractor-body"> <div class="button-group"> <button id="bili-feed-scan-button" title="扫描视频">${ICONS.scan}</button> <button id="bili-feed-copy-button" title="一键复制所有信息" disabled>${ICONS.copy}</button> </div> <p id="bili-feed-extractor-status">尚未扫描</p> <hr> <div id="bili-feed-extractor-results"></div> </div> `; document.body.appendChild(container); addStyles(); // 添加样式 // 绑定事件 document.getElementById('bili-feed-scan-button').addEventListener('click', scanAndDisplayVideos); document.getElementById('bili-feed-copy-button').addEventListener('click', copyAllResults); const toggleButton = document.getElementById('bili-feed-toggle-button'); const body = document.getElementById('bili-feed-extractor-body'); toggleButton.addEventListener('click', () => { const isCollapsed = body.style.display === 'none'; if (isCollapsed) { body.style.display = 'block'; toggleButton.innerText = '收起'; } else { body.style.display = 'none'; toggleButton.innerText = '展开'; } }); // 初始时禁用复制按钮 const copyButton = document.getElementById('bili-feed-copy-button'); copyButton.style.opacity = '0.5'; } /** * 添加UI样式 */ function addStyles() { GM_addStyle(` #bili-feed-extractor-container { position: fixed; top: 100px; right: 20px; width: 50px; max-height: 70vh; background-color: #ffffff; border: 1px solid #e3e5e7; border-radius: 8px; padding: 16px; z-index: 9999; font-size: 14px; color: #18191c; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column; transition: max-height 0.3s ease-in-out; } #bili-feed-extractor-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; } #bili-feed-extractor-container h3 { margin: 0; font-size: 16px; color: #fb7299; } #bili-feed-toggle-button { background: none; border: 1px solid #e3e5e7; color: #61666d; padding: 2px 8px; font-size: 12px; border-radius: 4px; cursor: pointer; } #bili-feed-toggle-button:hover { background-color: #f1f2f3; } #bili-feed-extractor-container .button-group { display: flex; gap: 10px; margin-bottom: 10px; } #bili-feed-extractor-container .button-group button { width: 42px; height: 34px; display: flex; align-items: center; justify-content: center; background-color: #00a1d6; color: white; border: none; padding: 0; border-radius: 5px; cursor: pointer; transition: background-color 0.2s, opacity 0.2s; } #bili-feed-extractor-container button:hover:not(:disabled) { background-color: #00b5e5; } #bili-feed-extractor-container button:disabled { cursor: not-allowed; } #bili-feed-extractor-container #bili-feed-extractor-status { text-align: center; color: #61666d; font-size: 12px; margin: 0; } #bili-feed-extractor-container hr { border: none; border-top: 1px solid #e3e5e7; margin: 12px 0; } #bili-feed-extractor-results { overflow-y: auto; flex-grow: 1; } #bili-feed-extractor-results .video-item { border-bottom: 1px solid #f1f2f3; padding-bottom: 10px; margin-bottom: 10px; } #bili-feed-extractor-results .video-item:last-child { border-bottom: none; margin-bottom: 0; } #bili-feed-extractor-results p { margin: 0 0 5px 0; word-wrap: break-word; line-height: 1.5; } #bili-feed-extractor-results strong { color: #61666d; } #bili-feed-extractor-results a { color: #00a1d6; text-decoration: none; } #bili-feed-extractor-results a:hover { text-decoration: underline; } `); } // 页面加载后直接创建面板 createPanel(); })();