抖音采集
安装方法
- 先问使用者用的是什么 AI 工具,选项按这个顺序列:1. WorkBuddy 2. Claude Code 3. Codex 4. 其他(用户直接说工具名),回答记作 X
- 只安装给 X,不安装或链接其他任何工具:
-
X 是 WorkBuddy:把本技能下载后放进
~/.workbuddy/skills/(WorkBuddy 的技能目录;skills CLI 不支持 WorkBuddy,由你直接放置) -
X 是其他工具:
npx -y --registry=https://registry.npmmirror.com skills add https://modelscope.cn/skills/sunny31221/douyin-collect-buheliwa -a X -y(不带
-a会安装给本机所有检测到的工具,禁止;--registry为 npmmirror 镜像,保证国内不翻墙也能拉到 CLI) -
X 不在上述范围时,按该工具自身的技能机制安装,装完确认 X 能识别本技能即可
-
- 装完后询问是否现在使用本技能
依赖什么
| 依赖 | 作用 | |---|---| | opencli(浏览器桥) | 打开视频页、抓音频流地址、读元信息。本技能唯一的外部依赖 | | curl | 下载音频流与封面(系统自带) | | mlx-whisper | 把音频转成逐字稿(macOS) | | requests(Python 包) | 解析短链重定向 |
装不上 / 跑不通怎么办:
| 情况 | 处理 |
|---|---|
| opencli 连不上浏览器 | opencli doctor 看哪一环断了;扩展没连上就在 Chrome 里点一下扩展图标 |
| 没登录抖音 | 把页面显示给使用者,让他自己登录;不要替他登录。页面能打开但抓不到音频流,多半就是这个原因 |
| 没有 mlx-whisper | 装一次;实在装不上就在最终报告里写明「转写未完成」,只落 02_内容信息.md + 封面,不留空文件 |
| 抓不到 media-audio 流 | 音频流地址只在浏览器实际播放时才发出。脚本打开页面后会自动静音播一下;还抓不到就确认页面是不是停在登录或验证页,再重抓一次 |
| 标题或 cover_url 是空的 | 两者都在页面加载那一下抓,页面没加载完就会落空。重跑一次 fetch(脚本会自己整页重开再试一次);标题实在拿不到就看页面 <h1>,封面实在拿不到就在 02_内容信息.md 里写「封面未获取」 |
| 音频流地址过期 | 签名地址有有效期。抓到手就立刻下;报错就整条 fetch 重跑一次 |
| cover_url 为空 | 详情接口这次也没返回本条封面。重跑一次 fetch;仍是空就在 02_内容信息.md 里写「封面未获取」,别拿页面上那张推荐封面顶上——那只会在素材里混进另一条视频的图 |
去哪装(推荐降级链:国际源失败 → 国内镜像):
# opencli
npm install -g @jackwener/opencli
npm install -g @jackwener/opencli --registry=https://registry.npmmirror.com # 淘宝镜像
# 装完还要在 Chrome 里装配套扩展,见 opencli 官方说明;再跑一次 opencli doctor
# mlx-whisper(Apple 芯片的 macOS)
pip3 install -U mlx-whisper
pip3 install -U mlx-whisper -i https://pypi.tuna.tsinghua.edu.cn/simple # 清华镜像
pip3 install -U mlx-whisper -i https://mirrors.aliyun.com/pypi/simple/ # 阿里云镜像
# Windows / Intel Mac 用 openai-whisper 代替
pip install -U openai-whisper
pip install -U openai-whisper -i https://pypi.tuna.tsinghua.edu.cn/simple
# requests
pip3 install -U requests
pip3 install -U requests -i https://pypi.tuna.tsinghua.edu.cn/simple
装完验证:
opencli doctor | head -5
mlx_whisper --help | head -3
python3 -c "import requests; print('requests ok')"
为什么走浏览器
抖音的公开分享页早已不内嵌视频信息(window._ROUTER_DATA 里只剩配置项和 abParams),
yt-dlp 抓不了(报 Fresh cookies (not necessarily logged in) are needed,加 --cookies-from-browser 也一样)。
音频流地址只在浏览器实际播放时由 MSE 请求发出,所以只能从抓包里取。
详见 references/采集排障.md。
触发场景
- "采集这个抖音视频" + 分享链接或分享文字
- "抖音入库" / "把这条抖音链接存进对标素材"
- 采集编排器识别到
v.douyin.com/douyin.com/video链接后分流到本技能
输出位置
AI第二大脑/规律研究/对标内容采集/抖音/
└── NNN_标题_视频ID/
├── 01_原始素材/
│ └── 01-封面图/
│ └── cover.jpg
├── 02_内容信息.md
├── 04_文案结构化梳理.md
└── 05_视频脚本.md
- 编号:取目标目录已有最大编号 +1(三位补零),由
create_note_folder.py决定,不由 AI 数 - 文件夹名:
编号_标题_视频ID。标题取核心标题,去掉话题词(话题词进02_内容信息.md的标签栏) - 去重:同一视频 ID 已存在时跳过,不重复建文件夹
- 原片不存:音频只是转写的原料,转写完即删
少花调用次数
有些链路按请求次数计费(第三方兼容接口的每日额度多是这样),不按 token。一次模型回复里发多个工具调用,只算 1 次请求;串行一次发一个,就一次一个数。同一个任务排得好坏,能差三倍次数。
- 能串的串成一条命令:
python3 a.py && python3 b.py,中间结果用$(...)接住。互不依赖的命令别分成两次 Bash。 - 无依赖的一轮发完:抓取、下载、读文件这些互不依赖的动作,放在同一条回复里一起发。
- 脚本能批量就别逐条调:先看脚本的
--help,支持一次处理多条或整个目录的,就一次跑完。 - 输出要过滤:脚本输出配
head/grep再看。全量输出进上下文既拖速度,也容易把关键信息淹掉。 - 图片只存档,不进模型:下载下来的封面和正文图直接落位,不要用 Read 之类的读图能力打开看。图片进 API 会以 base64 文本计费,一张原图约十万 token,此后每轮请求都带着重发。确实要看图时,先跑
shrink.py压小,一次最多两张。
流程
1. 抓取(解析链接 + 开页面 + 抓音频流 + 读元信息)
一条命令跑完:
python3 "<本技能目录>/scripts/fetch_douyin.py" --json fetch '<分享文字或链接>' --out-dir /tmp/douyin
返回 JSON 里这几个字段后面都要用:video_id、title、author、author_fans、published、duration_sec、cover_url、stats(点赞 / 评论 / 收藏 / 分享)、audio_path。
只想解析链接拿视频 ID 时:
python3 "<本技能目录>/scripts/fetch_douyin.py" --json resolve '<分享文字或链接>'
分享文字直接原样传进去,不要自己从里面抠链接。
如果抓不到音频流,看返回的报错提示;也可以自己用 opencli browser <session> network --since 5m --all 看抓到了什么。
2. 建素材文件夹
python3 "<本技能目录>/scripts/create_note_folder.py" \
--platform 抖音 --type 视频 \
--id <video_id> --title "<核心标题>" --author "<作者>" \
--published "<发布时间>" --url "<分享链接>" \
--likes <点赞> --comments <评论> --collects <收藏> --shares <分享> \
--fans "<作者粉丝数>" --duration "<时长>"
返回 JSON 里的 folder 就是素材文件夹路径,后面所有文件都写进它。
--title 传去掉话题词的核心标题;--likes 一类收 1.5万 / 32000 两种写法。
3. 抽封面
用 fetch 返回的 cover_url 直接下载(必须带 Referer,否则 403):
curl -sL -H "Referer: https://www.douyin.com/" \
-o "<素材文件夹>/01_原始素材/01-封面图/cover.jpg" "<cover_url>"
拿到的是本条视频自己的封面,来自详情接口 aweme/detail 的 aweme_detail.video.cover。页面上扫不到它是常态(播放器直接把视频塞进 <video>,不渲染封面图,能扫到的全是右侧推荐的),所以别自己去 DOM 里找。改 URL 里的尺寸参数会 403(签名跟参数绑死),不要去改。
拿到下载结果里的标题、作者、发布时间、封面路径、音频路径。
4. 转写逐字稿
mlx_whisper "<audio_path>" --model mlx-community/whisper-large-v3-turbo \
--language zh --output-dir "<素材文件夹>" --output-format txt
(Windows / Intel Mac 换成 whisper "<audio_path>" --model medium --language zh --output_format txt --output_dir "<素材文件夹>")
参数用连字符,--output_dir 这种下划线写法会报 unrecognized arguments。
模型选择(2026-10-15 实测,11 分 39 秒音频):
| 模型 | 耗时 | 说明 |
|---|---|---|
| whisper-large-v3-turbo | 36 秒 | 推荐,速度最快,质量与 medium 相当 |
| whisper-medium-mlx | 1 分 39 秒 | 慢一些,质量没有更好 |
| whisper-large-v3-mlx | 3 分钟以上 | 质量最好,逐字稿要精修时用 |
转写完把音频删掉(逐字稿已落盘):
rm "<audio_path>"
转写结果要做三件事,再存档:
- 繁转简:mlx-whisper 可能输出繁体,转成简体,其余字词不动
- 术语纠错:语音转写会把同音词写错,抖音这类口播视频尤其多。先看页面上有没有抖音自带的「章节要点」,那是抖音自己的语音识别出的分段小标题,可以拿来校准术语;再按上下文逐个核对
- 误转词对照:确认认错的词列进
05_视频脚本.md文末的修正说明,逐条写清原转写、修正为、依据
转写结果是逐字稿原文,除繁转简与术语纠错外照抄:不改写、不顺句、不补标点,口语词、重复、口癖都保留。
繁转简的办法(按顺序试):
- 让 AI 直接转(最省事,繁体转简体是模型的常规能力)
- 想自动化就装一次:
pip3 install opencc-python-reimplemented -i https://pypi.tuna.tsinghua.edu.cn/simple(Homebrew 的 Python 会报externally-managed-environment,加--break-system-packages或改用虚拟环境),转法是opencc.OpenCC('t2s').convert(text)
5. 写 02_内容信息.md
脚本已建好骨架并填好字段表。补三处:
- 视频简介:照抄标题连同话题词;拿不到写「无」
- 标签:把标题里的话题词逐个写出来(
#内容创作、#黑色生命力…) - 封面:确认嵌入路径对得上
字段表里的互动数据由脚本直接填入,拿不到的留「未获取」,不估、不凭印象填。
6. 写 05_视频脚本.md
照 assets/视频脚本模板.md 写。固定结构:
# 视频脚本(<编号> · <标题>)
> 转录说明:mlx_whisper(large-v3-turbo 模型)转写,<日期>;已按语义修正明显误转词,未润色口语表达。
> 转写默认出繁体时已转简体:只转字形,不改用词。
> 原文照抄为主,修正处已在文末「修正说明」逐条列出。
---
## 一、<分段小标题:开场钩子 / 背景介绍 / 第一步… / 观点收尾>
<该段脚本原文照抄——最大化还原,不提炼、不压缩、不概括>
## 二、<分段小标题>
<同上>
---
## 修正说明
| 原转写 | 修正为 | 说明 |
|---|---|---|
| <误转词> | <正确词> | <同音误转 / 上下文推断 / 页面章节要点佐证> |
**存疑保留**:<拿不准的误转词原样保留,在这里逐条说明>
要点:05 是原文存档——分段小标题 + 原文照抄,中心思想/核心论点那类梳理归 04 管。
分段可以借抖音页面上「章节要点」给的时间点(那套时间轴是抖音自己生成的,可直接采信为分段依据)。
7. 写结构化梳理
05_视频脚本.md 是原始素材,还要再出一份便于下游提炼规律的梳理件 04_文案结构化梳理.md(模板见 assets/文案结构化梳理模板.md):
# 文案结构化梳理
> 来源:<编号> <标题>([[05_视频脚本.md]])
> 梳理日期:<YYYY-MM-DD>
> 说明:本文件做结构化梳理:中心思想、核心论点、逐段梳理。总结保留原文的具体论据、数据与比喻——**写到「不读原文也能知道这段说了什么、能吸收这段的知识」**;完整原文见 05 号文件,本文件只做概括与归类,不改写、不新增原文没有的东西。
---
## 一、中心思想
<一段话说清这条视频主张什么:讲了什么、结论是什么、对谁说的。不评价、不引申>
一句话概括:**<原文里最有代表性的一句总结;原文没有就自己凝练一句,不加引号>**
## 二、核心论点(N 条)
1. **<论点>**:<展开,保留原文的数据、例子、比喻>
2. **<论点>**:<…>
## 三、逐段梳理
### <原文小标题(原文没有就按自然结构拟一个)>
**一句话总结**:<保留该段的核心主张 + 具体论据、数据、比喻、例子,写到不读原文也能知道这段说了什么;不整段照抄>
## 四、结构规律提炼
<3-5 条,讲这条视频的骨架怎么搭的:几段式、每段承担什么、开头与结尾各做什么>
要点:梳理件里的每一句都要能追回 05 的原文;不新增视频里没有的数据或例子。
8. 回写已入库标记
采完立刻在链接文档那一行行尾追加「(已入库 ✓ 日期)」,让编排器下次读文档时知道这条已经采过:
python3 "<本技能目录>/scripts/link_doc.py" mark <视频ID> --url "<原始分享链接>"
链接是抖音短链(v.douyin.com/xxx)时,必须带 --url——短链行里没有数字 ID,脚本靠这一项认行;不带会把同一条视频的另一行标错。
脚本只动那一行,其余行逐字不动,改前先留一份 .bak。已标记过的行再标一次会跳过,不重复追加。
入库来源如果不是链接文档(使用者直接给的链接),这一步跳过。
9. 完成后报告
报告:标题、作者、时长、转写字数、封面是否抽到、落盘路径。有跳过或失败的项目一并说明。
约定(每条带来由与适用范围)
-
不代替使用者登录抖音 适用与边界:管抓取环节遇到登录页时。处理:把页面显示出来,告诉他登录完会自动继续。不适用:使用者已登录的浏览器会话,直接用。
-
不绕过风控:不换代理、不破验证码、不伪造设备指纹 适用与边界:管抓取方式。边界:遇到验证码或风控拦截就暂停并告知,不尝试绕过。不适用:正常的登录态失效,重开页面即可。
-
只用浏览器实际发出的音频流:不自建解析、不猜接口签名 适用与边界:管音频来源。不适用:创作者自己提供的本地文件——那直接转写,不走抓取。
-
逐字稿只做繁转简与术语纠错:除此之外不改写、不润色、不补标点;误转词另列对照 适用与边界:管转写产出的
05_视频脚本.md。不适用:创作者自己写的稿子。 -
拿不到的数据留白:互动数据、发布时间拿不到就写「未获取」,不估 适用与边界:没有例外——拿不到就写「未获取」。
-
去重靠视频 ID:同一视频不重复入库 适用与边界:管同一条视频重复入库时。不适用:同一作者的不同视频,按新素材处理。
-
原片与音频不进素材文件夹:转写完即删,素材夹只留封面与文稿 适用与边界:管素材文件夹的内容。不适用:使用者明确要求留存原片的场合。
-
禁用词检查只跑 04,不跑 05:
04_文案结构化梳理.md是自己写的,照常跑check_prose.py;05_视频脚本.md是别人口播的逐字稿原文,不套用禁用词规则——把原话里的「说白了」「不是…而是…」改掉就是篡改存档。跑检查时跳过 05,或看到它的报错直接放行 适用与边界:管这两个文件的检查动作。不适用:02_内容信息.md(字段表加简介,照常查)。
不做什么
- 不批量采集作者主页——一次一条链接;批量要另想办法,本技能的抓取路径不支持
- 不采评论区——抖音评论没有稳定的读取路径
- 不绕过登录、不代替使用者登录
- 不碰付费 / 私密内容
- 不识别链接属于哪个平台、不建目录、不提规律、不沉淀卡片
- 不跑归档 CSV——「已入库 ✓」标记由本技能写,归档由编排器批量采完后统一跑
Resources
- 链接文档回写脚本:
scripts/link_doc.py(mark <ID>回写已入库标记,改前自动留.bak) - 内容信息模板:assets/内容信息模板.md
- 视频脚本模板:assets/视频脚本模板.md
- 采集排障:references/采集排障.md
微信扫一扫