JianHeShui/dsh-douyin

dsh-douyin

Douyin toolkit for DeepSeek Harness: hot list, search, video reading with native vision frames, guarded Playwright DM/group driver, and a local HTTP API. Linux adapter included.

미분류deepseek-harnessdouyinhttp-api

dsh-douyin

把抖音接进 DeepSeek Harness:热榜、搜索、视频内容理解、私信/群聊,全部作为 DSH 的一等公民工具,另附一个可独立调用的本地 HTTP API。

基于 SakuraMat0u/dsh-douyin-toolkit(MIT)改造:
增加了 Linux/headless 适配、私信与群聊驱动、视频下载与抽帧、本地 HTTP API,并把所有服务器路径参数化。

English summary

A Douyin toolkit for DeepSeek Harness (DSH) and any HTTP client. It reads the hot list, searches videos, downloads videos and extracts frames for vision models, and drives the web DM/group chat through Playwright — with dry-run on by default and three independent gates before anything is actually sent. Based on SakuraMat0u/dsh-douyin-toolkit (MIT); this fork adds Linux/headless support, an IM driver, media download, and a local HTTP API.

目录

  • 这是什么
  • 特性
  • 和上游的关系
  • 架构
  • 环境要求
  • 安装
  • 登录
  • 快速开始
  • 配置
  • 私信安全模型
  • 风险与合规
  • 常见问题
  • 目录结构
  • 开发
  • 贡献
  • 许可与致谢

这是什么

一个 DSH 插件(Cordis Host 插件,工具直接注册到 ctx.tools,不是 MCP server),外加一组可以单独调用的 Python 脚本。

它解决四件事:

  1. 读得动:热榜、搜索、视频详情、用户主页、评论。
  2. 看得懂:视频下载 → ffmpeg 抽帧 → 交给支持视觉的模型(比如 DeepSeek

flash 的原生视觉),不需要自己实现视频理解。

  1. 说得上话:通过 Playwright 驱动抖音网页版,私信单个用户、给群聊发消息。
  2. 接得住:所有能力都能通过本地 HTTP API(默认 127.0.0.1:7709)暴露,

任何语言写的上层程序都能调。

它不做:发布视频、批量点赞关注、养号、多账号矩阵、自动过验证码、签名逆向。

特性

能力 · 说明 · 需要登录 热榜 · 抖音热榜条目、热度、搜索链接 · 否 搜索 · 关键词搜索,search_id 链式翻页 · 是(多数情况) 视频详情 · 文案、作者、互动数据、前 N 条评论 · 是 用户主页 · 简介、粉丝、近期作品 · 是 视频下载 · 移动端分享页解析无水印直链,绕过失效的 Douyin 提取器 · 是 抽帧 · ffmpeg 均匀抽 4–12 帧,供视觉模型使用 · 是 私信 / 群聊 · Playwright 驱动网页版,dry-run 默认,三道闸 · 是 登录状态机 · 可轮询的扫码/短信状态机(有头环境) · — 状态自检 · 依赖、登录态、配额、上次错误一句话总结 · 否 HTTP API · 上述能力的 JSON 接口 · 视接口

其它工程特性:

  • 单 worker + 抖动:所有后端调用串行,翻页 3–8 秒高斯抖动,独立调用

1.8–3.2 秒,避免明显的机器人节奏。

  • 小时配额 + 指数退避:滚动 1 小时请求预算(默认 60),触发限流后

1/2/4/8/15 分钟退避,不立即重试。

  • 凭证脱敏:cookie、sessionid、passport_*、localStorage、

storage_state 不会出现在返回值、日志或报错里。

  • 账号指纹:记录首个登录账号的不可逆指纹,换号后写操作直接拒绝。
  • 缺失即 `null`:抖音数据稀疏,缺字段返回 null,不填 0、不猜。

和上游的关系

本仓库是 SakuraMat0u/dsh-douyin-toolkit 的改造版。上游是一个只跑 Windows + Edge 的只读 + 单条评论插件,本仓库在此 基础上加了:

变更 · 说明 Linux / headless 适配 · 浏览器发现扩展到 Chromium/Chrome/Playwright 自带内核;无 X server 时自动降级 headless;进程清理加 POSIX 分支 私信 / 群聊 · 新增 python/douyin_im.py:Playwright 驱动网页版,dry-run 默认 + 双闸 + 可选白名单 + 串行锁 视频下载 / 抽帧 · 新增 python/douyin_http.py:移动端分享页解析无水印直链 + yt-dlp generic + ffmpeg 抽帧 HTTP API · 把 dy-cli 与私信驱动包装成本地 JSON 服务(端口 7709) 路径参数化 · 服务器绝对路径全部改为环境变量 / 相对路径 文档 · 新增 Linux 适配、Cookie 导出、HTTP API、安全说明

