Bilibili 字幕批量下载报 Cookie 失效?用 TaoToken 让 Codex 对照 CID 接口查
2026/9/21 20:18:23 网站建设 项目流程

1. 脚本跑一半就报 Cookie 失效,问题到底出在哪

你手上这份 Python 批量下载 Bilibili 视频字幕的脚本,逻辑其实不复杂:pandas 读 CSV 拿到标题和视频链接,正则抠出 BV 号,请求 pagelist 接口拿 CID,再打 wbi/v2 接口取字幕地址,最后把字幕正文拼成 CSV。链路清晰,但真正跑起来,十有八九会卡在三个地方:headers 里的 Cookie 过期、wbi 参数对不上、分 P 取完 CID 之后字幕链接拿不到。

这三个问题有个共同点——它们都不是 Python 语法错误,而是接口返回的 JSON 在“说话”。Cookie 失效时接口会返回-101未登录;wbi 签名不对会返回-403;CID 拿错或者分 P 没对齐,subtitle字段直接是空数组。你盯着 traceback 看不出所以然,因为 requests 根本没抛异常,它只是安安静静返回了一个带错误码的 JSON。

这篇就是从这个排障视角出发:先把 Codex 通过 TaoToken 配通,让它当一个“接口对照助手”,你把报错、返回 JSON 和分段请求链路贴给它,让它逐项核对 CID 和字幕接口的参数,确认请求能跑通之后,再回到脚本里改 headers 和参数。TaoToken 在这里只负责给 Codex 提供 Key 和 Base URL,不替代 requests、pandas,也不会去访问 B 站——它就是个帮你读接口、对参数的推理入口。

适合谁看:已经有一份能跑但总在某个环节断掉的字幕下载脚本,想快速定位是 Cookie、wbi 还是 CID 问题的 Python 使用者。

2. 先把 Codex 接到 TaoToken 上,拿到排查用的 Key 和 Base URL

排障之前得有个能对话的模型入口。我试过直接拿报错去搜索引擎翻,效率很低,因为 B 站接口的错误码和参数组合太多,搜到的答案往往对不上你的具体分段。用 Codex 的好处是你可以把整段请求链路和返回 JSON 一起贴进去,让它按接口文档逐项比对。

第一步,打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 创建账号,进控制台生成一个 API Key。这个 Key 就是你后面填进 Codex 配置里的凭证。

第二步,在 Codex 的配置里把 Base URL 填成https://taotoken.net/api。注意这里只填到/api,不要自己拼/v1/chat/completions之类的路径,Codex 会按自己的协议去补全。模型名按你控制台里可用的填,通常gpt-4oclaude-3-5-sonnet这类都能选。

配置大概长这样,以环境变量方式注入最省事:

export OPENAI_API_KEY="你在TaoToken控制台生成的Key" export OPENAI_BASE_URL="https://taotoken.net/api"

如果你用的是 Codex CLI,可以在它的配置文件里写:

[model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" env_key = "TAOTOKEN_API_KEY"

然后export TAOTOKEN_API_KEY="你的Key"。配完之后跑一句最简单的对话测试,能正常返回就说明通道通了。这一步别省,很多人后面排查半天,结果是 Base URL 多写了个斜杠或者 Key 复制时带了空格。

注意:TaoToken 只提供模型推理入口,你的脚本该用 requests 还是用 requests,该带 Cookie 还是带 Cookie,它不碰你的业务请求。

3. 把报错和请求链路整理成 Codex 能读的排查材料

配通之后,别急着把整个脚本甩给 Codex。它需要的是“分段请求链路 + 每段的返回”,而不是几百行代码。你要做的是把三个关键节点的请求和响应摘出来。

第一个节点是 pagelist 取 CID。请求长这样:

cid_back = requests.get( f"http://api.bilibili.com/x/player/pagelist?bvid={bvid}", headers=headers ) print(cid_back.status_code) print(cid_back.json())

正常返回里data是个列表,每个元素有cidpagepart。如果这里返回code: -400,多半是 bvid 抠错了,比如链接带了?p=2没去掉。如果返回code: -403,那是 headers 里的 Referer 或 User-Agent 被识别了。

第二个节点是 wbi/v2 取字幕地址。你原脚本里w_rid是写死的364cdf378b75ef6a0cee77484ce29dbb,这就是典型的 wbi 参数对不上。B 站的 wbi 签名是拿img_keysub_key按特定规则拼出来的,写死的值只在极短时间内有效,换个视频或者过几分钟就失效。正确做法是先请求https://api.bilibili.com/x/web-interface/nav拿到wbi_img里的两个 key,再按官方算法生成w_ridwts

第三个节点是字幕正文。拿到subtitle_url之后请求它,返回的 JSON 里body是字幕数组,每项有fromtocontent。如果subtitle_url是空,说明这个视频没有 CC 字幕,或者你的 Cookie 没有登录态看不到。

把这三段的请求 URL、headers、返回 JSON 整理成一段文本,贴给 Codex,问它:“这三段请求里,哪一段的参数和 B 站接口文档对不上?Cookie 失效会体现在哪个返回码上?”它会帮你逐项对照。

4. 让 Codex 对照 CID 和字幕接口逐项核对参数

贴材料的时候,把 Cookie 那行单独标出来。比如:

请求1: GET https://api.bilibili.com/x/player/pagelist?bvid=BV1xx411c7mD 返回: {"code":0,"data":[{"cid":123456789,"page":1,"part":"P1"}]} 请求2: GET https://api.bilibili.com/x/player/wbi/v2?aid=xxx&cid=123456789&w_rid=364cdf...&wts=1710000000 返回: {"code":-403,"message":"访问权限不足"} 请求3: GET https://aisubtitle.hdslb.com/bfs/subtitle/xxx.json 返回: {"code":-101,"message":"账号未登录"}

Codex 看到-403-101会告诉你:-403是 wbi 签名校验失败,-101是 Cookie 没带上或者已过期。然后它会建议你先去浏览器重新登录 B 站,F12 里复制最新的 Cookie,替换 headers 里的Cookie字段。同时把w_ridwts改成动态生成,而不是写死。

这里有个容易踩的坑:Cookie 里包含SESSDATAbili_jctDedeUserID等多个字段,你复制的时候要整行复制,别只拿SESSDATA。另外 Cookie 有时效,跑批量脚本前最好先手动请求一次 nav 接口确认登录态还在。

Codex 还能帮你验证 CID 是否取对。比如分 P 视频,pagelist 返回多个 CID,你原脚本用item['cid']循环取,这没问题,但要注意aid是从视频页面 HTML 里正则抠的,如果页面结构变了,aid可能抠错,导致 wbi/v2 返回-400。让 Codex 帮你写一段更稳的aid提取逻辑,比如从window.__INITIAL_STATE__里解析。

5. 验证请求跑通后再回脚本改 headers 和参数

Codex 给的建议不能直接信,得自己验证。最稳的方式是先用 curl 或 Python 单独跑通一个视频的三段请求,确认返回code: 0subtitle里有内容,再把这套参数搬回批量脚本。

验证 pagelist:

curl -s "https://api.bilibili.com/x/player/pagelist?bvid=BV1xx411c7mD" \ -H "User-Agent: Mozilla/5.0" \ -H "Referer: https://www.bilibili.com" \ -H "Cookie: 你的完整Cookie"

验证 wbi/v2 时,w_ridwts要动态算。你可以让 Codex 帮你写一个get_wbi_sign函数,输入img_keysub_key和参数字典,输出签名后的 query string。核心逻辑是:把参数按 key 排序,拼成key=value&key=value形式,加上wts,再用sub_key做一次 MD5。具体算法 Codex 会给你完整代码,你复制进脚本即可。

验证字幕正文:

subtitle_resp = requests.get(subtitle_url, headers=headers) print(subtitle_resp.status_code) print(subtitle_resp.json()['body'][:3])

如果这三步都返回正常,再把headers里的 Cookie 换成新的,把写死的w_rid换成动态生成,把aid提取逻辑换成从__INITIAL_STATE__解析。改完跑一个视频,看输出 CSV 里有没有字幕内容。

实测下来,最容易反复的是 Cookie。批量跑几十个视频,中途 Cookie 可能失效,脚本会开始大量返回-101。你可以在download_subtitle_json里加一个判断:如果 wbi_resp 返回code == -101,就打印提示并break,让你重新换 Cookie,而不是继续跑一堆失败请求。

6. 本篇常见错排查

报错一:KeyError: 'subtitle'说明 wbi/v2 返回的 JSON 里没有subtitle字段。先打印完整返回,看code是不是-403-101。如果是-403,检查w_rid是否动态生成;如果是-101,换 Cookie。

报错二:json.decoder.JSONDecodeError字幕 URL 返回的不是 JSON,可能是 HTML 错误页。检查subtitle_url是否以https:开头,你原脚本里拼了"https:" + subtitle_links[0]['subtitle_url'],如果接口返回的已经是完整 URL,就会拼成https:https://...。打印出来看一眼。

报错三:分 P 视频只下载了第一个 P检查cid_json['data']的长度,以及循环里filename的拼接逻辑。你原脚本用len(cid_json['data']) > 1判断是否多 P,这个没问题,但part_title里可能包含/等非法字符,导致文件写入失败。用sanitize_filename处理一下。

报错四:Cookie 复制后仍然-101浏览器 F12 里复制的 Cookie 可能带了换行或多余空格。用strip()清理,并确认SESSDATA的值没有过期。可以在浏览器里刷新一下 B 站首页,确认登录态还在,再重新复制。

报错五:aid提取为空页面 HTML 结构变化会导致text.find('"aid"')返回-1。改用正则re.search(r'"aid":(\d+)', text),或者从window.__INITIAL_STATE__里解析。

排障过程中如果 Codex 给的参数和实际返回对不上,把新的返回 JSON 再贴回去,让它重新核对。这个来回过程比你自己翻文档快得多。

7. 配通之后,这套排查方式还能复用到别的接口脚本

Codex 走 TaoToken 配通之后,你手里就多了一个“接口对照”工具。不只是 B 站字幕,任何带签名、带 Cookie、带多段请求的脚本,都可以用同样的方式排查:把每段请求和返回整理出来,让 Codex 逐项核对参数,确认跑通后再回脚本改。

如果你后面要长期跑这类批量任务,或者想把 Codex 接进自己的编码流程里,可以看看 Coding Plan,它更适合持续性的脚本调试和 Agent 场景。需要单独管理 Key 的话,API Keys 页面可以随时生成和吊销。接入文档里有 Base URL 和模型名的完整说明,配的时候对着填就行。

模型对话入口适合快速验证某个接口返回的含义,比如你拿不准-403-101的区别,直接开一个对话把 JSON 贴进去问,比翻社区帖子快。排障这件事,工具顺手了,剩下的就是耐心对参数。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询