公司动态
B站视频字幕提取全攻略:手动与Python自动化方法详解
1. 项目概述为什么我们需要提取B站字幕做视频剪辑、内容分析或者外语学习的朋友可能都遇到过这样的场景看到一个B站哔哩哔哩视频的文案或字幕特别精彩想把它整理成文字稿或者想为没有字幕的视频手动添加字幕但对着视频逐字听写效率太低又或者想分析某个UP主的文案风格和关键词频率。这时候如果能直接把视频里的字幕“扒”下来无疑能省下大量时间和精力。B站作为一个以高质量PUGV专业用户生成视频内容为核心的平台其字幕系统其实相当完善。大部分UP主为了观看体验都会上传或生成字幕。这些字幕数据就藏在网页背后以一种结构化的格式通常是JSON存在。我们所要做的就是找到它、解析它并转换成我们需要的格式如SRT、TXT。这个过程听起来有点技术含量但实际操作起来只要你跟着步骤走十分钟内就能搞定完全不需要高深的编程知识。我最初研究这个方法是因为需要批量处理一些知识区视频做文本分析手动下载效率太低。在尝试了多种方案后我总结出了一套稳定、有效且对新手友好的流程。它不依赖任何需要特殊网络环境的工具或网站核心只用到一个大家都能正常访问的浏览器和几行简单的Python代码甚至不用代码也有办法。下面我就把这套“亲测有效”的方法从原理到实操再到你可能遇到的各种坑毫无保留地分享给你。2. 核心原理与数据来源拆解在动手之前我们先搞清楚B站字幕是怎么来的以及我们会从哪里找到它。理解这一点能让你在后续操作中更有方向感遇到问题也知道该往哪里排查。2.1 B站字幕的两种类型与存放位置B站视频的字幕主要来源于两个途径UP主上传/AI生成的字幕CC字幕这是最常见的一种。UP主可以在后台上传SRT、ASS等格式的字幕文件或者直接使用B站提供的AI语音识别功能生成字幕。这类字幕的特点是支持多语言轨道切换你在播放器右下角看到的那个“字幕”按钮点开能选中文、英文甚至关闭的就是它。它的数据是以JSON格式存储的。硬编码字幕硬字幕这部分字幕是UP主在剪辑视频时直接渲染到视频画面上的。它已经是视频图像的一部分就像电影里的对白字幕一样。这种方法无法通过技术手段直接提取出纯净的文本只能借助OCR光学字符识别软件从视频帧中识别准确率和效率都较低不在我们本次讨论的“有效”方法范围内。我们方法的核心目标就是第一种——CC字幕。那么这个JSON数据藏在哪里呢答案就在每个B站视频页面的网络请求中。当你播放一个带有CC字幕的视频时浏览器除了加载视频流还会向B站的服务器请求一个字幕文件。这个请求会被记录在浏览器开发者工具的“Network”网络面板里。我们的任务就是拦截这个请求拿到它的返回数据。2.2 关键技术点JSON与SRT格式这里会涉及两个关键的技术名词别担心我用人话解释一下JSON你可以把它理解为一个结构非常清晰的“数据快递箱”。B站服务器把字幕文本、每条字幕的开始时间、结束时间、样式等信息分门别类地打包在这个“箱子”里。它非常适合程序读取和处理但人类直接看会觉得有点乱。SRT这是最通用、最简单的字幕文件格式。它按顺序排列每一段字幕包含序号、时间轴开始 -- 结束和文本内容。几乎所有视频编辑软件如剪映、Premiere和播放器都支持SRT格式。我们的工作流程本质上就是一个**“数据搬运和转码”**的过程从网页的“网络请求”中捕获那个装着字幕的JSON“快递箱”然后拆开它按照SRT的格式要求把里面的时间码和文本重新组装好保存成一个新的.srt文件。注意这个方法成功的前提是你观看的视频必须拥有CC字幕即播放器有“字幕”开关且可选。你可以先手动点开视频的字幕功能确认一下。3. 方法一手动抓取与转换无需安装Python如果你只是偶尔需要提取一两个字幕或者对运行代码有顾虑那么这个纯手动的方法最适合你。它只需要浏览器整个过程像寻宝一样有趣。3.1 详细操作步骤3.1.1 打开开发者工具在Chrome、Edge或Firefox浏览器中打开你想要提取字幕的B站视频页面。按下键盘上的F12键或者右键点击页面选择“检查”/“审查元素”。这时浏览器侧面或底部会弹出一个工具窗口。在这个工具窗口顶部找到并点击“Network”网络标签页。同时为了更精确地过滤我们点击“Fetch/XHR”这个过滤器。这个过滤器只会显示网页通过脚本发起的特定数据请求能帮我们快速找到字幕数据。3.1.2 定位字幕请求确保开发者工具是打开状态然后刷新一下视频页面或者直接点击播放视频。观察“Network”面板下的请求列表会刷出很多条目。我们需要从中找到包含字幕数据的那个。在列表上方的筛选栏里输入关键词“subtitle”或“caption”。列表会立刻过滤剩下的请求通常就很少了。仔细查看这些请求的“Name”或“URL”列寻找包含api.bilibili.com/x/player/v2或api.bilibili.com/x/v2/dm/subtitle等字样的链接。点击这个请求。3.1.3 获取并解析JSON数据点击找到的请求后右侧会显示该请求的详细信息。切换到“Preview”预览或“Response”响应标签页。如果这个请求是正确的你会看到一个结构清晰的JSON数据。它通常有一个data对象里面包含subtitle或subtitles字段。展开后你会看到一个list里面就是所有字幕条目的数组。每一条字幕通常包含以下关键信息from: 字幕开始时间单位秒to: 字幕结束时间单位秒content: 字幕文本内容可能还有location位置等信息但我们主要需要前三个。现在你需要手动复制这个JSON数据。在“Preview”视图下你可以直接展开整个结构然后右键点击最外层的花括号{...}选择“Copy object”。或者切换到“Response”标签页复制里面所有的原始文本。3.1.4 使用在线工具转换为SRT拿到JSON文本后我们需要一个“翻译官”把它变成SRT格式。打开一个新的浏览器标签页访问任何一个JSON转SRT在线工具。你可以搜索“json to srt online”找到很多。将刚才复制的JSON文本粘贴到在线工具的输入框里。点击“转换”或“Generate”按钮。工具会自动解析JSON并生成对应的SRT格式文本。你可以在输出框看到结果通常格式如下1 00:00:01,000 -- 00:00:04,500 欢迎来到我的频道今天我们来聊聊如何提取字幕。 2 00:00:04,600 -- 00:00:07,800 这个方法非常简单只需要三步。最后将转换好的SRT文本复制下来粘贴到一个新建的文本文件中并将文件后缀名从.txt改为.srt。这个文件就可以在剪辑软件或播放器中使用了。3.2 手动方法的优缺点与注意事项优点零安装不需要在电脑上安装任何额外软件。直观可控每一步你都能看到原始数据对理解整个过程有帮助。临时需求首选处理单个视频最快。缺点效率低每个视频都需要重复打开开发者工具、查找、复制、转换的流程。依赖网络需要访问在线的JSON转换工具。容易出错手动复制大量JSON文本时可能出错且在线工具质量参差不齐。实操心得在“Network”面板里如果找不到明显的subtitle请求可以尝试在筛选栏输入?cid或aid这些是B站视频的参数有时字幕接口会附带这些ID。复制JSON时确保复制的是完整对象。最稳妥的方法是去“Response”标签页复制全部内容。有些在线转换工具对B站原始的JSON格式支持不好可能需要你手动调整JSON结构。如果转换失败可以多换几个工具试试。4. 方法二使用Python脚本实现自动化提取对于需要批量提取字幕或者希望将流程固定下来、一键运行的朋友Python脚本是更强大的选择。写好的脚本就像一个专属工具下次用的时候只需要改一下视频链接就行。4.1 环境准备与核心库你不需要是Python高手只要跟着步骤把环境搭起来就行。安装Python如果你电脑上没有Python去官网python.org下载安装。记得在安装时勾选“Add Python to PATH”这样才可以在命令行里直接使用。安装后打开命令行CMD或PowerShell输入python --version能显示版本号就说明成功了。安装必要库我们主要需要两个库requests用于网络请求json用于解析数据这个是Python自带的。在命令行里输入以下命令安装pip install requests如果下载慢可以使用国内镜像源例如pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple4.2 脚本编写思路与代码逐行解析脚本的核心逻辑其实就是把我们手动操作的步骤用代码描述出来获取视频信息 - 构造字幕请求 - 下载JSON - 转换为SRT。下面我写一个功能完整且带有详细注释的脚本。import requests import json import re import sys def get_bvid_from_url(url): 从B站视频链接中提取 BV号。 支持多种格式的链接。 # 匹配 BV 号的正则表达式 bvid_pattern r(BV[0-9A-Za-z]{10}) match re.search(bvid_pattern, url) if match: return match.group(1) else: print(错误无法从URL中提取BV号。请检查链接格式。) print(支持的链接格式示例) print( - https://www.bilibili.com/video/BV1xx411c7mD/) print( - https://b23.tv/BV1xx411c7mD) return None def fetch_subtitle_json(bvid): 根据 BV 号获取视频的字幕 JSON 数据。 # 步骤1: 获取视频的基本信息其中包含字幕接口所需的 cid video_info_url fhttps://api.bilibili.com/x/web-interface/view?bvid{bvid} headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 } try: print(f正在获取视频信息: {bvid}) resp requests.get(video_info_url, headersheaders, timeout10) resp.raise_for_status() # 检查请求是否成功 video_info resp.json() if video_info[code] ! 0: print(f获取视频信息失败: {video_info.get(message)}) return None cid video_info[data][cid] video_title video_info[data][title] print(f视频标题: {video_title}) print(f获取到 CID: {cid}) except requests.exceptions.RequestException as e: print(f网络请求失败: {e}) return None except (KeyError, json.JSONDecodeError) as e: print(f解析视频信息失败: {e}) return None # 步骤2: 使用 cid 获取字幕列表 subtitle_list_url fhttps://api.bilibili.com/x/player/v2?bvid{bvid}cid{cid} try: print(正在获取字幕列表...) resp requests.get(subtitle_list_url, headersheaders, timeout10) resp.raise_for_status() subtitle_list_info resp.json() if subtitle_list_info[code] ! 0: print(f获取字幕列表失败: {subtitle_list_info.get(message)}) return None subtitles subtitle_list_info[data].get(subtitle, {}).get(subtitles, []) if not subtitles: print(该视频没有可用的CC字幕。) return None print(f找到 {len(subtitles)} 个字幕轨道。) for idx, sub in enumerate(subtitles): lang sub.get(lan_doc, 未知语言) print(f [{idx}] {lang}) # 默认选择第一个字幕轨道通常是中文 choice 0 selected_sub subtitles[choice] subtitle_url selected_sub[subtitle_url] print(f选择字幕轨道: {selected_sub.get(lan_doc)}) # 步骤3: 下载字幕 JSON 数据 # 注意字幕 URL 可能是相对路径需要补全为完整 HTTPS 链接 if subtitle_url.startswith(//): subtitle_url https: subtitle_url elif not subtitle_url.startswith(http): subtitle_url https: subtitle_url print(f正在下载字幕数据...) resp requests.get(subtitle_url, headersheaders, timeout10) resp.raise_for_status() subtitle_json resp.json() return { title: video_title, data: subtitle_json, language: selected_sub.get(lan_doc, ) } except requests.exceptions.RequestException as e: print(f获取字幕数据失败: {e}) return None except (KeyError, json.JSONDecodeError, IndexError) as e: print(f解析字幕数据失败: {e}) return None def json_to_srt(subtitle_data, video_title): 将 B 站字幕 JSON 数据转换为 SRT 格式字符串。 if subtitle_data[code] ! 0: return None body subtitle_data[body] srt_lines [] for i, item in enumerate(body, start1): # 提取开始和结束时间单位秒 start_time item[from] end_time item[to] # 将秒转换为 SRT 格式的时间码HH:MM:SS,mmm def sec_to_srt_time(t): hours int(t // 3600) minutes int((t % 3600) // 60) seconds int(t % 60) milliseconds int((t - int(t)) * 1000) return f{hours:02d}:{minutes:02d}:{seconds:02d},{milliseconds:03d} srt_start sec_to_srt_time(start_time) srt_end sec_to_srt_time(end_time) # 字幕内容 content item[content] # 构建 SRT 块 srt_lines.append(str(i)) srt_lines.append(f{srt_start} -- {srt_end}) srt_lines.append(content) srt_lines.append() # 空行分隔 return \n.join(srt_lines) def save_srt_file(srt_content, video_title, language): 将 SRT 内容保存到文件。 # 清理文件名中的非法字符 safe_title re.sub(r[:/\\|?*], _, video_title) if language: filename f{safe_title}_{language}.srt else: filename f{safe_title}.srt with open(filename, w, encodingutf-8) as f: f.write(srt_content) print(f字幕文件已保存为: {filename}) return filename def main(): print( B站字幕提取工具 ) # 获取用户输入的视频链接 if len(sys.argv) 1: url sys.argv[1] else: url input(请输入B站视频链接: ).strip() # 1. 提取BV号 bvid get_bvid_from_url(url) if not bvid: return # 2. 获取字幕JSON数据 result fetch_subtitle_json(bvid) if not result: print(字幕提取失败请检查视频是否有CC字幕或网络连接。) return # 3. 转换为SRT格式 srt_content json_to_srt(result[data], result[title]) if not srt_content: print(转换SRT格式失败。) return # 4. 保存文件 save_srt_file(srt_content, result[title], result[language]) print(操作完成) if __name__ __main__: main()4.3 如何使用这个脚本保存脚本将上面的代码完整复制保存到一个文本文件中将文件后缀名改为.py例如bilibili_subtitle_downloader.py。运行脚本打开命令行CMD或终端导航到脚本所在的目录。例如如果你的脚本在桌面可以输入cd Desktop运行脚本并附上视频链接python bilibili_subtitle_downloader.py https://www.bilibili.com/video/BV1GJ411x7h7/或者直接运行脚本然后根据提示输入链接python bilibili_subtitle_downloader.py获取结果脚本运行成功后会在当前目录下生成一个以视频标题命名的.srt文件。4.4 Python方法的优缺点优点高效批量稍加修改如读取文件中的链接列表即可实现批量自动下载。稳定可靠直接调用B站官方API成功率极高。功能可扩展你可以轻松修改脚本比如同时下载中英文字幕、调整时间轴、过滤广告词等。离线工作所有转换在本地完成不依赖任何在线服务。缺点需要基础环境需要安装Python和库对纯小白有轻微门槛。链接格式依赖脚本需要从链接中正确提取BV号如果B站未来更改链接规则可能需要更新正则表达式。实操心得脚本中的User-Agent头很重要它让请求看起来像来自一个真实的浏览器避免被服务器拒绝。如果视频有多个字幕轨道如中、英文脚本默认选择第一个索引0。你可以修改choice变量的值来选择其他轨道或者增加一个交互让用户选择。保存文件名时清理非法字符如\ / : * ? |是必要的否则系统会拒绝创建文件。5. 常见问题与排查技巧实录在实际操作中你可能会遇到一些“坑”。下面是我在多次使用中总结出来的常见问题及解决方法希望能帮你快速排雷。5.1 通用问题排查表问题现象可能原因解决方案手动法Network里找不到subtitle请求1. 视频没有CC字幕。2. 未刷新页面或开始播放。3. 过滤器设置不对。1. 确认播放器有“字幕”按钮且能开关。2. 刷新页面或开始播放视频同时监控Network。3. 尝试清除筛选词或筛选“json”、“cid”。手动法复制JSON后在线转换失败1. 复制的JSON不完整或格式错误。2. 在线工具不支持B站原始格式。1. 确保在“Response”标签页复制全部原始文本。2. 换一个在线转换工具或尝试用Python脚本。Python法运行脚本报错ModuleNotFoundError未安装requests库。在命令行执行pip install requests。Python法脚本运行后提示“该视频没有可用的CC字幕”1. 视频确实无CC字幕。2. 视频是合集或分PCID获取有误。3. API接口暂时性故障。1. 网页端确认字幕是否存在。2. 确保链接是单个视频的播放页而非合集列表页。3. 稍后再试。Python法保存的文件名乱码或包含非法字符视频标题含有系统不允许作为文件名的字符。脚本中已包含清理非法字符的逻辑。如果仍有问题可手动修改safe_title的生成规则。最终SRT文件时间轴错乱时间戳转换计算错误或原始JSON中的时间单位不是秒。检查sec_to_srt_time函数。B站API返回的时间单位通常是秒确认无误。可对比手动法获取的原始JSON数据中的from值。提取的字幕文本不完整或有大量“...”UP主上传的字幕文件本身如此或AI识别后未做修正。这是源数据问题技术手段无法解决。只能手动校对和补全。5.2 进阶技巧与注意事项处理大会员或付费视频本方法基于公开可访问的API。如果视频是大会员专享或需要付费且字幕也属于权益的一部分那么非会员账户通过API可能无法获取到字幕数据。这是正常情况。批量处理思路如果你有大量视频需要处理可以创建一个urls.txt文件每行放一个视频链接。然后修改Python脚本的main函数读取这个文件用循环依次处理每个链接并做好错误处理避免一个失败导致全部中断。字幕翻译有时你会看到字幕轨道里有“中文自动生成”和“中文简体”两种。前者是AI原始识别结果可能有错误后者是UP主校对后上传的质量更高。脚本默认选择列表第一个你可以根据lan_doc字段选择更优的轨道。网络波动在脚本中我增加了timeout10参数和异常捕获 (try...except)。如果网络不好导致请求超时脚本会报错而非卡死这是一个良好的编程习惯。尊重版权与UP主劳动提取字幕主要用于个人学习、研究或剪辑自己的二创作品需符合平台规范。请勿将提取的字幕用于商业用途或侵犯原作者权益的行为。6. 方案对比与延伸应用场景6.1 手动法与Python脚本法对比特性手动法浏览器在线工具Python脚本法上手难度极低无需编程中等需配置Python环境处理速度慢单个视频需数分钟快单个视频秒级完成批量能力几乎不可能非常容易写个循环即可稳定性依赖在线工具可用性高直接对接API可定制性无极高可按需修改脚本适用场景偶尔提取一两个视频定期、批量处理字幕需求选择建议如果你是电脑小白且需求频率很低一个月不到一两次手动法完全够用。但如果你是一个内容创作者、数据分析者或外语学习者需要频繁处理字幕那么花半小时配置一下Python环境一劳永逸地获得一个自动化工具绝对是笔划算的投资。6.2 提取后的字幕能做什么拿到SRT字幕文件后它的用处远超你的想象视频剪辑与二创直接导入剪映、Premiere、Final Cut Pro等软件作为字幕轨道或文案参考极大提升剪辑效率。内容分析与复盘将字幕文本导入文档分析UP主的文案结构、高频词汇、口语习惯学习他们的内容创作技巧。外语学习提取双语字幕制作成学习卡片或者对比中英文字幕学习地道表达。生成视频笔记结合AI工具如ChatGPT将字幕文本总结成视频的重点摘要、思维导图或问答对。为无声视频配字幕如果你下载了一个没有字幕的视频可以找到同主题其他视频的字幕经修改后使用。本地存档与搜索将喜欢的视频字幕保存下来建立个人知识库方便日后全文检索。我个人最常用的场景是1和2。作为业余视频制作者看到优秀的文案结构我会把字幕提出来分析它的开场钩子、节奏划分、结尾总结是怎么做的。而在做技术分享视频前我也会先用这个方法把自己的口播稿字幕提出来审阅修改比反复听视频快得多。最后工具虽好但核心还是内容本身。这个方法帮你解放了生产力让你能把更多时间花在更有价值的创作、学习和思考上。希望这篇超详细的指南能切实地帮到你。如果在操作中遇到任何脚本报错记得把完整的错误信息贴出来社区里有很多热心朋友可以一起帮你分析。