上游的核心设计(dy-cli 只读通道、错误码、限频、脱敏、登录状态机、账号指纹) 都保留了,没有重写。

架构

flowchart TD
    A[DSH Cordis 插件<br/>index.js + lib/tools.js] --> B[backend.js<br/>限频 / 配额 / 脱敏 / 串行]
    C[HTTP 客户端<br/>任意语言] --> D[douyin_http.py<br/>FastAPI :7709]
    B --> E[dy-cli<br/>python -m dy_cli.main]
    B --> F[douyin_bridge.py<br/>Playwright 登录 / 评论]
    D --> E
    D --> G[douyin_im.py<br/>Playwright 私信 / 群聊]
    D --> H[yt-dlp + ffmpeg<br/>下载 / 抽帧]
    F --> I[(系统浏览器<br/>Edge / Chromium)]
    G --> I

两条入口(DSH 插件 / HTTP)共享同一批 Python 脚本和同一个 data/ 目录,互不 冲突:插件走子进程 + 自己的串行门;HTTP 服务另有进程级锁,避免同时开两个 Chromium。

环境要求

项 · 要求 · 备注 Python · 3.10+ · 实测 3.10 / 3.14 Node.js · 22+ · DSH 自带 浏览器 · Edge(Windows)/ Chromium 或 Chrome(Linux、macOS) · 也可 playwright install chromium ffmpeg / ffprobe · 可选 · 只有抽帧需要 yt-dlp · 可选 · 没有时会退回 urllib 直接下载 磁盘 · ≥ 1 GB · 成片缓存默认上限 800 MB

安装

1. 克隆并建虚拟环境

git clone https://github.com/JianHeShui/dsh-douyin.git
cd dsh-douyin

python3 -m venv .venv
# Linux / macOS
.venv/bin/pip install -r python/requirements.txt
# Windows
# .venv\Scripts\pip install -r python\requirements.txt

需要 HTTP API 的话,再装一层(requirements-http.txt 是超集):

.venv/bin/pip install -r python/requirements-http.txt

2. 准备浏览器

Windows 上装了 Edge 就不用管。Linux / macOS:

.venv/bin/playwright install chromium
# 国内网络慢可以走镜像:
# PLAYWRIGHT_DOWNLOAD_HOST=https://cdn.npmmirror.com/binaries/playwright \
#   .venv/bin/playwright install chromium

也可以用系统包(apt install chromium),插件会自动发现。要指定就用 DOUYIN_BROWSER=/usr/bin/chromium,或在插件配置里设 edgePath。

3. 装进 DSH

dsh plugin --profile desktop add file:$PWD
# 或按你的 profile 名: --profile web

插件自带 cordis.patch.yml,安装时会插入 id: douyin 的配置行。装完重启 DSH。自检:

# DSH 里直接调用 douyin_status
# 或者命令行
./scripts/selfcheck.sh          # Windows: .\scripts\selfcheck.ps1

4.(可选)起 HTTP 服务

./scripts/run-http.sh           # Windows: .\scripts\run-http.ps1
curl -s http://127.0.0.1:7709/health | jq .

常驻用 deploy/douyin-api.service(systemd 模板,记得改 User= 与路径)。

登录

必须在有显示器的电脑上登录,再把 cookie 送到服务器。 服务器 headless 环境 无法扫码、无法过滑块。

# 本地电脑上执行,会弹出浏览器窗口
.venv/bin/python tools/export_login_state.py
# 扫码登录成功后,自动写出 data/home/.dy/cookies/default.json

# 送到服务器
scp data/home/.dy/cookies/default.json user@server:~/dsh-douyin/data/home/.dy/cookies/default.json
ssh user@server 'chmod 600 ~/dsh-douyin/data/home/.dy/cookies/default.json'

完整流程、可选参数、过期处理见 docs/COOKIE-GUIDE.md。

登录后验证:

curl -s -X POST http://127.0.0.1:7709/im/status | jq .

快速开始

在 DSH 里

douyin_status                                   # 先看状态
douyin_hot({"count": 10})                       # 热榜
douyin_search({"keyword": "开源", "limit": 5})   # 搜索
douyin_video({"aweme_id": "7xxxxxxxxxxxxxx"})   # 视频详情

