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

B站互动助手 acttk/dsh-bili-interactor

DeepSeek 客户端
acttk11 天前有提交已提供中文文档扫描:含敏感能力兼容 / 相关生态

DSH 插件:让 AI 替你逛 B站 并真的产生互动 —— 点赞 / 投币 / 弹幕 / 评论 / 回评论 /…

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

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

相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/acttk/dsh-bili-interactor.git

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:待复验
是什么[目录]—
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
暂无时间戳·判据 →
装得上吗[实装验证]—
曾在 dsh 0.2.1-rc.2 下真实安装成功,但当前 dsh 已更新至 0.2.2-rc.1,本站尚未在新版下复验
L4 · 真实安装等级说明 →
数据截至 2026/10/26·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/06·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 11 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件写入剪贴板(不计风险)读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 65 处,展示前 55 条)
  • 读取本地文件
    lib/index.js:58
    try { return JSON.parse(readFileSync(join(PKG_DIR, 'package.json'), 'utf8')).version } catch { return '' }
  • 读取本地文件
    lib/index.js:67
    try { lines = readFileSync(f, 'utf8') } catch { }
  • 写入本地文件
    lib/index.js:71
    writeFileSync(f, arr.join('\n') + '\n', 'utf8')
  • 写入本地文件
    lib/index.js:76
    try { writeFileSync(liveFile(home), '', 'utf8') } catch { }
  • 读取本地文件
    lib/index.js:123
    const dirs = readdirSync(root)
  • 读取本地文件
    lib/index.js:134
    for (const f of readdirSync(r).filter((x) => /^python3(\.\d+)?$/.test(x)).sort().reverse()) {
  • 执行外部命令来自配置/变量
    lib/index.js:150
    const out = execFileSync(cmd, args, { timeout: 15_000, encoding: 'utf8', windowsHide: true })
  • 执行外部命令来自配置/变量
    lib/index.js:162
    execFileSync(cmd, ['-c', PY_DEP_PROBE], { timeout: 20_000, windowsHide: true })
  • 删除本地文件
    lib/index.js:237
    try { unlinkSync(join(home, 'login.json')) } catch { }
  • 写入本地文件
    lib/index.js:346
    if (b64) writeFileSync(join(home, 'qr.png'), Buffer.from(b64, 'base64'))
  • 写入本地文件
    lib/index.js:395
    mkdirSync(shared, { recursive: true })
  • 删除本地文件
    lib/index.js:407
    try { unlinkSync(join(home, 'qr.png')) } catch { }
  • 删除本地文件
    lib/index.js:408
    try { unlinkSync(join(home, 'login.json')) } catch { }
  • 读取本地文件
    lib/index.js:1554
    return existsSync(own) && statSync(own).size > 20
  • 读取本地文件
    lib/index.js:1554
    return existsSync(own) && statSync(own).size > 20
  • 执行外部命令来自配置/变量
    lib/index.js:1599
    child = spawn(cmd, args, { windowsHide: true, env: { ...process.env, PIP_DISABLE_PIP_VERSION_CHECK: '1' } })
  • 删除本地文件
    lib/index.js:2006
    if (existsSync(f)) { unlinkSync(f); removed.push(f) }
  • 写入本地文件
    lib/index.js:2333
    writeFileSync(learnedFile(home), keep.map((e) => JSON.stringify(e)).join('\n') + (keep.length ? '\n' : ''), 'utf8')
  • 写入剪贴板
    client.js:43
    await navigator.clipboard.writeText(t)
  • 发起网络请求
    client.js:198
    const r = await fetch(API + '/state', { credentials: 'same-origin' })
  • 发起网络请求
    client.js:210
    const r = await fetch(API + '/doctor', { credentials: 'same-origin' })
  • 发起网络请求
    client.js:223
    const r = await fetch(API + '/setup/deps', { method: 'POST', credentials: 'same-origin' })
  • 发起网络请求
    client.js:235
    const r = await fetch(API + '/setup/status', { credentials: 'same-origin' })
  • 发起网络请求
    client.js:248
    const r = await fetch(API + '/visibility', { credentials: 'same-origin' })
  • 发起网络请求
    client.js:261
    const r = await fetch(API + '/learned', { credentials: 'same-origin' })
  • 读取本地文件
    lib/state.js:39
    export const readText = (f) => { try { return readFileSync(f, 'utf8').replace(/^ FEFF/, '') } catch { return '' } }
  • 读取本地文件
    lib/state.js:41
    export const exists = (f) => { try { return existsSync(f) } catch { return false } }
  • 写入本地文件
    lib/state.js:44
    try { writeFileSync(f, JSON.stringify(obj, null, 2), 'utf8'); return true } catch { return false }
  • 写入本地文件
    lib/state.js:52
    try { mkdirSync(home, { recursive: true }) } catch { }
  • 读取本地文件
    lib/state.js:69
    if (!existsSync(file)) return false
  • 读取本地文件
    lib/state.js:70
    if (statSync(file).size <= maxBytes) return false
  • 读取本地文件
    lib/state.js:71
    const lines = readFileSync(file, 'utf8').split(/ ? /).filter(Boolean)
  • 写入本地文件
    lib/state.js:73
    writeFileSync(file, lines.slice(-keepLines).join('\n') + '\n', 'utf8')
  • 写入本地文件
    lib/state.js:92
    appendFileSync(f, `${new Date().toISOString()} ${msg}\n`, 'utf8')
  • 写入本地文件
    lib/state.js:221
    appendFileSync(f, JSON.stringify({ ts: localIso(), ...row }) + '\n', 'utf8')
  • 读取本地文件
    lib/state.js:267
    try { mtime = statSync(liveFile(home)).mtime.toISOString() } catch { }
  • 写入本地文件
    lib/state.js:272
    try { ensureHome(home); writeFileSync(liveFile(home), '', 'utf8'); return true } catch { return false }
  • 读取本地文件
    lib/ignore.js:26
    if (!existsSync(f)) return {}
  • 读取本地文件
    lib/ignore.js:28
    const o = JSON.parse(String(readFileSync(f, 'utf8') || '{}'))
  • 写入本地文件
    lib/ignore.js:37
    mkdirSync(dirname(ignoredFile(home)), { recursive: true })
  • 写入本地文件
    lib/ignore.js:38
    writeFileSync(ignoredFile(home), JSON.stringify(map, null, 2), 'utf8')
  • 读取本地文件
    lib/danmaku.js:26
    const txt = readFileSync(f, 'utf8')
  • 读取密钥环境变量
    lib/danmaku.js:27
    if (/DEEPSEEK_API_KEY/.test(txt) && process.env.DEEPSEEK_API_KEY) return process.env.DEEPSEEK_API_KEY
  • 读取密钥环境变量
    lib/danmaku.js:31
    return process.env.DEEPSEEK_API_KEY || ''
  • 请求外部主机api.deepseek.com
    lib/danmaku.js:40
    const res = await fetch('https://api.deepseek.com/chat/completions', {
  • 发起网络请求
    lib/danmaku.js:40
    const res = await fetch('https://api.deepseek.com/chat/completions', {
  • 读取本地文件
    lib/learn.js:26
    if (!existsSync(f)) return []
  • 读取本地文件
    lib/learn.js:28
    for (const line of String(readFileSync(f, 'utf8') || '').split(/ ? /)) {
  • 写入本地文件
    lib/learn.js:47
    mkdirSync(dirname(learnedFile(home)), { recursive: true })
  • 写入本地文件
    lib/learn.js:59
    writeFileSync(learnedFile(home), next.map((e) => JSON.stringify(e)).join('\n') + '\n', 'utf8')
  • 写入本地文件
    lib/learn.js:64
    appendFileSync(
  • 写入本地文件
    lib/learn.js:143
    writeFileSync(learnedFile(home), keep.map((e) => JSON.stringify(e)).join('\n') + '\n', 'utf8')
  • 发起网络请求
    lib/login.mjs:55
    const r = await fetch(SPI, { headers: { 'User-Agent': UA } })
  • 发起网络请求
    lib/login.mjs:72
    const r = await fetch(GEN, { headers: { 'User-Agent': UA } })
  • 发起网络请求
    lib/login.mjs:88
    const res = await fetch(pollUrl(key), {
扫描于 2026/11/6(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
涉及外部主机:api.deepseek.com

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

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
dsh-bili-interactor 让 AI 替你在 B站 上真的产生互动 —— 刷视频、点赞、投币、发弹幕、发评论、回评论,以及别人回你之后接着聊。 一个 DSH(DeepSeek Harness)插件。在 设置 → B站互动 里操作,不用另开网页。 用的是你自己的账号。 点赞会亮、投币会扣、评论会挂在视频下、关注会被人看见。 默认参数刻意保守,请自己控制量 —— 大量重复操作很可能被 B站 判定为异常并折叠、限流或封禁。 详见文末的风险与免责。 它做什么 - 刷视频:按关键词搜索,粗筛掉广告/抽奖类内容,同一个 UP 主一轮内限量 - 互动:点赞 / 投币 / 收藏 / 发弹幕 / 关注,每项独立成败,互不影响 - 发评论:给视频发一条新评论,可以 @ 指定的人 - 读内容再说话:先取视频的 B站 AI 字幕(没有就本地转写,再没有就看弹幕),所以评论说的是视频里真正讲了什么 - 回评论:从别人的评论里挑「值得接话」的回 —— 挑之前也会先看一遍视频内容,判断才准;纯情绪、复读、广告不选,挑不出来就不回 - 接着回:后台定时检查自己发过的评论,有人回了就接着聊 —— 条数可设上限,也可设成不限 - 聊太多就撤:跟同一个人在同一个视频下来回聊到一定轮数,会先「审查」这段对话有没有营养、对方像不像真人。
展开完整文档(README 剩余 1 节)
dsh-bili-interactor

让 AI 替你在 B站 上真的产生互动 —— 刷视频、点赞、投币、发弹幕、发评论、回评论,以及别人回你之后接着聊。

一个 DSH(DeepSeek Harness)插件。在 设置 → B站互动 里操作,不用另开网页。

用的是你自己的账号。 点赞会亮、投币会扣、评论会挂在视频下、关注会被人看见。
默认参数刻意保守,请自己控制量 —— 大量重复操作很可能被 B站 判定为异常并折叠、限流或封禁。
详见文末的风险与免责。

它做什么

- 刷视频:按关键词搜索,粗筛掉广告/抽奖类内容,同一个 UP 主一轮内限量
- 互动:点赞 / 投币 / 收藏 / 发弹幕 / 关注,每项独立成败,互不影响
- 发评论:给视频发一条新评论,可以 @ 指定的人
- 读内容再说话:先取视频的 B站 AI 字幕(没有就本地转写,再没有就看弹幕),所以评论说的是视频里真正讲了什么
- 回评论:从别人的评论里挑「值得接话」的回 —— 挑之前也会先看一遍视频内容,判断才准;纯情绪、复读、广告不选,挑不出来就不回
- 接着回:后台定时检查自己发过的评论,有人回了就接着聊 —— 条数可设上限,也可设成不限
- 聊太多就撤:跟同一个人在同一个视频下来回聊到一定轮数,会先「审查」这段对话有没有营养、对方像不像真人。判定没营养(比如两边都是 AI 在互相捧场)就发最后一句表明不再聊,之后在这个视频下不再回复他
- 跳过刷过的:记住刷过哪些视频,之后不再重复推同一条(可关)
- 学习说话规律:不是抄别人的句子,而是从真人评论里总结「怎么说话才像真人」的可执行规律,跑得越多 AI 味越淡
- 都看得见:面板里能查到它说过什么、在哪些视频下说过、哪些评论真的被别人看到了、有多少条别人根本刷不到

三种「说」要分清,面板里也这么标:

| 标签 | 含义 | 谁先开口 |
| 评论 | 我在视频下发的新评论 | 我 |
| 回评论 | 别人发了评论,我去接他的话 | 别人 |
| 接着回 | 别人回的是我发过的评论,我接着聊 | 别人(冲我来的) |

设置里改任何一项都是立刻保存、立刻生效的,不需要重启 DSH。设置页顶部有一条常驻状态条告诉你存没存上。
「现在跑一轮」如果正好撞上后台监听在跑,会排队等它结束再自动开始,不用你反复点。

截图

图里是演示数据,不是真实账号内容。

总览 —— 今天动了多少次、额度用了多少、这一轮在干什么

总览

它说了什么 —— 每条原文都在,可跳到对应楼层、可检查是否真的公开

它说了什么

碰过的视频 —— 每条视频下我说过什么,带直达链接

碰过的视频

另外三页(记忆 / 过程 / 设置)

记忆 —— 学到了什么、几分、为什么记、从哪来

记忆

过程 —— 这一轮的实时实录,包括为什么跳过某条

过程

设置 —— 全部开关和限额

设置

环境要求

| 需要什么 | 必须吗 | 用途 | 大小 |
| DSH(Desktop 版,带插件系统) | 必须 | 宿主 | — |
| Python 3.10+ + bilibili-api-python httpx qrcode pillow | 必须 | 调 B站 接口、渲染登录二维码 | ~100MB |
| 一个 B站 账号(建议小号) | 必须 | 干活的那个号 | — |
| DeepSeek API key | 可选 | 有 key 才按人设说话;没有就退回内置模板 | — |
| 本地转写环境(Whisper) | 绝大多数人不需要 | 只有连 AI 字幕都没有的视频才用得上 | 700MB~1.5GB |

关于「它怎么知道视频在说什么」

它读的是文字,不是画面:模型拿到的是视频的字幕文本,不解码画面、不听声音。

好消息是——大多数视频都有字幕,不需要下载任何东西。B站的 AI 字幕(ai-zh)覆盖很广,插件调 player/info 接口就能拿到,实测 4 个不同类型的视频全都有:

| 视频 | 字幕条数 | 语言 |
| 部署教程 | 1 | ai-zh 中文 |
| 官方 MV | 12 | zh-CN / zh-Hans / zh-Hant … |
| 748 集课程 | 1 | ai-zh 中文 |
| 大肥鱼整活 | 8 | ai-zh / ai-en / ai-ja |

四层降级:

| 层 | 手段 | 条件 | 要装东西吗 |
| ① | B站 字幕(ai-zh 优先) | 大多数视频都有 | 不要 |
| ② | 本地 Whisper 转写(py/asr.py) | 连 AI 字幕都没生成的极少数视频 | 要,~500MB 模型 |
| ③ | 弹幕池 | 永远可用。观众会把重点和坑打在屏幕上 | 不要 |
| ④ | 只有标题/简介 | 上面都没有时。过程实录里会写明「只有标题」 | 不要 |

默认只用 ①③④,不下载任何东西。 第 ② 层是给你想覆盖「连字幕都没有」那种视频时用的,默认关闭,不装也完全不影响正常使用。

DeepSeek API key 是可选的:有 key 时评论/回复由模型按你的人设生成;没有 key 会退回内置模板,人设不生效(面板顶部会提示)。

安装

从插件市场装(推荐)

在 DSH 的插件市场里搜 B站互动 或 dsh-bili-interactor,点安装。

或者直接一条命令:

dsh plugin --profile desktop add github:acttk/dsh-bili-interactor

市场条目里没有锁版本 —— 安装时直接 clone 仓库的 main 分支,所以你拿到的是安装那一刻的最新代码。

装完第一件事:让它自己检查环境

面板顶部会自动做一次环境自检,缺什么直接列出来,带一个「一键装依赖」按钮(会自动建虚拟环境并 pip install,不用你手动敲命令)。

如果你更喜欢手动:

cd ~/.dsh
python -m venv bili-interactor/.venv
Windows:
bili-interactor/.venv/Scripts/pip install bilibili-api-python httpx qrcode pillow
macOS / Linux:
bili-interactor/.venv/bin/pip install bilibili-api-python httpx qrcode pillow

插件按这个顺序找解释器:配置项 pythonPath → ~/.dsh/bili-interactor/.venv → ~/.dsh/bili-duty/.venv(和另一个插件共用的兼容路径) → PATH 上的 python。
正常情况下你不用管这个,自检会告诉你找到的是哪个。

可选:装本地转写(大多数人不用装)

先看情况再决定:

- 视频有 B站 字幕(大多数都有,包括 AI 字幕)→ 什么都不用装,插件直接读
- 视频连 AI 字幕都没有(纯音乐、无声录屏、少数冷门视频)→ 才需要这一层

要装的话:

在仓库根目录跑,会自动建 ~/.dsh/bili-interactor/.venv-asr 并预热模型 Windows: powershell -ExecutionPolicy Bypass -File scripts/setup-asr.ps1 macOS / Linux: bash scripts/setup-asr.sh

想更准可以换模型(tiny / base / small / medium,默认 small) powershell -ExecutionPolicy Bypass -File scripts/setup-asr.ps1 medium

装完去设置里打开 「没字幕才本地转写」。

模型走 hf-mirror.com 国内镜像,不用梯子。第一次跑会加载模型(几十秒),之后就是本地读。
如果本机已经装了「刷B站」插件,它的转写环境会被自动复用,不用重复装。

手动装进 profile(只有从源码开发时才需要)

从市场装的话跳过这一节。

2. 装进 profile
cd ~/.dsh/profiles/desktop
pnpm add link:<本仓库路径>

3. 让 profile 加载它:cordis.patch.yml 末尾加上
- insert:
- id: bili-interactor
name: dsh-bili-interactor

装完重启一次 DSH(首次要构建前端 bundle),之后改代码只需刷新页面。

第一次用

1. 打开 设置 → B站互动
2. 点 扫码登录,面板里会直接出二维码
3. 手机 B站 App → 右上角扫一扫 → 点「确认登录」
4. 面板变成「已登录」,就能用了

二维码 180 秒有效,面板里有倒计时。没扫完就离开页面也没关系,宿主在后台继续轮询,扫上了会自动变成已登录。

登录成功的凭证存在 ~/.dsh/bili-interactor/credential.json(含 SESSDATA,别外传、别提交)。

面板

| 页签 | 能看什么 |
| 总览 | 今天动了几次、剩多少额度、投币数、上一轮结果;可见性告警(有多少条别人看不到);可以手动「现在跑一轮」;按时间范围批量查可见性 |
| 它说了什么 | 评论、回评论、接着回、私信的全部原文;带「跳到这一楼」和「复制正文」;每条都标了「公开 / 仅自己可见 / 查不到」 |
| 碰过的视频 | 今天碰过的视频卡片:标题、UP、各种动作次数、我在这条下说过的话(带直达);可筛「我说过话的」 |
| 不再回复的人 | 聊太多被判定没营养之后记下来的人:名字、聊了几轮、原因、视频链接;可逐个「恢复回复」或全部清空 |
| 记忆 | 学到的说话规律(不是别人原话)、分数、为什么记、来源;可单条删除、可手动添加 |
| 过程 | 这一轮的实时实录:在搜什么、挑了哪条、为什么跳过、失败原因、审查结果 |
| 设置 | 全部开关和限额;顶部有常驻保存状态条 |

可见性检查按楼分组查,不是按条查 —— 一个楼只发 2 次请求就能判断这个楼里我所有评论的可见性,比按条查省 6 倍请求,不容易触发风控。

配置

配置存在 ~/.dsh/bili-interactor/config.json,也可以直接在面板「设置」里改。所有上限填 0 都是不限。

额度

| 键 | 默认 | 说明 |
| enabled | true | 总开关 |
| maxVideosPerRun | 5 | 一轮刷几条视频(你真正想调的那个) |
| maxActionsPerRun | 20 | 一轮最多动几次(点赞/投币/弹幕/评论/回复全算),是护栏 |
| maxActionsPerDay | 120 | 一天最多动几次(管「跑一轮」,不含监听回复) |

三个数字别搞混:maxVideosPerRun × (2 + replyCount) 才是一轮大约的动作数。
比如每轮刷 5 条、每条跟 2 个人搭话 → 一条视频约 4 个动作 → 一轮约 20 个,正好等于 maxActionsPerRun。超了就会被护栏拦住,「刷几条视频」根本轮不完 ——设置页会直接把这两个数算给你看,超了变黄字提醒。

动作

| 键 | 默认 | 说明 |
| doLike / doCoin / doDanmaku | true | 点赞 / 投币 / 发弹幕 |
| doDigest | true | 先摘视频内容(字幕/弹幕)再说话,评论才不会只吐槽标题 |
| doTranscribe | false | 没字幕时用本地 Whisper 转写(准但慢,一条 1~2 分钟,需装转写环境) |
| doWatch | false | 上报观看进度。这是在刷播放数据,默认关,容易被识别 |
| watchStyle | fast | fast 几秒上报完;real 按真实节奏走完(更慢但更像真人) |
| doFavorite / favoriteId | false / 0 | 收藏,需要填收藏夹 ID |
| doFollow | false | 关注 UP(最容易被人发现,默认关) |
| coinPerVideo | 1 | 每条投几个币 |
| actionIntervalMs | [1500, 4000] | 两次动作之间的随机间隔 |

选视频

| 键 | 默认 | 说明 |
| keywords | ["恐怖游戏","游戏解说"] | 搜什么 |
| order | click | click 按播放 / pubdate 按最新 / totalrank 综合 |
| daysBack | 7 | 太老的不碰,0 = 不限。服务端筛,不是本地事后过滤 |
| minPlay | 1000 | 播放量下限 |
| maxPerUpPerRun | 2 | 同一个 UP 一轮最多碰几条 |
| skipKeywords | 见默认值 | 标题命中就跳过 |
| skipSeenVideos | true | 跳过刷过的视频,不再重复推同一条 |

daysBack 交给 B站 服务端筛(time_start / time_end),不是下载 42 条再本地砍。
这点很关键:按播放排序返回的天然是历史爆款,本地砍完必然剩 0 —— 会表现为「这轮空手」。
另外 time_range 参数筛的是视频时长,不是发布时间,别搞混。

评论

| 键 | 默认 | 说明 |
| doComment | true | 发新评论 |
| doReplyComment / replyCount | true / 2 | 回别人的评论;每条视频最多跟几个人搭话(是人数,不是句数) |
| mentionUid | 0 | @ 谁(填 UID),0 = 不 @ |
| persona / commentPersona | 见默认值 | 人设提示词,写多长都行 |

接着回(回复监听)

| 键 | 默认 | 说明 |
| doReplyBack | true | 开关 |
| replyBackMax | 0 | 每条评论下最多回几句,0 = 不限 |
| replyBackPerDay | 0 | 一天最多回几条,0 = 不限 |
| replyBackMinLen | 2 | 对方回复太短就不理 |
| listenIntervalMin | 1 | 每几分钟查一次 |
| listenMaxThreadsPerTick | 15 | 每次最多看几条「我发过的评论」(多了轮流) |
| listenLookbackHours | 72 | 只往回看多少小时内自己发的评论 |
| deepTalkLimit | 10 | 跟同一个人在同一视频下来回聊到这么多轮就审查;判定没营养就发最后一句后不再回复他。0 = 关掉 |

listenMaxThreadsPerTick 直接决定请求频率:填 20 就是每分钟最多 20 次请求。
楼很多时它会轮流看,几轮转完一圈,不会漏。

「查几楼」和「隔几分钟」要一起调:两个乘起来决定「多久能发现新回复」,除起来决定「每分钟发多少请求」。楼多了之后建议 20 楼 / 5 分钟,一圈约 1 小时、每分钟 4 次请求 —— 比 50 楼 / 2 分钟(每分钟 25 次)稳得多。

学习

| 键 | 默认 | 说明 |
| doLearn | true | 开关 |
| learnPerRun | 3 | 一轮最多记几条 |
| learnUseCount | 8 | 说话时参考几条 |
| learnMinScore | 6 | 低于这个分不记(0~10) |
| learnPrompt | 见默认值 | 你自己写的标准,会原样交给模型 |

它记的是规律,不是别人的原话。 分两类:

| 类型 | 是什么 | 怎么用 |
| 规律(rule) | 可执行的写法,如「先甩结论再补理由,别铺垫」 | 下次写评论时必须照着做 |
| 例句(quote) | 别人的原话 | 只用来感受语感,一个字都不许照抄 |

为什么这样设计:以前是「从评论区挑出说得好的句子存起来」,结果模型只会模仿那些句子,写出缝合怪 —— 记的是「别人说了什么」,不是「怎么说话」。现在改成从真人评论里提炼「怎么说话才像真人」的可执行规律(真人的回复短、有情绪、会跑题、只说半句; AI 的回复工整、面面俱到、爱总结、爱升华),跑得越多 AI 味越淡。

旧数据(没有 kind 字段)会自动当成「例句」处理,不会丢。

数据文件

全部在 ~/.dsh/bili-interactor/:

credential.json 登录凭证(含 SESSDATA,别外传) config.json 配置 ledger.jsonl 一行一个动作(超过 3MB 自动只留最近 2000 行) learned.jsonl 学到的规律/例句,一行一条 replied.json 已回过的子评论(防重复回) seen.json 刷过的视频(跳过用,最多留 3000 条) ignored.json 不再回复的人(按 视频+用户 记) visibility.json 哪些评论是「别人能看到」的 daily.json 当日计数 live.md 过程实录 interact.log 运行日志

命令行

py/interact.py 可以单独用,全部输出 JSON:

PY=~/.dsh/bili-interactor/.venv/Scripts/python # macOS/Linux: .venv/bin/python3

$PY py/interact.py whoami
$PY py/interact.py search --keyword 恐怖游戏 --order click --limit 10 $PY py/interact.py comments --bvid BV1xxxxxxx --order time --limit 20 $PY py/interact.py act --bvid BV1xxxxxxx --like --coin 1 --danmaku "这波可以" $PY py/interact.py comment --bvid BV1xxxxxxx --text "……"
$PY py/interact.py sub-replies --bvid BV1xxxxxxx --rpid 123456
$PY py/interact.py visible --bvid BV1xxxxxxx --rpid 123456
$PY py/interact.py digest --bvid BV1xxxxxxx # 摘视频内容(字幕/弹幕/简介) $PY py/interact.py transcribe --bvid BV1xxxxxxx # 本地转写(慢,要装转写环境) $PY py/interact.py watch --bvid BV1xxxxxxx # 上报观看(会产生观看记录)

登录走宿主(lib/login.mjs),凭证在 Set-Cookie 响应头里。

代码结构

lib/index.js 宿主:HTTP 路由、调度、回复监听、审查、记账 lib/login.mjs 扫码登录(Node 侧,从 Set-Cookie 取凭证) lib/targets.js 搜索、粗筛、挑目标 lib/danmaku.js 文案生成(评论/回复/弹幕/审查/告别)、学习提炼 lib/learn.js 说话规律的读写、去重、淘汰 lib/seen.js 刷过的视频(跳过用) lib/ignore.js 不再回复的人(纯本地,不做任何 B站 拉黑) lib/state.js 配置、账本、当日额度、本地时间 py/interact.py 执行层:只调 B站 接口,只干活不判断 py/asr.py 本地转写(Whisper,把没字幕的视频读成文字) client.js 设置页面前端

写盘全部在 Node 侧,Python 只负责联网 —— DSH 沙箱下子进程往往写不进 ~/.dsh/<插件名>。
这条边界由 tests/test_login.py 断言(它会监视每一次写盘尝试)。

测试

node smoke.mjs # 前端渲染、七个页签、跳转链接
node smoke-host.mjs # 宿主路由、状态、拒绝路径

契约与界面规则(这几条是踩过坑之后补的,别删)
node tests/test_state_serializable.mjs # /state 必须永远能序列化(Timer 会挂死接口)
node tests/test_hooks_strict.mjs # 真 React 的 hooks 顺序(放错位置整块面板崩)
node tests/test_hooks_order.mjs # hooks 不能在提前 return 之后
node tests/test_backnow.mjs # 「立刻检查一次」的返回契约
node tests/audit_contract.mjs # 全量交叉检查:配置项/接口/开关有没有没闭环的

功能
node tests/test_no_reply.mjs # 聊太多不再回复(作用域、轮数统计)
node tests/test_visibility_scan.mjs # 可见性按楼分组、时间窗过滤
node tests/test_vis_busy.mjs # 可见性扫描的忙判断(查过一次还能再查)
node tests/test_seen.mjs # 跳过刷过的视频
node tests/test_reply_select.mjs # 挑评论兜底:按信息量不按字数
node tests/test_reply_pick.mjs # 「值得接话」的筛选
node tests/test_learn_rule.mjs # 学习:规律去重、例句不挤掉规律
node tests/test_learn_mention.mjs # @ 去重、记忆读写
node tests/test_dedupe.mjs # 同一个楼不重复回
node tests/test_digest.mjs # 视频内容摘取
node tests/test_login_flow.mjs # 扫码 → 自动登录 → 凭证落盘 → 界面变已登录
node tests/test_cookie_parse.mjs # 从 Set-Cookie 取凭证
node tests/test_qr_ttl.mjs # 二维码有效期预算
node tests/test_scan_then_expire.mjs # 扫了没确认就过期
node tests/test_proactive_refresh.mjs # 主动换码

python tests/test_comment_result.py # 评论结果判定(含 12014 频率上限)
python tests/test_login.py # Python 侧零写盘

需要插件正在运行(真实端到端)
python tests/probe_endpoints.py http://127.0.0.1:<端口>
python tests/probe_userpath.py http://127.0.0.1:<端口>

已知限制

- 弹幕收不回(B站 限制:发出后 2 分钟内、每天 5 条),写歪了只能手动删
- 评论可能只有你自己看得见:code: 0 只代表 B站 收下了。新号、敏感内容、短时间大量评论会被折叠或送审 ——面板的「可见性」卡片就是查这个:选个时间范围(1 小时 / 24 小时 / 3 天 / 全部),立刻把这段时间里所有评论的可见性过一遍,列出哪些别人根本刷不到。别以为发出去了别人就能看到
- 被折叠多半是内容问题,不是频率问题:实测被折叠的评论几乎都是攻击性言论。
降频率救不了这个,改内容才行 —— 毒舌可以,骂人不行
- 有频率上限:短时间内发太多评论会返回 12014,这一轮会自动停下
- 有风控:密集写操作可能返回 -412 / -352 / -101
- 它「看」视频的方式是读字幕文本,不是看画面:拿 B站 字幕(ai-zh 优先)当材料,没有字幕时可以用本地 Whisper 转写,再没有就靠弹幕池 —— 它不会解码画面、也不听声音
- 它不上报观看(默认):不会给视频刷播放量。开了「上报观看」才会,那属于刷数据,风险自担
- 没有定时「跑一轮」:只有手动触发和回复监听(写操作要你亲手按)
- 圈子刷久了会干:同一个小圈子(比如某个关键词)就那么几条视频,刷过之后「跳过刷过的」会把它们全筛掉,表现为「这轮空手」。这不是 bug ——加新关键词、把「只看最近几天」调大、或清掉已刷记录就能解决

风险与免责

- 这是非官方工具,使用的是网页端接口。B站 可能随时调整接口或提高风控等级。
- 请不要用它刷量、发广告、引战、批量骚扰。这类行为违反 B站 社区规则,可能导致账号被限制或封禁。
- 自动化操作本身就有被判定为异常的风险。建议用小号,并且把各项上限设在合理范围。
- 使用者需自行承担使用本工具的一切后果。作者不对账号受限、内容被删、数据丢失等任何损失负责。
- 项目仅供学习和个人研究使用。

License

MIT
预览分享卡片长什么样 ↓acttk/dsh-bili-interactor
分享 · DeepSeek Harness Hub
acttk/dsh-bili-interactor

DSH 插件:让 AI 替你逛 B站 并真的产生互动 —— 点赞 / 投币 / 弹幕 / 评论 / 回评论 /…

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部