您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
提取 Bilibili 视频页面中字幕的纯文本内容(不含时间戳),并一键复制,按钮显示在右下角。
// ==UserScript== // @name Bilibili 字幕文本提取器(按钮右下角) // @namespace https://greasyfork.org/users/d // @version 1.2 // @description 提取 Bilibili 视频页面中字幕的纯文本内容(不含时间戳),并一键复制,按钮显示在右下角。 // @author d // @match *://www.bilibili.com/video/* // @license MIT // @grant none // ==/UserScript== (function () { 'use strict'; function log(msg) { console.log('[字幕提取器] ' + msg); } window.addEventListener('load', function () { const btn = document.createElement('button'); btn.innerText = '提取字幕文本'; Object.assign(btn.style, { position: 'fixed', right: '20px', bottom: '20px', zIndex: '9999', padding: '8px 12px', backgroundColor: '#00a1d6', color: '#fff', border: 'none', borderRadius: '4px', cursor: 'pointer', boxShadow: '0 2px 6px rgba(0,0,0,0.3)' }); btn.onclick = async function () { log('开始提取流程...'); const panelOpened = !!document.querySelector('div._InteractWrapper_tepst_1'); const activeTab = document.querySelector('div._TabItem_krx6h_8._Active_krx6h_36'); const isSubtitleTabActive = activeTab && activeTab.innerText.includes('字幕列表'); // ✅ 如果面板已经打开且字幕标签已经激活,直接提取 if (panelOpened && isSubtitleTabActive) { log('面板和字幕标签已打开,直接提取字幕...'); extractAndCopySubtitles(); return; } // 否则,继续自动操作 const aiBtn = document.querySelector('.video-ai-assistant'); if (!aiBtn) { alert('未找到 AI 按钮,可能页面结构已变或不支持该功能。'); return; } log('点击 AI 按钮...'); aiBtn.click(); // 等待面板展开 try { await waitForElement('div._InteractWrapper_tepst_1', 5000); } catch (e) { alert('字幕面板加载超时,请重试。'); return; } log('等待字幕列表标签...'); const subtitleTab = await waitForSubtitleTab(); if (!subtitleTab) { alert('未找到“字幕列表”标签,可能结构变化。'); return; } subtitleTab.click(); log('已点击“字幕列表”标签,等待字幕加载...'); await delay(2000); // 等待字幕内容加载 extractAndCopySubtitles(); }; document.body.appendChild(btn); function extractAndCopySubtitles() { const textElements = document.querySelectorAll('._Text_1iu0q_64'); if (textElements.length === 0) { alert('未找到字幕内容,可能加载失败或结构变化。'); return; } const texts = Array.from(textElements) .map(el => el.innerText.trim()) .filter(text => text); const result = texts.join('\n'); console.log('[字幕提取器] 提取内容:\n' + result); navigator.clipboard.writeText(result).then(() => { alert(`✅ 成功提取并复制 ${texts.length} 条字幕文本!`); }).catch(() => { alert('❌ 复制失败,请手动查看控制台输出'); }); } // 等待某元素出现 function waitForElement(selector, timeout = 5000) { return new Promise((resolve, reject) => { const interval = 100; let elapsed = 0; const timer = setInterval(() => { const el = document.querySelector(selector); if (el) { clearInterval(timer); resolve(el); } elapsed += interval; if (elapsed >= timeout) { clearInterval(timer); reject(`等待 ${selector} 超时`); } }, interval); }); } // 等待“字幕列表”标签加载并返回该元素 function waitForSubtitleTab(timeout = 5000) { return new Promise((resolve) => { const interval = 100; let elapsed = 0; const timer = setInterval(() => { const tabs = document.querySelectorAll('div._TabItem_krx6h_8'); for (const tab of tabs) { if (tab.innerText.includes('字幕列表')) { clearInterval(timer); resolve(tab); return; } } elapsed += interval; if (elapsed >= timeout) { clearInterval(timer); resolve(null); } }, interval); }); } function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } }); })();