B站收藏夹一键导出:Python脚本调用API生成Excel表格
发布时间:2026/10/2 18:46:41来源:尧图网络
B站收藏夹这东西越攒越乱越乱越不敢动。我自己的账号大概收藏了两千多条视频前阵子想整理发现靠网页端一条条复制链接根本不现实翻了三页就放弃了。后来仔细研究了一轮把B站收藏夹快速导出的方案彻底跑通了从API原理到最终拿到一份整理好的Excel表格全程可复现。这篇文章就把完整操作和踩过的坑记录下来给同样有备份、整理、迁移需求的兄弟们一个参考。不管你是单纯想备份还是想分析自己的收藏习惯这篇都能直接照搬。1. 万事开头难先把导出方案定下来1.1 为什么B站官方不做“一键导出”B站目前没有提供任何“导出收藏夹”的官方按钮这是平台策略决定的不只是技术做不到。收藏数据一旦沉淀在某个平台上就相当于用户的隐形资产平台不提供导出本质上就是在提升用户迁移的成本。这个逻辑很容易理解类似很多笔记软件、视频平台、音乐APP入口做得很顺出口却永远模模糊糊。但对用户来说这个限制很麻烦。收藏夹里的内容不只是“看过的东西”很多是稍微晚一点就要用的教程、值得反复看的纪录片、想学习的公开课。我一直担心一件事哪天某个视频被UP主删除或者平台调整分区策略收藏夹里那些内容就彻底消失了。与其被动等不如主动做一份本地备份。所以“导出收藏夹”这件事核心价值有两个一是备份把自己的数据真正掌握在手里二是整理导出的数据可以做成表格按时间、UP主、分区去复盘自己到底收藏了什么信息价值远超在网页端干巴巴地翻页。1.2 三条路线的优劣对比与选型建议了解完需求再来看可行的方案。目前想把B站收藏夹导出来主要有三条路手动复制、现成的开源工具、自己写脚本。这三条路我都试过先说结论收藏量在100条以内手动处理勉强能忍几百上千条只有后两条路靠谱。手动复制最大的问题不是慢是容易漏。B站收藏夹有分页加载翻到后面还会出现滚动懒加载的情况你很难确认到底有没有全部复制完。而且复制下来的内容通常只有标题和链接收藏时间、UP主这些信息丢了后续做数据分析就无从谈起。现成的开源工具确实省事GitHub上有不少“B站收藏夹导出”相关的项目有些甚至带GUI界面。但它们的通病是更新慢B站接口只要升级一次工具就可能失效而且把账号Cookie交给第三方工具本身就有安全风险我更推荐自己动手写脚本。自己写脚本听起来门槛高其实拆开看就是“调两个API、处理几页JSON、写进一张表格”完全在能力范围内。而且脚本方案的最大优势是可控Cookie只保存在本地、字段按需定制、导出的格式自己选。这篇文章后面提到的代码就是我实测可用的最终版本可以直接复制使用。2. 核心解密B站收藏夹API与请求参数2.1 两个必须了解的官方API接口B站的官方API是现成的不需要任何申请密钥只要带上自己账号的登录态即可访问。要完成收藏夹导出只需要用到两个核心接口。第一个是获取“收藏夹列表”。这个接口会返回当前账号下创建的所有收藏夹信息包括收藏夹ID、名称、内容数量https://api.bilibili.com/x/v3/fav/folder/created/list-all?up_mid{你的UID}第二个是获取“某个收藏夹内的视频列表”。这里需要用到上一步返回的收藏夹ID同时控制分页参数https://api.bilibili.com/x/v3/fav/resource/list?media_id{收藏夹ID}pn{页码}ps{每页数量}platformweb关于这两个接口的细节有几个点需要说明一下。up_mid就是B站个人空间地址里那一串数字。比如你打开自己的空间地址类似https://space.bilibili.com/1234567那1234567就是你的UID。接口里的media_id是收藏夹的唯一标识这个ID和你在网页端看到的“收藏夹ID”是两回事必须通过第一个接口去拿不要自己猜。分页参数里pn表示页码从1开始ps表示每页条数。B站对ps的上限控制比较严格实测传20最稳妥传50偶尔会被拒绝。不要觉得20太少一个收藏夹就算有1000条也就50次请求配合后面的延时控制几十秒就跑完。2.2 Cookie获取方法只有登录态能拿到完整数据调用这些接口时绝大部分字段都要求传入登录后的Cookie信息。别嫌麻烦这一步是整个导出流程中最重要的准备工作。Cookie本质上是你的临时身份凭证B站在服务端根据Cookie判断“这个请求来自谁”没有这个凭证接口只会返回“未登录”的错误。我自己最推荐的Cookie获取方法是用浏览器开发者工具复制。打开Chrome或Edge先登录B站网页版。然后按F12打开开发者工具切到“网络Network”标签页刷新一下B站任意页面。此时能在请求列表里看到大量请求在过滤框里输入api.bilibili.com随便点开一个请求在“请求头Request Headers”里找到Cookie:这一行后面那一长串就是你要的内容全部复制下来。有朋友会问能不能在浏览器控制台里直接敲document.cookie来拿我试过这个方法只能拿到部分非HttpOnly字段关键的SESSDATA字段是HttpOnly属性JS代码根本读不到所以还是老老实实用开发者工具复制最靠谱。还有一点必须提醒Cookie就是账号的钥匙泄露给任何人就相当于把账号借出去了。建议用完之后在B站网页端退出登录再重新登录一次让旧的Cookie失效或者至少在脚本运行完就立刻从代码文件里删掉Cookie不要存到云端笔记里。2.3 返回字段说明与数据清洗思路请求接口后返回的数据是一个JSON对象结构有点层层嵌套但核心内容都在data.medias这个数组里。每条视频的数据包含这些关键字段字段名含义用途id视频BV号生成视频链接title视频标题导出核心内容cover封面图链接可选字段pub_date视频发布时间判断内容时效性fav_time收藏时间查看收藏轨迹upper.nameUP主名称按作者分类link视频短链接直达视频页这里有个细节值得注意接口返回的fav_time和pub_date都是Unix时间戳也就是一串秒数。直接看这串数字是看不出时间的需要转换成人类可读格式。Python里用datetime.fromtimestamp(时间戳)一行代码就能搞定下面的脚本里已经写好了。另外有些收藏内容可能是互动视频、剧集或者已经失效的视频返回的字段会有些差异。写脚本的时候最好对title为空的情况做兜底处理避免导出的表格里出现一堆空行。3. 手动实操用Python脚本把收藏夹完整导出来3.1 环境准备与安装依赖先交代一下环境脚本基于Python 3.8理论上Windows/macOS/Linux都能跑。除了Python标准库之外只要额外装一个requests库。安装命令很简单pip install requests如果你用的是Python 3.8以上版本其实也可以用自带的urllib来发请求少装一个库更清爽。但requests在易用性上明显更好代码也更简洁我这里统一用requests演示。如果你连Python都没装去官网下个最新稳定版安装时记得勾选“Add Python to PATH”否则命令行里敲不了python命令。整个脚本不需要GUI界面命令行走天下。考虑到不是所有人都熟悉命令行后面的步骤我会尽量写得细一些照着一行行敲就行。3.2 完整脚本实现可复制下面这个脚本是我实跑过的版本做了三件事读取你配置的Cookie和UID、获取所有收藏夹列表、遍历每个收藏夹分页拉取视频信息最后统一输出两个文件一个bili_favorites.csv用Excel打开一个bili_favorites.json保留完整原始数据备用。import requests import json import time import csv from datetime import datetime # 需要手动配置的部分 UID 你的UID COOKIE 你的完整Cookie # HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0 Safari/537.36, Referer: https://www.bilibili.com/, Cookie: COOKIE, } def ts_to_str(ts): 把Unix时间戳转成可读时间 if not ts: return return datetime.fromtimestamp(ts).strftime(%Y-%m-%d %H:%M:%S) def get_fav_folders(): 获取当前账号下所有收藏夹 url fhttps://api.bilibili.com/x/v3/fav/folder/created/list-all?up_mid{UID} resp requests.get(url, headersHEADERS, timeout10) data resp.json() if data.get(code) ! 0: print(f获取收藏夹列表失败{data}) return [] folders data.get(data, {}).get(list, []) print(f共发现 {len(folders)} 个收藏夹) return folders def get_fav_medias(media_id, total): 分页获取某个收藏夹内的所有视频返回完整列表 all_medias [] ps 20 pn 1 while pn * ps total ps: url ( fhttps://api.bilibili.com/x/v3/fav/resource/list f?media_id{media_id}pn{pn}ps{ps}platformweb ) resp requests.get(url, headersHEADERS, timeout10) data resp.json() if data.get(code) ! 0: print(f 第 {pn} 页请求失败{data}) break medias data.get(data, {}).get(medias, []) if not medias: break all_medias.extend(medias) print(f 已抓取 {len(all_medias)} / {total} 条) pn 1 time.sleep(0.6) return all_medias def main(): folders get_fav_folders() if not folders: return all_rows [] all_media_raw {} for folder in folders: fid folder.get(id) fname folder.get(title) total folder.get(media_count, 0) print(f\n处理收藏夹{fname}共 {total} 条) if total 0: continue medias get_fav_medias(fid, total) all_media_raw[fname] medias for m in medias: upper m.get(upper) or {} row { 收藏夹: fname, 标题: m.get(title, ), BV号: m.get(bvid, ), 链接: m.get(link, ), UP主: upper.get(name, ), 发布时间: ts_to_str(m.get(pub_date)), 收藏时间: ts_to_str(m.get(fav_time)), 简介: (m.get(intro) or )[:50], } all_rows.append(row) if not all_rows: print(没有导出任何数据请检查Cookie和UID) return # 输出CSVUTF-8 BOM避免Excel打开乱码 csv_file bili_favorites.csv with open(csv_file, w, newline, encodingutf-8-sig) as f: writer csv.DictWriter(f, fieldnamesall_rows[0].keys()) writer.writeheader() writer.writerows(all_rows) # 输出JSON原始数据 json_file bili_favorites.json with open(json_file, w, encodingutf-8) as f: json.dump(all_media_raw, f, ensure_asciiFalse, indent2) print(f\n导出完成CSV文件{csv_file}JSON文件{json_file}共 {len(all_rows)} 条记录) if __name__ __main__: main()把这个脚本保存成export_bili_fav.py运行之前记得先做好两处配置把UID替换成你的个人空间ID把COOKIE替换成2.2节复制的完整Cookie字符串。别把这两个字段留空否则只会浪费一次报错时间。3.3 运行、验证与结果解读配置好之后在命令行进入脚本所在目录执行python export_bili_fav.py正常情况下的输出会是这样的共发现 3 个收藏夹 处理收藏夹默认收藏夹共 428 条 已抓取 20 / 428 条 已抓取 40 / 428 条 ... 已抓取 428 / 428 条 处理收藏夹学习资料共 156 条 ... 导出完成CSV文件bili_favorites.csvJSON文件bili_favorites.json共 xxxx 条记录看到 “导出完成” 之后用Excel打开bili_favorites.csv检查一下。如果打开发现中文乱码别慌这不是数据问题是编码问题脚本里已经用utf-8-sig格式输出就是为了避免这个坑如果你用的还是乱码说明可能用了记事本打开CSV换成WPS或Excel就好。每一行的标题、链接、UP主、收藏时间都在基本就能确认导出的数据是完整的。JSON文件的作用是留底里面保存了所有原始返回字段。万一以后想扩展更多字段不用重新跑接口直接解析JSON文件就好。关于字段的详细含义可以回看前文2.3节的表格。4. 踩坑实录高频问题与排查方法4.1 马上能用的“常见报错速查表”自己写代码跑数据出问题是常态关键是能快速定位。我把实测过程中遇到的高频问题整理成了一张速查表按“症状-原因-解法”的路径来看一眼就能直接上手排查。问题现象大概率原因解决方法返回code: -101Cookie未正确携带或已过期重新复制Cookie确认请求头里有完整的SESSDATA返回code: -352风控拦截请求太频繁把睡眠时间从0.6提高到1-2秒不要开多线程并发只返回20条就停了没有翻页或翻页逻辑错误检查while循环条件是否按total计算了总页数所有字段为空复制的Cookie不完整用开发者工具方式复制而不是document.cookie报错Invalid URLUID或链接拼接出错打印URL检查看up_mid和media_id是否被正确替换CSV中文乱码编码问题确认是用utf-8-sig写入CSV而不是普通utf-8HTTP 412B站认为客户端异常请求头补全Referer和正常的User-Agent这里重点说一下-352这个问题。B站的风控策略是动态的短时间内请求频率过高就容易触发。我最初跑的时候没有加延时结果在第3个收藏夹就触发了风控整个脚本直接卡死。后来改成每次请求之间至少停0.6秒情况才好转。如果收藏夹特别多建议把延时调到1秒以上安全优先。另外-101这个报错几乎90%是因为Cookie复制不全。Cookie字符串很长复制的时候容易漏掉末尾的字符。粘贴后最好也检查一下前后有没有多余的空格空格虽然不会导致100%报错但有时候就是这种小细节让人抓狂。4.2 实用扩展从“导出数据”到“使用数据”脚本跑通之后导出只是起点怎么用这批数据才体现价值。我这段时间用导出的数据做了几件事感觉受益挺大的。第一件事筛出“已失效”的视频。把CSV里的链接批量用脚本检测一遍凡是返回404或者在网页端提示“视频不可用”的单独列一张表决定是取消收藏还是找替代资源。B站的视频有时候只是因为版权原因被限制过段时间又会恢复这时候别急着把本地记录删掉先保留着。第二件事按“收藏时间”做趋势分析。用CSV里的收藏时间字段很容易看到自己在哪些时间段集中收藏了一堆视频反而暴露出“收藏从未停止学习从未开始”的囤积习惯。我现在每季度会跑一次导出对比本季度的收藏趋势决定下一阶段的学习重心。第三件事把导出的JSON转成适用于其他工具的格式。比如导入Obsidian做个人知识库或者写个简单的转存脚本把“学习资料”收藏夹里的视频信息同步成一份结构化清单。有了完整的数据字段这些都是顺手的事关键是你不再被平台限制住了。最后还有一个小建议养成定期导出的习惯。不用太频繁一个月一次就够。B站不会通知你哪条视频即将消失但你的本地表格里会清清楚楚记录下每条内容曾经存在过。这一点我深有体会。
网站建设高端定制企业官网