This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
openclaw-skills/test_deep_subtitle.py
T
OpenClaw Agent e0a2b323d9 Update obsidian-kb skill and add find-skills
- obsidian-kb: Add OCR processors (easyocr, tesseract)
- obsidian-kb: Fix subtitle detection with test files
- obsidian-kb: Add cookie verification script
- Add find-skills skill for discovering capabilities
- Add video processing scripts
- Update clawhub lock file
2026-02-09 11:53:42 +08:00

220 lines
9.8 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
深度测试B站字幕提取 - 尝试所有可能的方法
"""
import asyncio
import json
import re
from playwright.async_api import async_playwright
from bs4 import BeautifulSoup
async def test_all_methods(bvid):
"""尝试所有方法获取字幕"""
url = f"https://www.bilibili.com/video/{bvid}"
async with async_playwright() as playwright:
browser = await playwright.chromium.launch(headless=True)
context = await browser.new_context()
page = await context.new_page()
print(f"正在测试视频: {url}")
print("=" * 80)
# 等待页面完全加载
print("\n1. 访问页面...")
await page.goto(url, wait_until='networkidle', timeout=60000)
await asyncio.sleep(3)
# 获取基本信息
print("\n2. 获取视频基本信息...")
try:
api_url = "https://api.bilibili.com/x/web-interface/view"
response = await page.request.get(api_url, params={'bvid': bvid})
data = await response.json()
if data.get('code') == 0:
video_data = data.get('data', {})
print(f" 标题: {video_data.get('title')}")
print(f" aid: {video_data.get('aid')}")
print(f" cid: {video_data.get('cid')}")
cid = video_data.get('cid')
aid = video_data.get('aid')
else:
print(f" ❌ 获取基本信息失败: {data.get('message')}")
await browser.close()
return
except Exception as e:
print(f" ❌ 异常: {e}")
await browser.close()
return
# 方法1: 使用标准 API(官方 CC 字幕)
print("\n3. 方法1: 官方 CC 字幕 API...")
try:
player_url = "https://api.bilibili.com/x/player/v2"
player_response = await page.request.get(player_url, params={'bvid': bvid, 'cid': cid})
player_data = await player_response.json()
if player_data.get('code') == 0:
subtitle_info = player_data.get('data', {}).get('subtitle', {})
subtitles_list = subtitle_info.get('subtitles', [])
if subtitles_list:
print(f" ✅ 找到 {len(subtitles_list)} 个官方字幕")
for i, sub in enumerate(subtitles_list):
print(f" [{i+1}] {sub.get('lan_doc')} (id={sub.get('id')})")
# 获取第一个字幕内容
subtitle_url = subtitles_list[0].get('subtitle_url', '')
if subtitle_url:
full_url = f"https:{subtitle_url}"
print(f" URL: {subtitle_url}")
sub_response = await page.request.get(full_url)
if sub_response.ok:
sub_data = await sub_response.json()
body = sub_data.get('body', [])
print(f" ✅ 获取成功,共 {len(body)} 条字幕")
print(f" 示例: {body[0] if body else '无'}")
else:
print(" ❌ 没有找到官方 CC 字幕")
print(f" Subtitle info: {json.dumps(subtitle_info, indent=8, ensure_ascii=False)}")
except Exception as e:
print(f" ❌ 异常: {e}")
# 方法2: 尝试 AI 字幕 API
print("\n4. 方法2: AI 自动生成字幕...")
try:
# B站 AI 字幕可能在另一个 API
ai_subtitle_url = "https://api.bilibili.com/x/player/wbi/v2/playurl"
# 这个通常用于视频流,但也可能包含字幕信息
ai_params = {
'bvid': bvid,
'cid': cid,
'qn': 80, # 清晰度
'fnval': 16, # 包含字幕的标志
}
ai_response = await page.request.get(ai_subtitle_url, params=ai_params)
ai_data = await ai_response.json()
if ai_data.get('code') == 0:
print(f" AI API 响应: {json.dumps(list(ai_data.get('data', {}).keys()), indent=8, ensure_ascii=False)}")
# 检查是否有字幕信息
if 'subtitle' in ai_data.get('data', {}):
subtitle = ai_data['data']['subtitle']
print(f" ✅ 找到 AI 字幕信息")
print(f" {json.dumps(subtitle, indent=8, ensure_ascii=False)}")
except Exception as e:
print(f" ❌ 异常: {e}")
# 方法3: 从页面脚本标签中提取(可能包含字幕配置)
print("\n5. 方法3: 从页面 HTML 中提取字幕配置...")
try:
content = await page.content()
soup = BeautifulSoup(content, 'lxml')
script_tags = soup.find_all('script')
found_subtitle = False
for script in script_tags:
if script.string and ('subtitle' in script.string or 'cc_subtitle' in script.string):
# 提取包含字幕配置的 JSON
matches = re.findall(r'window\.__(?:playinfo|INITIAL_STATE|subtitle__)\s*=\s*({.+?});', script.string)
for match in matches:
try:
data = json.loads(match)
# 查找字幕相关字段
if 'subtitle' in str(data) or 'subtitles' in str(data):
print(f" ✅ 找到字幕配置")
print(f" {json.dumps(data, indent=8, ensure_ascii=False)[:500]}")
found_subtitle = True
break
except:
pass
if found_subtitle:
break
if not found_subtitle:
print(" ❌ 页面中没有找到字幕配置")
except Exception as e:
print(f" ❌ 异常: {e}")
# 方法4: 尝试不同的播放器 API 端点
print("\n6. 方法4: 尝试其他 API 端点...")
endpoints = [
f"https://api.bilibili.com/x/player/wbi/v2/player?bvid={bvid}&cid={cid}",
f"https://api.bilibili.com/x/player/v2?bvid={bvid}&cid={cid}",
f"https://api.bilibili.com/x/player/playurl?bvid={bvid}&cid={cid}&qn=80&fnval=16",
]
for endpoint in endpoints:
try:
print(f" 测试: {endpoint}")
response = await page.request.get(endpoint)
if response.ok:
data = await response.json()
# 检查响应中是否有字幕信息
json_str = json.dumps(data, ensure_ascii=False)
if 'subtitle' in json_str.lower():
print(f" ✅ 可能包含字幕信息")
# 只显示相关部分
if 'data' in data and 'subtitle' in str(data['data']):
print(f" {json.dumps(data.get('data', {}).get('subtitle', {}), indent=12, ensure_ascii=False)}[:500]")
else:
print(f" 状态码: {response.status}")
except Exception as e:
print(f" 异常: {e}")
# 方法5: 尝试使用 aid 而不是 cid
print("\n7. 方法5: 尝试使用 aid 参数...")
try:
if aid:
player_url = "https://api.bilibili.com/x/player/v2"
response = await page.request.get(player_url, params={'aid': aid, 'bvid': bvid})
data = await response.json()
print(f" 响应码: {data.get('code')}")
if data.get('code') == 0:
subtitle_info = data.get('data', {}).get('subtitle', {})
subtitles_list = subtitle_info.get('subtitles', [])
if subtitles_list:
print(f" ✅ 使用 aid 找到 {len(subtitles_list)} 个字幕")
else:
print(f" ❌ 使用 aid 也没有找到字幕")
except Exception as e:
print(f" ❌ 异常: {e}")
# 方法6: 检查视频是否有多 P(分集)
print("\n8. 方法6: 检查是否为分集视频...")
try:
api_url = "https://api.bilibili.com/x/web-interface/view"
response = await page.request.get(api_url, params={'bvid': bvid})
data = await response.json()
if data.get('code') == 0:
pages = data.get('data', {}).get('pages', [])
print(f" 共 {len(pages)} 个分集")
for i, p in enumerate(pages):
print(f" [{i+1}] cid={p.get('cid')}, page={p.get('page')}, title={p.get('part')}")
# 如果有多个分集,尝试每个分集的字幕
if len(pages) > 1:
print(f"\n 尝试获取第1个分集的字幕...")
first_cid = pages[0].get('cid')
player_url = "https://api.bilibili.com/x/player/v2"
response = await page.request.get(player_url, params={'bvid': bvid, 'cid': first_cid})
data = await response.json()
subtitle_info = data.get('data', {}).get('subtitle', {})
subtitles_list = subtitle_info.get('subtitles', [])
if subtitles_list:
print(f" ✅ 第1个分集有 {len(subtitles_list)} 个字幕")
else:
print(f" ❌ 第1个分集也没有字幕")
except Exception as e:
print(f" ❌ 异常: {e}")
await browser.close()
if __name__ == '__main__':
bvid = "BV1KtFzzqEUG"
asyncio.run(test_all_methods(bvid))