🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

刷B站 littlefallenstar/dsh-bili-scroll

DeepSeek Harness
littlefallenstar13 天前有提交已提供中文文档扫描:含敏感能力

每天自动刷一轮B站并写结论,推荐视频进稍后再看

29.8/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/24 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add littlefallenstar/dsh-bili-scroll
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么
dsh 原生插件 · platform
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 13 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 158 处,展示前 84 条)
  • 读取本地文件
    index.js:239
    try { myVer = String(JSON.parse(readFileSync(join(pluginDir, 'package.json'), 'utf8')).version || '') } catch { myVer = '' }
  • 读取本地文件
    index.js:248
    if (existsSync(win)) return win
  • 读取本地文件
    index.js:251
    for (const d of readdirSync(lib)) {
  • 读取本地文件
    index.js:254
    if (existsSync(p)) return p
  • 读取本地文件
    index.js:260
    try { return readdirSync(sitePkgs(venvRoot)).some((n) => n.startsWith(prefix)) } catch { return false }
  • 读取本地文件
    index.js:262
    const venvReadyNow = () => existsSync(venvPython()) && hasPkg(join(stateDir, '.venv'), 'bilibili_api')
  • 写入本地文件
    index.js:267
    mkdirSync(outDir, { recursive: true })
  • 写入本地文件
    index.js:271
    try { mkdirSync(join(stateDir, 'reports'), { recursive: true }) } catch { }
  • 写入本地文件
    index.js:275
    try { appendFileSync(logFile, line + '\n', 'utf8') } catch { }
  • 写入本地文件
    index.js:340
    writeFileSync(personaFile, capped, 'utf8')
  • 写入本地文件
    index.js:371
    writeFileSync(replyFile, capped, 'utf8')
  • 写入本地文件
    index.js:618
    writeFileSync(seenFile, HEADER + [...others, row].join('\n') + '\n', 'utf8')
  • 读取密钥环境变量
    index.js:1396
    if (process.env.DEEPSEEK_API_KEY) return {}
  • 删除本地文件
    index.js:1802
    try { rmSync(headlessRunFile, { force: true }) } catch { }
  • 发起网络请求
    index.js:2011
    const r = await fetch(
  • 执行外部命令来自配置/变量
    index.js:2632
    const child = spawn(dsh.command, args, {
  • 删除本地文件
    index.js:2683
    if (!cur?.pid || cur.pid === (child.pid || 0)) rmSync(headlessRunFile, { force: true })
  • 删除本地文件
    index.js:2705
    try { rmSync(headlessRunFile, { force: true }) } catch { }
  • 执行外部命令固定命令
    index.js:2796
    const c = spawn('uv', ['--version'], { windowsHide: true, stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    index.js:2807
    const c = spawn(cmd, ['--version'], { windowsHide: true, stdio: 'ignore' })
  • 执行外部命令来自配置/变量
    index.js:2824
    try { c = spawn(cmd, args, { cwd: stateDir, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] }) }
  • 执行外部命令来自配置/变量
    index.js:2861
    c = spawn(cmd, args, { cwd: stateDir, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'],
  • 删除本地文件
    index.js:3367
    rmSync(f, { force: true })
  • 执行外部命令来自配置/变量
    index.js:3514
    try { child = spawn(cmd, args, { detached: true, stdio: 'ignore' }) } catch (e) { resolve(String(e?.message ?? e)); return }
  • 发起网络请求
    index.js:3596
    const r = await fetch(url, {
  • 发起网络请求
    client.js:56
    const jget = async (p) => (await fetch(API + p, { credentials: 'same-origin' })).json()
  • 发起网络请求
    client.js:57
    const jpost = async (p, body) => (await fetch(API + p, {
  • 发起网络请求
    client.js:64
    const jdelete = async (p, body) => (await fetch(API + p, {
  • 写入剪贴板
    client.js:1021
    await navigator.clipboard.writeText(v)
  • 读取本地文件
    lib/hostdeps.mjs:50
    for (const n of readdirSync(join(npm, '@deepseek-ai'))) {
  • 读取本地文件
    lib/hostdeps.mjs:63
    for (const p of readdirSync(join(dshHome, 'profiles'))) {
  • 读取本地文件
    lib/hostdeps.mjs:78
    if (!existsSync(pkgFile)) return null
  • 读取本地文件
    lib/hostdeps.mjs:79
    const pkg = JSON.parse(readFileSync(pkgFile, 'utf8'))
  • 读取本地文件
    lib/hostdeps.mjs:86
    return existsSync(file) ? pathToFileURL(file).href : null
  • 写入本地文件
    lib/digest.mjs:117
    mkdirSync(dir, { recursive: true })
  • 写入本地文件
    lib/digest.mjs:120
    writeFileSync(file, text, 'utf8')
  • 执行外部命令来自配置/变量
    lib/mcp.mjs:33
    this.proc = spawn(command, args, {
  • 写入本地文件
    lib/state.mjs:46
    mkdirSync(dir, { recursive: true })
  • 读取本地文件
    lib/state.mjs:51
    try { return JSON.parse(readFileSync(file, 'utf8')) } catch { return fallback }
  • 写入本地文件
    lib/state.mjs:55
    writeFileSync(file, JSON.stringify(value, null, 2), 'utf8')
  • 读取本地文件
    lib/state.mjs:97
    if (!existsSync(from)) { log(`缺文件:${from}`); continue }
  • 读取本地文件
    lib/state.mjs:98
    if (!overwrite && existsSync(to)) continue
  • 读取本地文件
    lib/state.mjs:99
    if (overwrite && existsSync(to) && readFileSync(from, 'utf8') === readFileSync(to, 'utf8')) continue
  • 读取本地文件
    lib/state.mjs:99
    if (overwrite && existsSync(to) && readFileSync(from, 'utf8') === readFileSync(to, 'utf8')) continue
  • 写入本地文件
    lib/state.mjs:100
    copyFileSync(from, to)
  • 读取本地文件
    lib/today.mjs:31
    const doc = JSON.parse(readFileSync(todayFile(stateDir, date), 'utf8'))
  • 写入本地文件
    lib/today.mjs:40
    mkdirSync(todayDir(stateDir), { recursive: true })
  • 写入本地文件
    lib/today.mjs:42
    writeFileSync(todayFile(stateDir, date), JSON.stringify(doc, null, 2) + '\n', 'utf8')
  • 读取本地文件
    lib/today.mjs:272
    return readdirSync(todayDir(stateDir))
  • 写入本地文件
    lib/today.mjs:285
    try { writeFileSync(todayFile(stateDir, d), '', 'utf8') } catch { }
  • 发起网络请求
    lib/login.mjs:46
    const r = await fetch(SPI, { headers: { 'User-Agent': UA } })
  • 发起网络请求
    lib/login.mjs:55
    const r = await fetch(GEN, { headers: { 'User-Agent': UA } })
  • 发起网络请求
    lib/login.mjs:64
    const res = await fetch(pollUrl(key), { headers: { 'User-Agent': UA }, redirect: 'manual' })
  • 写入本地文件
    lib/login.mjs:80
    mkdirSync(stateDir, { recursive: true })
  • 写入本地文件
    lib/login.mjs:82
    writeFileSync(file, JSON.stringify({
  • 执行外部命令来自配置/变量
    lib/login.mjs:99
    child = spawn(pythonPath || 'python', ['-c', code, url, png], {
  • 读取本地文件
    lib/login.mjs:103
    const done = () => { try { resolve(existsSync(png) ? png : null) } catch { resolve(null) } }
  • 读取本地文件
    lib/uvfetch.mjs:33
    return createHash('sha256').update(readFileSync(file)).digest('hex')
  • 发起网络请求
    lib/uvfetch.mjs:45
    const r = await fetch(source.url + '.sha256')
  • 读取本地文件
    lib/uvfetch.mjs:55
    try { entries = readdirSync(dir, { withFileTypes: true }) } catch { return null }
  • 执行外部命令来自配置/变量
    lib/uvfetch.mjs:69
    const r = spawnSync(cmd, args, { stdio: 'ignore' })
  • 读取本地文件
    lib/uvfetch.mjs:83
    if (existsSync(target)) return target
  • 写入本地文件
    lib/uvfetch.mjs:85
    mkdirSync(dir, { recursive: true })
  • 删除本地文件递归
    lib/uvfetch.mjs:87
    rmSync(tmp, { recursive: true, force: true })
  • 写入本地文件
    lib/uvfetch.mjs:88
    mkdirSync(tmp, { recursive: true })
  • 发起网络请求
    lib/uvfetch.mjs:105
    const r = await fetch(u, { signal: AbortSignal.timeout(8000) })
  • 发起网络请求
    lib/uvfetch.mjs:134
    const res = await fetch(s.url)
  • 写入本地文件
    lib/uvfetch.mjs:136
    await pipeline(Readable.fromWeb(res.body), createWriteStream(s.file))
  • 读取本地文件
    lib/uvfetch.mjs:137
    const mb = (statSync(s.file).size / 1048576).toFixed(1)
  • 写入本地文件
    lib/uvfetch.mjs:154
    copyFileSync(hit, target)
  • 写入本地文件
    lib/uvfetch.mjs:155
    try { chmodSync(target, 0o755) } catch { }
  • 执行外部命令来自配置/变量
    lib/uvfetch.mjs:157
    const r = spawnSync(target, ['--version'], { stdio: 'ignore' })
  • 删除本地文件递归
    lib/uvfetch.mjs:160
    rmSync(tmp, { recursive: true, force: true })
  • 删除本地文件递归
    lib/uvfetch.mjs:168
    rmSync(tmp, { recursive: true, force: true })
  • 读取本地文件
    lib/mail.mjs:48
    const cfg = JSON.parse(readFileSync(mailConfigPath(stateDir), 'utf8'))
  • 写入本地文件
    lib/mail.mjs:69
    mkdirSync(dirname(file), { recursive: true })
  • 写入本地文件
    lib/mail.mjs:70
    writeFileSync(file, JSON.stringify(cfg ?? {}, null, 2) + '\n', 'utf8')
  • 执行外部命令固定命令
    lib/mail.mjs:84
    const r = spawnSync(
  • 读取本地文件
    lib/mail.mjs:143
    const py = existsSync(venvPy) ? venvPy : 'python'
  • 执行外部命令来自配置/变量
    lib/mail.mjs:175
    child = spawn(py, args, { cwd: String(stateDir), env, windowsHide: true })
  • 删除本地文件递归
    selfcheck.mjs:45
    try { rmSync(SANDBOX_HOME, { recursive: true, force: true }) } catch { }
  • 写入本地文件
    selfcheck.mjs:46
    mkdirSync(SANDBOX_HOME, { recursive: true })
  • 读取本地文件
    selfcheck.mjs:78
    const pkg = JSON.parse(readFileSync('./package.json', 'utf8'))
  • 删除本地文件递归
    selfcheck.mjs:169
    try { rmSync(SANDBOX_HOME, { recursive: true, force: true }) } catch { }
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-llm@deepseek-ai/dsh-tools@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DSH 插件:每天替你刷一轮 B 站 —— 读字幕原文判断、每条写结论、把这一轮的总结发邮件/写 Obsidian、推荐的进稍后再看。

README

由 DeepSeek 最新模型翻译生成
dsh-bili-scroll | 刷B站 DSH 插件:每天替你刷一轮 B 站 —— 自己搜、读字幕原文判断、每条都写结论,把这一轮的总结发到你的邮箱 / Obsidian,推荐的顺手加进「稍后再看」。 面板在右侧栏 →「刷B站」,四个标签页:功能设置 / 提示词 / 环境与账号 / 今日。 长什么样 | 功能设置 | 今日(推荐 / 不推荐 分轮次) | | 功能设置 | 今日 | | 搜索意图 / 发信门槛 / 自动续刷 | 写多细、说不说话 | | 搜索与续刷 | 写多细 | | 环境与账号:邮箱与 Obsidian(都在面板里填,不用改文件) | | 邮箱与 Obsidian | 它每天做什么 搜(按你的关键词 / 搜索意图,1~2 组词) → 捞回 N 条候选(默认 5 条,跨组去重) → 逐条读字幕原文,判断值不值得看 → 每条写一份笔记 + 一个结论(✅ 值得看 / ❌ 不值得看 + 理由) → 发一封「这一轮」的总结邮件(可选同时写 Obsidian) → 推荐的加进 B站「稍后再看」 → 待看被你看空 ⇒ 自动再刷下一轮(可关) 两个口径(这版的重点): 1. 「每轮刷几个视频」= 5,就真的看 5 条,每条都给结论 —— 不凑数、也不偷偷多刷; 2. 每轮只发这一轮的总结,不叠加:邮件一封一封来,Obsidian 一天里也按轮次分开。
展开完整文档(README 剩余 1 节)
dsh-bili-scroll | 刷B站

DSH 插件:每天替你刷一轮 B 站 —— 自己搜、读字幕原文判断、每条都写结论,把这一轮的总结发到你的邮箱 / Obsidian,推荐的顺手加进「稍后再看」。

面板在右侧栏 →「刷B站」,四个标签页:功能设置 / 提示词 / 环境与账号 / 今日。

长什么样

| 功能设置 | 今日(推荐 / 不推荐 分轮次) |
| 功能设置 | 今日 |

| 搜索意图 / 发信门槛 / 自动续刷 | 写多细、说不说话 |
| 搜索与续刷 | 写多细 |

| 环境与账号:邮箱与 Obsidian(都在面板里填,不用改文件) |
| 邮箱与 Obsidian |

它每天做什么

搜(按你的关键词 / 搜索意图,1~2 组词) → 捞回 N 条候选(默认 5 条,跨组去重) → 逐条读字幕原文,判断值不值得看 → 每条写一份笔记 + 一个结论(✅ 值得看 / ❌ 不值得看 + 理由) → 发一封「这一轮」的总结邮件(可选同时写 Obsidian) → 推荐的加进 B站「稍后再看」 → 待看被你看空 ⇒ 自动再刷下一轮(可关)

两个口径(这版的重点):

1. 「每轮刷几个视频」= 5,就真的看 5 条,每条都给结论 —— 不凑数、也不偷偷多刷;
2. 每轮只发这一轮的总结,不叠加:邮件一封一封来,Obsidian 一天里也按轮次分开。

面板有什么

右侧栏 →「刷B站」,四个标签页:

| 页 | 能做什么 |
| 功能设置 | 跑在哪(后台 / 前台)、每轮刷几个、搜索意图、排序、只看最近几天、自动评论 / 回复 / 点赞、本地转写、自动续刷 |
| 提示词 | 主题、人设、篇幅;改完即时生效 |
| 环境与账号 | 装依赖、扫码登录 B站、配邮箱(授权码)、配 Obsidian、看产物 / 打开家目录 |
| 今日 | 今天刷到的视频:推荐列表 / 不推荐,各自按「第 N 轮」分层;可新建文件夹、拖动归类、深挖写详细笔记、删除;底部是「本次跳过」 |

邮件与 Obsidian(可选)

- 邮箱:QQ 邮箱用「授权码」而不是登录密码(设置页有图文步骤)。
面板「环境与账号 → 邮箱」里填发件邮箱 / 授权码 / 收件人,点「发一封测试」验证。
- Obsidian:填库路径(面板有「自动探测」),产物写到 <库>/B站日报/<日期>/round-<HHMM>.md。
不用 Obsidian 也完全没问题 —— 两个都是可选,不填就不发 / 不写。

详细步骤:docs/配置指南.md

待看与自动续刷

- 推荐的视频会被加进你 B站的「稍后再看」(开关在「功能设置」)。
- 「稍后再看」被清空 ⇒ 判定你看完了 ⇒ 自动再刷一轮。
- 间隔默认 5 分钟;「最多续刷几轮」填 0 = 不限;
- 一轮里一条推荐都没加时不会触发续刷(否则会空转烧钱);
- 同一时间只允许一轮在跑(重复点「现在跑一轮」会被挡掉)。

在哪打开

装好、重启之后:

1. 右侧栏顶部有一排标签 —— 点 「刷B站」(不在「设置」里,这是最容易找不到的地方);
2. 打开后是四个标签页:功能设置 / 提示词 / 环境与账号 / 今日;
3. 第一次用先走 「环境与账号」:装依赖 → 扫码登录 →(可选)配邮箱 / 配 Obsidian;
4. 然后回 「功能设置」 调「每轮刷几个视频」,或直接点右上角 「现在跑一轮」。

邮箱和 Obsidian 都在 「环境与账号」 页里填,不需要改任何文件;不填就只用「今日列表 + 稍后再看」。

装

需要 DSH ≥ 0.1.7-rc.1,装完重启一次(插件在 bundle 层组装,重载页面不算)。

把仓库放到:<DSH_HOME>/profiles/desktop/node_modules/dsh-bili-scroll 重启 DSH → 右侧栏出现「刷B站」→ 环境与账号 → 装依赖 / 扫码登录

- 依赖镜像:内置安装脚本用清华源(部分地区 403)。装不动时把环境变量 BILI_DUTY_PIP_MIRROR 指到别家(如 https://mirrors.aliyun.com/pypi/simple)。
- 没字幕的视频默认跳过;要本机转写需额外下 Whisper 模型(几百 MB ~ 1 GB)。

数据在哪

| 内容 | 路径 |
| 配置 | <DSH_HOME>/bili-duty/config.json |
| 今日列表 | <DSH_HOME>/bili-duty/today/<日期>.json |
| 每条视频的笔记 | <DSH_HOME>/bili-duty/reports/<标题>-<YYMMDD>.md |
| 每轮的总结(邮件正文同源) | <DSH_HOME>/bili-duty/out/<日期>/round-<HHMM>.md |
| 运行日志 | <DSH_HOME>/bili-duty/duty.log |
| 判重表 | <DSH_HOME>/bili-duty/seen.md |

删掉某条笔记的 .md,那条视频也会从「今日」列表里消失(列表以磁盘为准)。

常见问题

- 设置页里找不到「刷B站」:它在右侧栏,不在设置列表里。
- 没收到邮件:先看「环境与账号 → 邮箱」的发测试结果,再看 duty.log 里有没有 发信成功 / 发信跳过:邮箱没开。
- 面板一直显示「正在后台运行」:单轮有 45 分钟上限;真卡住时看日志最后几行。
- 点了「现在跑一轮」没反应:多半是上一轮还没结束(会提示"上一轮还在跑")。

这版从哪来

两层上游,都是 MIT 许可:

| 层 | 仓库 | 作者 |
| 初版 | c1overzz/dsh-bili-scroll | @凌羽clover |
| 分支 | jojoman2024/dsh-bili-scroll | @闲人JOJO |
| 这一支 | LittlefallenStar/dsh-bili-scroll | 本仓库 |

- 初版给了整个骨架:定时跑一轮 → 搜视频 → 读字幕原文 → 写笔记 → 发信。
- 分支(JOJO 的)加了:右侧栏入口、前台会话里跑任务、搜索排序筛选、单条深挖落档、插件工具与对模型行为的硬校验。
- 这一支在分支的 0.1.4 之上再做:三种反馈端(QQ 邮箱 / Obsidian / 稍后再看)、三层搜索(关键词 / 主题 / 搜索意图)、评分与文件夹分级、笔记详略可选、可选自动点赞(只点赞)、待看清空自动续刷、单轮闸、跳过留痕。

- 逐版变动:CHANGELOG.md
- 为什么这么改(含踩过的坑):docs/开发日志.md

License

MIT,保留上游版权声明:Copyright (c) 2026 dsh-bili-duty contributors。
本仓库的修改部分同样以 MIT 发布,完整条款见 LICENSE。
预览分享卡片长什么样 ↓littlefallenstar/dsh-bili-scroll
分享 · DeepSeek Harness Hub
littlefallenstar/dsh-bili-scroll

每天自动刷一轮B站并写结论,推荐视频进稍后再看

这是你的仓库?认领条目

回到顶部