最初的校园英雄传最新版
12.59MB · 2025-12-03
最初的需求很简单:我想把 B 站视频中 “AI 小助手” 的字幕全部抓下来。
打开开发者工具(F12 → Console),我写了这样一段脚本
// 改进版:抓取时间 + 文本(更稳健)
const subtitles = Array.from(document.querySelectorAll('[class*="Part_"]'))
.map(div => {
const time = div.querySelector('[class*="Time_"]')?.innerText?.trim() || "";
// 直接拿 Content 层的文本(防止 Text 层未渲染)
const content = div.querySelector('[class*="Content_"]')?.innerText?.trim() || "";
return `${time} ${content}`.trim();
})
.filter(line => line.length > 3); // 去掉空行
if (subtitles.length === 0) {
alert("️ 没抓到字幕,请确认已展开『AI 小助手』面板。");
} else {
console.log(subtitles.join('n'));
const blob = new Blob([subtitles.join('n')], { type: 'text/plain' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'bilibili_ai_subtitles.txt';
a.click();
URL.revokeObjectURL(a.href);
alert(` 已抓取 ${subtitles.length} 条字幕,文件已下载!`);
}
这段 JavaScript 脚本就是一个 网页小帮手机器人 ,它负责从 B 站页面的「AI 小助手字幕区」里:
| 步骤 | 做的事 | 技术实现 | 生活比喻 |
|---|---|---|---|
| ① 扫描货架,找到所有字幕盒子 | 找到所有 class 名里带 Part_ 的 DOM 节点 | document.querySelectorAll('[class*="Part_"]') | 在超市货架上找“标有饼干”的盒子 |
| ② 拆开盒子,读取时间+文字 | 抓取每个字幕的时间和内容 | querySelector('[class*="Time_"]') + querySelector('[class*="Content_"]') | 拿出饼干包装上的生产日期 + 名称 |
| ③ 过滤空行,留下有效字幕 | 去掉没加载成功的空节点 | .filter(line => line.length > 3) | 把空包装袋丢掉,只留真的饼干 |
| ④ 打包成文件(Blob 技术) | 把字幕变成一个临时 txt 文件对象 | new Blob([...], { type: 'text/plain' }) | 用袋子把所有饼干装起来,贴上标签 |
| ⑤ 模拟点击下载 + 提示成功 | 创建一个隐藏下载链接并点击它 | a.click() + alert() | 小机器人把打包好的礼物送到你手上,还甜甜地说:“我干完啦~” |
Part_、Time_、Content_)。a.download 模拟点击下载,实现自动保存。alert() 提示 用户任务完成。
但是 浏览器有个坑:当出现这种提示时(如图):
可以使用两种绕过方式:
在 console 里输入:
allow pasting
然后再粘贴脚本即可执行。
按F12→切换到Conso1e标签→输入$=0回车,解除网页复制限制。
$=0
手动操作太麻烦,于是我决定用 Python 爬虫 来自动打开 B 站、点击 “AI 小助手”、抓取字幕并保存。
核心代码如下
import os
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
# ========== 用户输入 B站链接 ==========
bvid_input = input("请输入B站视频链接或BV号:n ").strip()
# 兼容用户只输入 BV号 的情况
import re
match = re.search(r'(BV[0-9A-Za-z]+)', bvid_input)
if not match:
print(" 无法识别BV号,请输入正确的视频链接或BV号!")
exit()
bvid = match.group(1)
VIDEO_URL = f"https://www.bilibili.com/video/{bvid}/"
# ========== 保存路径配置 ==========
SAVE_PATH = rf"F:简单demo尝试B站AI小助手抓取bilibili_ai_subtitles_{bvid}.txt"
MSEDGEDRIVER_PATH = r"F:简单demo尝试B站AI小助手抓取msedgedriver.exe"
# 如果要保留登录状态,请确保 Edge 全部关闭
USER_DATA_DIR = r"C:UsersAdminAppDataLocalMicrosoftEdgeUser Data"
PROFILE_DIR = "Default"
# ========== 启动浏览器 ==========
options = Options()
options.add_argument(f"--user-data-dir={USER_DATA_DIR}")
options.add_argument(f"--profile-directory={PROFILE_DIR}")
options.add_argument("--remote-debugging-port=9222") # 防止崩溃
options.add_experimental_option("detach", True) # 防止自动关闭
driver = webdriver.Edge(service=Service(MSEDGEDRIVER_PATH), options=options)
print(f" 正在打开视频页面:{VIDEO_URL}")
driver.get(VIDEO_URL)
time.sleep(8)
# ========== 打开“AI小助手”面板 ==========
try:
ai_button = driver.find_element(By.XPATH, '//span[contains(text(),"AI小助手") or contains(text(),"AI助手")]')
ai_button.click()
print(" 已点击『AI小助手』按钮")
except Exception:
print("️ 未找到AI小助手按钮,请手动展开。")
time.sleep(5)
# ========== 抓取字幕内容 ==========
js_code = r"""
const subtitles = Array.from(document.querySelectorAll('[class*="Part_"]'))
.map(div => {
const time = div.querySelector('[class*="Time_"]')?.innerText?.trim() || "";
const content = div.querySelector('[class*="Content_"]')?.innerText?.trim() || "";
return `${time} ${content}`.trim();
})
.filter(line => line.length > 3);
return subtitles.join('n');
"""
print(" 正在抓取字幕内容...")
subtitles_text = driver.execute_script(js_code)
if not subtitles_text.strip():
print("️ 没抓到字幕,请确认AI助手面板已展开。")
else:
os.makedirs(os.path.dirname(SAVE_PATH), exist_ok=True)
with open(SAVE_PATH, "w", encoding="utf-8") as f:
f.write(subtitles_text)
print(f" 已成功抓取 {len(subtitles_text.splitlines())} 条字幕!")
print(f" 文件已保存到:{SAVE_PATH}")
# 可选:运行结束后自动关闭浏览器
# driver.quit()
| 步骤 | 功能描述 | 技术实现 | 生活类比 |
|---|---|---|---|
| ① 用户输入视频链接或 BV 号 | 接收用户输入的 B 站链接(自动提取 BV 号) | input() + 正则匹配 BV[0-9A-Za-z]+ | 你告诉机器人要去哪个蛋糕店买蛋糕(BV号=店名) |
| ② 生成视频地址 | 拼接出完整 URL | VIDEO_URL = f"https://www.bilibili.com/video/{bvid}/" | ️ 小秘书在地图上找到这家店的地址 |
| ③ 启动浏览器 + 登录配置 | 启动 Edge 浏览器,用本地用户配置保持登录 | Selenium + Edge Options + --user-data-dir | 打开浏览器相当于机器人启动了自己的“导航车”去店里 |
| ④ 自动访问视频页面 | driver.get(VIDEO_URL) 并等待加载 | time.sleep(8) | ⏳ 机器人在门口等蛋糕师傅开门 |
| ⑤ 自动点击「AI 小助手」按钮 | 用 XPath 找到按钮并点击 | driver.find_element(By.XPATH, ...) | 机器人自己按电梯按钮进入蛋糕展示厅 |
| ⑥ 注入 JavaScript 脚本抓字幕 | 执行之前的网页脚本提取字幕 | driver.execute_script(js_code) | ️ 小秘书打开笔记本,把展示柜上所有蛋糕(字幕)都记下来 |
| ⑦ 把字幕保存成本地 txt 文件 | 把返回的字幕写入 bilibili_ai_subtitles_xxx.txt | open(..., "w", encoding="utf-8") | 小秘书打包成一个“字幕礼盒”送给主人 |
| ⑧ 结束提示 | 输出成功日志 | print() | 小秘书报告:“任务完成!共抓到 235 条字幕!” |
1️⃣ Selenium 自动化
2️⃣ 正则匹配 BV 号
3️⃣ JavaScript 注入执行
driver.execute_script(js_code) 在网页内部运行 JS。4️⃣ 文件保存
bilibili_ai_subtitles_BVxxxx.txt,区分不同视频。Edge 驱动和浏览器版本匹配
打开 Edge 浏览器;
在地址栏输入:
edge://settings/help
看到版本号,比如:
版本 130.0.2849.80 (官方内部版本) (64 位)
访问微软官方 WebDriver 下载页:
developer.microsoft.com/en-us/micro…
下载对应版本的 msedgedriver.exe(版本号前三位必须一致,例如 130)。
把下载的 msedgedriver.exe 放到:
F:简单demo尝试B站AI小助手抓取
Selenium 控制 Edge 的时候,如果你电脑已经开着 Bing / Edge,会出现错误:
DevToolsActivePort file doesn't exist
Microsoft Edge failed to start: crashed.
在 PowerShell 输入:
taskkill /F /IM msedge.exe
这样就能关闭所有 Edge / Bing 相关进程,让 Selenium 能正常启动浏览器。
打开 文件资源管理器(Win + E)
在地址栏里粘贴下面这一行,然后按回车:
%LOCALAPPDATA%MicrosoftEdgeUser Data
你会看到很多文件夹,比如:
Default
Profile 1
Profile 2
...
其中:
例子路径会是:
C:UsersAdminAppDataLocalMicrosoftEdgeUser Data
打开 Edge 浏览器
在地址栏输入:
edge://version
找到一行:
用户数据目录 / Profile path
比如显示:
C:UsersAdminAppDataLocalMicrosoftEdgeUser DataDefault
这就是完整路径!
exit() 报错打包后的程序提示:
NameError: name 'exit' is not defined
解决方法:
Python 打包后 exit() 无效,要改成:
import sys
sys.exit()
这版脚本从原来的命令行操作升级为带弹窗交互的 GUI 工具,所有输入与提示都从
input()、print() 改成了 tkinter 弹窗(askstring、messagebox)。同时加入了错误提示、手动确认继续、结果汇报等交互优化,让整个流程更人性化、可视化、适合打包成 EXE 双击使用,不再需要打开命令行。
实现情况:
程序用 tkinter 实现输入框与消息弹窗,通过 selenium 控制 Edge 浏览器打开 B站视频、点击“AI小助手”、执行注入的 JavaScript 脚本提取字幕,再用 Python 将结果保存为 txt 文件。整个过程融合了前端 DOM 抓取与后端文件写入逻辑,实现了“一键输入 → 自动抓取 → 弹窗提示保存”的自动化流程。
import os
import time
import re
import tkinter as tk
from tkinter import messagebox, simpledialog
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
# ========== 弹窗输入 ==========
root = tk.Tk()
root.withdraw() # 不显示主窗口
bvid_input = simpledialog.askstring("B站字幕抓取", "请输入B站视频链接或BV号:")
if not bvid_input:
messagebox.showinfo("提示", " 你没有输入视频链接,程序已退出。")
exit()
match = re.search(r'(BV[0-9A-Za-z]+)', bvid_input)
if not match:
messagebox.showerror("错误", "无法识别BV号,请输入正确的视频链接!")
exit()
bvid = match.group(1)
VIDEO_URL = f"https://www.bilibili.com/video/{bvid}/"
SAVE_PATH = rf"F:简单demo尝试B站AI小助手抓取bilibili_ai_subtitles_{bvid}.txt"
MSEDGEDRIVER_PATH = r"F:简单demo尝试B站AI小助手抓取msedgedriver.exe"
USER_DATA_DIR = r"C:UsersAdminAppDataLocalMicrosoftEdgeUser Data"
PROFILE_DIR = "Default"
# ========== 启动 Edge ==========
options = Options()
options.add_argument(f"--user-data-dir={USER_DATA_DIR}")
options.add_argument(f"--profile-directory={PROFILE_DIR}")
options.add_argument("--remote-debugging-port=9222")
options.add_experimental_option("detach", True)
try:
driver = webdriver.Edge(service=Service(MSEDGEDRIVER_PATH), options=options)
except Exception as e:
messagebox.showerror("错误", f"Edge 启动失败:n{e}")
exit()
driver.get(VIDEO_URL)
time.sleep(8)
# ========== 打开“AI小助手”面板 ==========
try:
ai_button = driver.find_element(By.XPATH, '//span[contains(text(),"AI小助手") or contains(text(),"AI助手")]')
ai_button.click()
time.sleep(5)
except Exception:
messagebox.showwarning("提示", "未找到AI小助手按钮,请手动展开后点击“确定”继续。")
simpledialog.askstring("操作提示", "手动展开后点击确定继续执行...")
time.sleep(3)
# ========== 抓取字幕内容 ==========
js_code = r"""
const subtitles = Array.from(document.querySelectorAll('[class*="Part_"]'))
.map(div => {
const time = div.querySelector('[class*="Time_"]')?.innerText?.trim() || "";
const content = div.querySelector('[class*="Content_"]')?.innerText?.trim() || "";
return `${time} ${content}`.trim();
})
.filter(line => line.length > 3);
return subtitles.join('n');
"""
subtitles_text = driver.execute_script(js_code)
if not subtitles_text.strip():
messagebox.showwarning("提示", "️ 没抓到字幕,请确认AI助手面板已展开。")
else:
os.makedirs(os.path.dirname(SAVE_PATH), exist_ok=True)
with open(SAVE_PATH, "w", encoding="utf-8") as f:
f.write(subtitles_text)
messagebox.showinfo("成功 ", f"共抓取 {len(subtitles_text.splitlines())} 条字幕!nn已保存到:n{SAVE_PATH}")
# driver.quit() # 可选
当 Python 代码调试完成后,使用 PyInstaller 打包:
pip install pyinstaller
执行:
pyinstaller --noconsole --onefile bilibili_ai_subtitle_scraper_gui.py
注意:
如果提示找不到 icon.ico,要么提供图标文件,要么删除 --icon=icon.ico
生成的 EXE 在:
distbilibili_ai_subtitle_scraper_gui.exe
使用 tkinter 弹窗输入:
import tkinter as tk
from tkinter import simpledialog
root = tk.Tk()
root.withdraw()
bvid = simpledialog.askstring("B站字幕抓取", "请输入B站视频链接或BV号:")
用户输入后自动爬取、保存、弹窗提示
双击 EXE
弹窗输入 BV 链接
自动打开 B 站
自动抓取字幕并保存到本地
输出示例:
共抓取 235 条字幕!
文件已保存到:F:简单demo尝试B站AI小助手抓取bilibili_ai_subtitles.txt
| 问题 | 解决方案 |
|---|---|
| Edge 启动崩溃 | 检查版本一致性 / 关闭进程 / 指定路径 |
| exit() 未定义 | 改用 sys.exit() |
| icon.ico 不存在 | 去掉 --icon 参数或添加文件 |
| 控制台不允许粘贴 | 输入 allow pasting 或用书签执行 |
| EdgeDriver 找不到 | 重新下载匹配版本 |
这次实践让我彻底明白:
从一个简单的 F12 脚本,逐步成长为一个能自动爬取字幕的桌面工具。
我甚至能把它加上批量抓取、进度条、错误检测等功能,继续进化成属于自己的“小AI字幕精灵”。