看视频内容(推荐路径):

POST /frames {"aweme_id": "...", "n": 8}   # 拿到 8 张帧
→ 把帧路径交给视觉模型,问"这条视频讲了什么"

在 DSH 里可以直接让 agent 完成这串动作;HTTP 侧则是两步:先 /frames,再把 返回的 frames[] 喂给任意支持图片输入的模型。

HTTP

# 热榜
curl -s -X POST http://127.0.0.1:7709/trending | jq .

# 搜索
curl -s -X POST http://127.0.0.1:7709/search \
  -H 'Content-Type: application/json' \
  -d '{"keyword":"猫","count":5}' | jq .

# 下载 + 抽帧
curl -s -X POST http://127.0.0.1:7709/frames \
  -H 'Content-Type: application/json' \
  -d '{"aweme_id":"7xxxxxxxxxxxxxx","n":8}' | jq .

# 私信(默认 dry-run:只填框 + 截图 + 清空)
curl -s -X POST http://127.0.0.1:7709/im/send \
  -H 'Content-Type: application/json' \
  -d '{"to":"某某","text":"在吗"}' | jq .

完整接口、错误码、dry-run 语义见 docs/HTTP-API.md。

命令行(不经过 DSH / HTTP)

python python/douyin_im.py status
python python/douyin_im.py conversations --limit 20
python python/douyin_im.py groups --limit 20
python python/douyin_im.py send --to=某某 --text=在吗          # dry-run
DOUYIN_IM_ALLOW_SEND=1 python python/douyin_im.py send --to=某某 --text=在吗 --send

配置

插件配置(cordis.patch.yml)

装好后不要重复 insert 同一个 id;在 profile 的 cordis.patch.yml 顶层加同 id 覆盖行:

- id: douyin
  name: dsh-douyin
  config:
    writesEnabled: false
    maxSearchPages: 2
    pythonPath: /opt/dsh-douyin/.venv/bin/python
    dataDir: /opt/dsh-douyin/data
    edgePath: /usr/bin/chromium

字段 · 默认 · 说明 enabled · true · 关闭后不注册任何工具 writesEnabled · false · 评论写操作总开关 toolEnabled · 全 true · 单工具开关:hot / search / video / user / status / login / verify / comment / publish maxResults · 20 · 单次返回上限,硬上限 20 maxSearchPages · 3 · 单次搜索翻页上限,硬上限 3 hourlyRequestBudget · 60 · 滚动 1 小时请求预算 pageDelayMinMs / pageDelayMaxMs · 3000 / 8000 · 翻页抖动区间 callDelayMinMs / callDelayMaxMs · 1800 / 3200 · 调用间隔区间 pythonPath · 空 · 默认 /.venv/bin/python(Windows 为 Scripts\python.exe) dataDir · 空 · 默认 /data edgePath · 空 · 默认自动发现 logLevel · info · silent / error / info / debug

环境变量(HTTP 服务 / 独立脚本)

完整列表见 .env.example。常用:

变量 · 默认 · 说明 DOUYIN_DATA_DIR · /data · 数据目录(cookie、profile、日志) DOUYIN_PYTHON · 当前解释器 · 装了 dy-cli 的解释器 DOUYIN_BROWSER · 自动发现 · 浏览器可执行文件 DOUYIN_HEADLESS · 私信驱动 1 · 0 开窗口调试 DOUYIN_COOKIE_FILE · /home/.dy/cookies/default.json · storage_state DOUYIN_MEDIA_DIR · /media · 成片 / 帧缓存 DOUYIN_HTTP_HOST / DOUYIN_HTTP_PORT · 127.0.0.1 / 7709 · 监听地址 DOUYIN_IM_ALLOW_SEND · 未设置 · 1 才允许真实发送 DOUYIN_IM_ALLOW_TO · 未设置 · 发送白名单,逗号分隔 DOUYIN_IM_TIMEOUT · 180 · 单次私信操作超时(秒)

私信安全模型

真实发出一条私信需要同时满足:

  1. 调用方显式要求:HTTP 传 send: true,CLI 传 --send;
  2. 服务端总闸打开:DOUYIN_IM_ALLOW_SEND=1;
  3. 如果设了 DOUYIN_IM_ALLOW_TO,目标必须在白名单里。

缺第 1/2 道:文本填进输入框、截图、然后清空,没有任何消息发出,响应里 data.dry_run 为 true。 缺第 3 道:直接 TARGET_NOT_ALLOWED,连输入框都不填。