#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 测试B站字幕提取 - 使用确定有字幕的视频 """ import asyncio import json from playwright.async_api import async_playwright async def test_with_cookie(bvid, cookie=None): """测试带 Cookie 的字幕提取""" 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() # 如果有 cookie,添加到上下文 if cookie: await context.add_cookies([cookie]) print("使用已登录 Cookie") # 使用 API 获取视频信息 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', {}) title = video_data.get('title', '') cid = video_data.get('cid', '') print(f"\n视频: {title}") print(f"BV号: {bvid}") print(f"cid: {cid}") # 获取字幕 if cid: 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() print(f"Player API 响应码: {player_data.get('code')}") 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')}") print(f" URL: {sub.get('subtitle_url')}") # 获取第一个字幕内容 subtitle_url = subtitles_list[0].get('subtitle_url', '') if subtitle_url: full_url = f"https:{subtitle_url}" print(f"\n正在获取字幕内容: {full_url}") sub_response = await page.request.get(full_url) print(f"字幕请求状态: {sub_response.status}") if sub_response.ok: sub_data = await sub_response.json() body = sub_data.get('body', []) print(f"\n字幕内容示例 (前5条):") for i, item in enumerate(body[:5]): from_time = item.get('from', 0) to_time = item.get('to', 0) content = item.get('content', '') print(f" [{i+1}] [{from_time:.1f}s - {to_time:.1f}s] {content}") print(f"\n✅ 字幕获取成功!共 {len(body)} 条字幕") else: print(f"❌ 获取字幕内容失败: {sub_response.status}") print(f"响应头: {sub_response.headers}") else: print("❌ 该视频没有字幕") print(f"Subtitle info: {json.dumps(subtitle_info, indent=2, ensure_ascii=False)}") else: print(f"❌ Player API 失败: {player_data.get('message')}") print(f"完整响应: {json.dumps(player_data, indent=2, ensure_ascii=False)}") else: print(f"❌ 获取视频信息失败: {data.get('message')}") await browser.close() async def main(): """测试多个视频""" # 罗翔的视频通常有官方字幕 test_videos = [ "BV1GJ411x7h7", # 罗翔 - 刑法 "BV1yx411s7Jq", # 可能的官方视频 "BV1zv4y1m7Qp", # B站官方视频 ] for bvid in test_videos: print(f"\n{'='*60}") print(f"测试视频: {bvid}") print(f"{'='*60}") try: await test_with_cookie(bvid) except Exception as e: print(f"❌ 测试失败: {e}") import traceback traceback.print_exc() await asyncio.sleep(2) if __name__ == '__main__': asyncio.run(main())