博主内容风格自动分析工具
概述
输入一个博主链接,自动完成:平台识别 → 视频列表获取 → 字幕/文案提取 → LLM多维度风格分析 → 内容分类 → 创作公式提炼 → 生成DOCX专业分析报告。
分析产出的 DOCX 报告同时作为下游文案生成管道的素材源:由独立的 transform_to_libraries.py 转换器(属于 copywriter 管道,不随本技能打包)解析 DOCX 生成结构化 JSON 原料库(选题库/钩子库/风格库/文案模板),再由 copywriter 技能合成选题并调用 LLM 写出说人话的口播文案。
适用平台:抖音、B站、小红书、快手、视频号(半自动)。
工作流程总览
Step 0: 输入处理(去重、身份识别、级别判定、增量检测)
Step 1: 平台识别 & 博主信息获取(含 aweme_id 去重)
Step 2: 内容提取(三层降级策略 + ASR 内置后处理)
Step 2.5: 质量验证门控(强制执行,不通过则不允许进入 Step 3)
Step 3: 风格画像(LLM 6维分析)
Step 4: 内容自动分类
Step 5: 创作公式提炼
Step 6: 高级分析(L3+级别专属)
Step 7: 格式转换 & 输出
Step 0:输入处理
0.1 解析链接列表
从用户输入中提取所有博主链接。支持:
- 直接粘贴链接(一个或多个)
- 批量选择(多个链接用换行或逗号分隔)
- 短链自动解析(如
v.douyin.com/xxx)
0.2 去重处理
对每个链接提取博主唯一标识:
平台:博主ID
例:
抖音 → douyin:MS4wLjABAAAA...
B站 → bilibili:123456
小红书 → xiaohongshu:xxx
快手 → kuaishou:xxx
相同博主标识的链接合并为一个,提示用户:"检测到X个链接指向Y个博主"。
详细规则见 references/identity_management.md。
0.3 博主身份识别(多账号时)
如果用户提供的多个链接名称相似:
- 使用 difflib.SequenceMatcher 计算名称相似度
- 计算简介的关键词重合度
- 相似度 > 80% 或关键词重合 > 60% → 提示用户确认是否同一博主
同博主多账号时提供三种策略:
- 独立分析(默认):每个账号独立分析
- 合并分析:所有视频合并为一个综合分析
- 对比分析:各账号独立分析 + 生成账号矩阵对比报告
详见 references/identity_management.md。
0.4 历史记录检测
检查 {{LOCAL_ROOT}}/blogger_lib/{博主名称}/ 是否存在历史分析记录。
检测流程:
- 读取
{博主名称}/博主信息.json→ 获取 sec_uid(跳过短链解析) - 读取最新
{级别}_{日期}/分析元数据.json→ 获取上次分析级别、日期、视频数、视频ID列表 - 如
分析元数据.json不含video_ids字段(旧版格式),从 API 重新获取视频列表 - 对比视频ID列表,计算新增视频数
有历史记录时:
- 新增 < 5条 → 建议增量更新
- 新增 5-20条 → 提供增量/完全重新分析两种选择
- 新增 > 20条 或 距上次 > 30天 → 建议完全重新分析
增量更新时只分析新增视频,结果与历史数据合并。
注意:
分析元数据.json必须包含video_ids字段(所有已分析视频的 aweme_id 列表),清理步骤删除raw/后,这是增量检测的唯一数据源。
0.5 级别判定
获取一年内视频数量 x,按规则判定级别:
x ≤ 10 → L1 快速版(基础分析,3份报告)
10<x≤20 → L2 标准版(+创作公式&标签矩阵,5份报告)
20<x≤40 → L3 深度版(+稳定性&趋势&爆款分析,8份报告)
40<x≤60 → L4 专业版(+季度对比&内容矩阵,10份报告)
60<x≤80 → L5 高级版(+发布规律&受众推断,12份报告)
80<x≤100 → L6 全量版(+年度演变&策略建议,14份报告)
x > 100 → L6 全量版(取最近100条)
各级别均分析全部视频(x≤100时),差异在于高级分析功能的数量。详细规格见 references/level_specs.md。
展示判定结果,用户确认后执行。费用按实际视频数计算。
Step 1:平台识别 & 博主信息获取
1.1 平台识别
根据URL特征识别平台,参考 references/platform_support.md:
| URL特征 | 平台 |
|---------|------|
| douyin.com/user/ 或 v.douyin.com/ | 抖音 |
| bilibili.com/space/ | B站 |
| xiaohongshu.com/user/ | 小红书 |
| kuaishou.com/profile/ | 快手 |
| channels.weixin.qq.com | 视频号 |
1.2 视频列表获取
抖音(TikHub API 方案,全量分页):
✅ 推荐方案:通过 TikHub App V3 API 获取全量视频列表,支持完整分页,无需登录、无需浏览器、无 a_bogus 限制。
技术方案:
- 调用 TikHub API
/api/v1/douyin/web/get_sec_user_id从博主链接解析sec_user_id - 调用 TikHub API
/api/v1/douyin/app/v3/fetch_user_post_videos分页获取视频列表 - 每页最多 30 条,自动翻页直至超出时间范围或达到目标数量
- 输出格式与 Playwright 方案完全兼容(
metadata.json)
关键代码路径:scripts/fetch_douyin_videos_api.py
- API 基础 URL:
https://api.tikhub.io - 分页参数:
sec_user_id,max_cursor,count - 时间筛选:
create_time > one_year_ago_timestamp - 请求间隔: 0.5 秒(避免触发限流)
- 费用: ~$0.001/页(每次 API 调用),一个 L6 博主约 $0.007
API Key 配置(必需):
- 环境变量:
TIKHUB_API_KEY或通过--api-key参数传入 - 获取: 注册 https://user.tikhub.io 后获取
- 存储: 添加到
(通过 COPY_ENV_FILE / BLOGGER_ENV_FILE 环境变量指定,不要写死路径)
故障降级(当 TikHub API 不可用时):
- 回退到 Playwright 桌面 UA 方案(
scripts/fetch_douyin_videos.py) - Playwright 仅能获取 ~18-20 条(a_bogus 限制),仅 L1-L2 可用
⚠️ Playwright 方案的 a_bogus 限制:已通过 12 种策略验证无法突破翻页。抖音
a_bogus签名与 URL 参数绑定,修改 cursor 导致签名失效。12 种测试(有头浏览器、PageDown、鼠标拖动、dispatch 事件、IntersectionObserver、page.request 带 cookie、多轮 headless 等)均无法推进 cursor。每 session 硬限制 18-20 条。
❌ yt-dlp
--flat-playlist不支持抖音用户主页(抖音客户端渲染,无静态 playlist)
B站:
yt-dlp --flat-playlist --dump-json "https://space.bilibili.com/<UID>/video" > videos.json
小红书/快手:
yt-dlp --flat-playlist --dump-json <用户主页URL>
视频号(半自动模式):
- 不支持自动抓取,提示用户选择:
- [A] 手动下载视频文件(推荐)
- [B] 元宝辅助提取文案
- [C] 手动粘贴文案
1.3 时间筛选
- 筛选「一年内」发布的视频(365天内)
- 按发布时间降序排列(最新的在前)
- 生成时间分布报告:
- 最近1个月、1-3个月、3-6个月、6-12个月的视频分布
- 发布频率(每周X条)
- 博主活跃状态(活跃/低频/停更)
1.4 博主停更检测
- 最新视频 > 90天前 → 提示"该博主已停更,数据可能不具备时效性"
- 用户选择继续或取消
1.5 输出
生成 raw/metadata.json,包含:
{
"blogger_name": "...",
"platform": "douyin",
"fans_count": 0,
"total_videos": 0,
"time_filter": {
"range": "one_year",
"filtered_count": 45,
"distribution": {...}
},
"videos": [
{
"video_id": "...",
"title": "...",
"publish_date": "2026-07-10",
"duration_ms": 60000,
"like_count": 0,
"comment_count": 0,
"share_count": 0,
"collect_count": 0,
"play_count": 0
}
]
}
Step 2:内容提取
2.1 三层降级策略
⚠️ 关键发现:抖音视频的
interaction_stickers(软字幕)在大多数视频中为None,SSR 分享页和桌面 detail API 均不包含口播字幕。caption字段等同于desc(发布描述),不是视频口播内容。因此 ASR(L2)是获取真实口播内容的主要方案,而非降级方案。
| 层级 | 方式 | 适用场景 | 实际可用性 | |------|------|----------|-----------| | L1 | 软字幕提取(interaction_stickers) | 有智能字幕的视频 | ❌ 大多数视频为 None | | L2 | ASR语音转文字(下载视频→提取音频→ASR) | 所有有语音的视频 | ✅ 主要方案 | | L3 | desc发布描述降级 | 所有自动方式失败 | ⚠️ 最后手段,需标注 |
ℹ️ OCR(硬字幕识别)为规划中功能,暂未实现,不在降级序列中占位。
2.2 抖音视频处理
字幕提取流程(scripts/extract_douyin_transcripts.py):
Step A:SSR软字幕尝试(L1)
- URL 格式:
https://www.iesdouyin.com/share/video/{aweme_id}/(❌ 不是douyin.com/video/) - 使用移动 UA 请求分享页,提取
_ROUTER_DATA - 检查
interaction_stickers和video_text字段 - 若有软字幕 → 直接使用,标注来源为"软字幕"
Step B:ASR语音转文字(L2,主要方案)
- 从 SSR
_ROUTER_DATA的video.play_addr.url_list获取视频下载地址 - 下载视频 → 用 ffmpeg 提取音频(mp3, 16kHz 单声道)
- 调用 SiliconFlow SenseVoiceSmall ASR API 转写口播内容(免费)
- ffmpeg 来源:
imageio-ffmpeg包(自带静态二进制,不依赖系统PATH) - ASR 脚本:
video-deconstruct-pro/scripts/asr_transcribe.py - API Key:
(通过 COPY_ENV_FILE / BLOGGER_ENV_FILE 环境变量指定,不要写死路径)中的SILICONFLOW_API_KEY - 转写 prompt 已优化智能家居场景词汇
Step C:desc降级(L4)
- 所有自动方式失败时,使用
desc字段作为文案 - 必须标注:
字幕来源: 无字幕(使用发布描述作为降级文案)
2.3 B站视频处理
yt-dlp --write-subs --write-auto-subs --sub-lang zh-Hans,zh --skip-download <video_url>
2.4 视频号处理
用户手动下载视频 → 传入本地视频路径 → ASR提取文案
ℹ️ 小红书 / 快手字幕提取(部分支持):Step 1.2 已通过 yt-dlp 获取其视频列表/下载视频,但 Step 2 未为其内置独立的软字幕/SSR 流程。当前应复用与抖音相同的 ASR 路径——下载视频 → 用 ffmpeg 提取音频 → 调用 SiliconFlow ASR(即 Step 2.2 的「Step B:ASR 语音转文字」逻辑),标记为部分支持。
2.5 批量处理
- ASR 逐条处理,单条间隔 ≥ 3秒(API 限流)
- 视频下载失败自动重试(最多2次),仍失败则跳过并记录
- ASR 失败则降级为 desc,标注来源
- 每条视频的 transcript 文件必须标注字幕来源
2.5.1 ASR 后台任务监控
当 ASR 批量处理以后台模式运行时,TaskOutput 可能无法获取 print() 的 stdout 输出。推荐以下监控方法:
方法A:文件计数法(推荐)
# 定期统计已完成的 transcript 文件数量
ls "raw/transcripts/" | wc -l
方法B:读取 extraction_summary.json
ASR 脚本完成后自动生成 extraction_summary.json,包含总数/成功/失败/来源分布等统计信息。
2.6 输出
按发布时间排序,每条视频一个txt文件:
raw/transcripts/video_001.txt ~ video_N.txt
每个文件包含:
视频序号 / 视频ID / 发布日期 / 时长 / 互动数据
字幕来源: [软字幕|ASR|desc降级]
---已清洗(asr_postprocess)--- ← 清洗标记
---视频文案(发布描述)---
{desc}
---视频字幕(真实口播内容)--- ← 仅当ASR/软字幕成功时存在
{transcript}
2.7 ASR 后处理质量门控(强制执行,不可跳过)
⚠️ 这是强制步骤,不可跳过。 之前因跳过此步骤导致报告出现 emoji、日文歌词、品牌名错误等问题,需要多轮返工。
ASR 转写完成后,必须经过统一后处理管道 scripts/asr_postprocess.py 的清洗和验证:
方式1:ASR 脚本已内置后处理(推荐)
extract_douyin_transcripts.py和siliconflow_asr_batch.py已在转写后自动调用- 无需额外操作,清洗在写入 .txt 文件前完成
方式2:对已有 .txt 文件批量清理(补救用)
python scripts/asr_postprocess.py raw/transcripts/ --domain smart_home
后处理管道包含 11 个步骤(按顺序执行):
| 步骤 | 功能 | 说明 |
|------|------|------|
| 1. emoji 清除 | 移除 U+1F000-U+27BF 等音乐/表情符号 | 🎼🎵🎶 等 ASR 误识别 |
| 2. 日文清除 | 移除平假名+片假名 (U+3040-U+30FF) | ASR 把背景音乐误识别为日文歌词 |
| 3. 韩文清除 | 移除 Hangul (U+AC00-U+D7AF) | 同上 |
| 3b. 噪声行移除 | 删除抖音水印音、语音助手碎片、ASR元数据行 | "抖音。"、"好哇。"、"字幕来源:ASR" |
| 4. 英文歌词过滤 | 删除连续英文词行(含混合行内嵌片段,保留产品白名单) | ASR 把背景音乐误识别为英文歌词 |
| 5. 领域纠错 | 修正品牌名/产品名/唤醒词/常见错字(先长词后短词) | 见 asr_postprocess.py 的 SMART_HOME_CORRECTIONS |
| 5b. 型号中文数字修复 | D两百→D200、A一百Pro→A100 Pro、PM二点五→PM2.5、六幺八→618 | 6种修复模式,PM小数优先 |
| 6. 重复句去重 | 去除连续重复的句子 | ASR 有时重复输出同一句 |
| 7. 纯音乐标记 | 中文<15字 → 标记为"背景音乐为主" | 避免把无口播内容误当文案分析 |
质量验证检查清单(报告生成前必须全部通过):
| 检查项 | 合格标准 |
|--------|----------|
| Emoji 残留 | 0 个文件 |
| 日文残留 | 0 个文件 |
| 品牌名错误 | 0 个文件 |
| 中文数字型号 | 0 个(D两百/A一百Pro 等已修复为 D200/A100 Pro) |
| 抖音噪声行 | 0 个("抖音。"等已移除) |
| ASR 元数据行 | 0 个("字幕来源:ASR" 已移除) |
| 重复视频 | 0 条(按 aweme_id 去重) |
| 纯音乐标记 | 中文<15字的视频已标记 |
| 清洗标记 | 全部文件含 ---已清洗(asr_postprocess)--- |
关键原则:清理脚本必须直接操作报告生成脚本所读取的源文件(
.txt),而不是操作中间 JSON 副本。清理完成后,删除所有中间 JSON 文件,确保 .txt 是唯一数据源。
2.8 ASR Prompt 优化
两个 ASR 脚本(extract_douyin_transcripts.py 和 siliconflow_asr_batch.py)均已向 SiliconFlow API 传入 prompt 参数,引导 ASR 模型正确识别领域词汇:
"prompt": "华为鸿蒙智家 小艺管家 悦彰 Sound X 中控屏 智能面板 全屋智能 PLC ZigBee 场景模式 一键离家 观影模式"
如果分析非智能家居领域的博主,需修改 asr_postprocess.py 中的领域纠错字典和 ASR prompt。
Step 3:风格画像(LLM 6维分析)
3.1 分析维度
将 N 条视频文案传入 LLM,从以下6个维度分析博主风格。标准 prompt 模板见 references/llm_prompts.md 模板1。
| 维度 | 分析内容 | 输出格式 | |------|----------|----------| | 语气语调 | 正式/轻松/搞笑/煽情/专业... | 标签 + 评分 + 分析段落 | | 结构节奏 | 开头钩子→铺垫→高潮→结尾 | 结构化描述 + 时间节奏 | | 话题偏好 | 常讲的话题TOP10 | 话题列表 + 频次百分比 | | 句式习惯 | 短句/长句/问句/感叹句 | 比例数据 + 典型例句(标注来源视频) | | 标签/关键词 | 常用标签、高频词汇TOP20 | 词频统计表 | | 情感节奏 | 情绪起伏曲型 | 节奏描述 + 情感曲线 |
3.2 分段分析策略(40条+)
当视频>40条时,分4组(每组10条)分别分析,最后合并:
组1分析 → 风格画像片段1
组2分析 → 风格画像片段2
组3分析 → 风格画像片段3
组4分析 → 风格画像片段4
↓
合并分析(LLM合并4个片段)
↓
最终风格画像
3.3 时间衰减权重(L3+)
在LLM prompt中标注视频时间段: "以下视频中,前5条为最近1个月发布,请在分析中重点参考。中间5条为1-3个月前发布。最后5条为更早的视频。"
3.4 输出
MD文件,包含完整的6维分析结果。最终转换为 01_博主画像.docx。
Step 4:内容自动分类
4.1 三维分类
将所有视频文案传入LLM,从三个维度分类。标准 prompt 模板见 references/llm_prompts.md 模板2。
维度1:内容类型(多选)
- 产品测评、场景展示、知识科普、促销活动、用户体验、开箱、教程、日常Vlog、观点评论、其他
维度2:情感驱动类型
- 痛点驱动、愿景驱动、对比驱动、故事驱动、数据驱动、情绪驱动
维度3:目标受众推断
- LLM从内容推断目标受众(标注为"推断结果")
- 对B站可抓取评论区关键词辅助推断
4.2 统计与可视化
生成分类统计表,包含每个类型的数量和占比。
4.3 输出
03_内容分类统计.docx— 分类统计表- 内容类型分布饼图(PNG,嵌入docx)
Step 5:创作公式提炼
5.1 公式提取
LLM分析高频视频的结构,提炼创作公式。标准 prompt 模板见 references/llm_prompts.md 模板3。
- 每个公式含:名称、适用场景、结构模板、关键词池、示例片段
- L1: 1-2个公式,L2: 3-5个,L3+: 5-10个
5.2 公式模板格式
公式名称:痛点三段式
适用场景:产品测评类
结构模板:
【开头】还在为XXX烦恼吗?(痛点钩子,2-3秒)
【中间】这款产品解决了我的三个问题(解决方案,30-40秒)
一、... 二、... 三、...
【结尾】如果你也遇到同样问题,可以试试看(行动号召,5-8秒)
关键词池:还在为、烦恼、解决了、三个问题、试试看
原文示例:[从原始文案中截取1-2个典型片段,标注来源视频]
5.3 输出
04_创作公式提炼.docx
Step 6:高级分析(L3+级别专属)
根据级别执行对应高级分析。详细规则参考 references/level_specs.md。
6.1 风格稳定性分析(L3+)
- 计算N条内容的风格一致性
- 识别风格突变点
- 输出
06_风格稳定性分析.docx
6.2 话题演变趋势(L3+)
- 按时间顺序追踪话题变化
- 识别上升/稳定/衰退话题
- 输出
07_话题演变趋势.docx(含折线图)
6.3 互动数据分析(L3+,原"爆款因子")
- 抖音/B站:取互动指数TOP 20%作为"爆款样本"
- 互动指数 = 点赞×1 + 评论×3 + 分享×5 + 收藏×2
- 对比爆款 vs 普通视频的内容差异
- 小红书/快手/视频号:互动数据不完整时标注为"内容特征分析"
- 输出
08_互动数据分析.docx
6.4 季度风格对比(L4+)
- 比较近3个月 vs 3-6个月 vs 6-12个月的风格差异
- 输出
09_季度风格对比.docx
6.5 内容矩阵图谱(L4+)
- 话题 × 内容类型热力图
- 使用
scripts/visualization.py的generate_heatmap() - 输出
10_内容矩阵图谱.docx(含热力图)
6.6 发布规律分析(L5+)
- 分析发布时间的星期×小时分布
- 建议最佳发布时间
- 输出
11_发布规律分析.docx
6.7 目标受众推断(L5+)
- LLM推断目标受众标签(年龄、职业、兴趣)
- 明确标注为"LLM推断,非平台实际数据"
- 输出
12_目标受众推断.docx
6.8 年度风格演变(L6)
- 12个月风格变化曲线
- 输出
13_年度风格演变.docx
6.9 内容策略建议(L6)
- 基于全量分析的策略建议
- 输出
14_内容策略建议.docx
Step 7:格式转换 & 输出
7.0 依赖预检(执行前必做)
# matplotlib 预检(L3+需要图表)
try:
import matplotlib
except ImportError:
subprocess.run([
"{{PIP}}",
"install", "matplotlib"
])
7.1 智能格式选择
| 产物 | 内容性质 | 目标格式 | 转换工具 |
|------|----------|----------|----------|
| 01-14 全部报告 | 叙述+表格 | docx | scripts/md_to_docx.py |
⚠️ 统一使用 DOCX 格式:所有 14 份报告统一输出为 DOCX。DOCX 已包含叙述文字 + 内嵌数据表格,功能完全覆盖 XLSX。同时生成 DOCX + XLSX 会导致内容重复(同一份数据表格出现两次),仅增加用户清理负担。 若用户明确要求某份报告额外导出 XLSX(如需在 Excel 中排序/筛选原始数据),可按需单独生成。 格式转换调用方式:必须使用
subprocess.run([python_exe, script_path, md_path, output_path])调用转换脚本,不要使用os.system()。os.system()在路径包含中文字符(如"博主分析库")时会导致命令拼接异常。
7.2 图表生成(L3+)
使用 scripts/visualization.py 生成:
- 风格雷达图 →
generate_style_radar() - 内容类型饼图 →
generate_content_pie() - 话题趋势折线图 →
generate_topic_trend() - 内容矩阵热力图 →
generate_heatmap() - 发布规律热力图 →
generate_publish_heatmap() - 图表嵌入docx →
embed_chart_in_docx()
7.3 文件组织
按方案A(博主身份归类)组织输出目录。
处理期间的目录结构(含中间文件):
{{LOCAL_ROOT}}/blogger_lib/
├── 博主身份索引.xlsx ← 全局索引(跨博主)
├── {博主名称}/
│ ├── 博主信息.json ← 博主身份(sec_uid等,持久保留)
│ └── {平台}_{账号名称}/
│ └── {级别}_{日期}/
│ ├── 01_博主画像.docx ← 最终交付物
│ ├── 02_视频文案合集.docx
│ ├── ...(14份 DOCX)
│ ├── md_temp/ ← 中间文件(清理时删除)
│ ├── charts/ ← 中间文件(清理时删除)
│ ├── 分析元数据.json ← 分析摘要(持久保留)
│ └── raw/ ← 中间文件(清理时删除)
│ ├── metadata.json
│ └── transcripts/
清理后的最终目录结构(只保留交付物 + 必要元数据):
{{LOCAL_ROOT}}/blogger_lib/
├── 博主身份索引.xlsx
├── {博主名称}/
│ ├── 博主信息.json ← 保留:增量分析时复用 sec_uid
│ └── {平台}_{账号名称}/
│ └── {级别}_{日期}/
│ ├── 01_博主画像.docx ← 最终交付物
│ ├── 02_视频文案合集.docx
│ ├── ...(14份 DOCX)
│ └── 分析元数据.json ← 保留:增量检测时读取级别/日期/视频数
分析元数据.json 规范
清理前生成,清理后保留。包含增量检测所需的全部信息:
{
"blogger": "博主名称",
"platform": "douyin",
"sec_uid": "MS4w...",
"level": "L6",
"analysis_date": "2026-07-15",
"video_count": 81,
"video_ids": ["7423xxx", "7422xxx", "..."],
"asr_success": 75,
"asr_failed": 3,
"reports": ["01_博主画像.docx", "02_视频文案合集.docx", "..."],
"style_score": 88,
"style_consistency": 96
}
video_ids字段是增量检测的关键——清理删除raw/metadata.json后,这是已分析视频ID列表的唯一来源。
7.4 清理(强制执行)
⚠️ 格式转换并验证成功后,必须清理所有中间文件,只保留 DOCX 最终交付物。 用户偏好:MD 仅可作为中间格式,最终交付必须为 WPS 可编辑格式(DOCX)。
清理范围:
| 操作 | 对象 | 说明 |
|------|------|------|
| 删除 | md_temp/ 目录 | 14 个 .md 中间文件,已转换为 DOCX |
| 删除 | raw/ 目录 | metadata.json、transcripts/ 等过程数据 |
| 删除 | charts/ 目录 | 图表已在 DOCX 中内嵌 |
| 删除 | 根目录 .md 文件 | 如有散落的 MD 文件一并清理 |
| 保留 | 博主信息.json | 博主 sec_uid 等身份信息,增量分析时复用 |
| 保留 | 分析元数据.json | 分析级别/日期/视频数/风格评分,增量检测时读取 |
| 保留 | 所有 .docx | 最终交付物(统一 DOCX 格式,含叙述+表格) |
| 保留 | 博主身份索引.xlsx | 全局索引(在工作空间根目录,数据表类产物可用 XLSX) |
import shutil, os, glob
# 清理中间目录
for d in ["md_temp", "raw", "charts"]:
p = os.path.join(output_dir, d)
if os.path.exists(p):
shutil.rmtree(p, ignore_errors=True)
# 清理根目录散落的 MD 文件
for md_file in glob.glob(os.path.join(output_dir, "*.md")):
try:
os.remove(md_file)
except Exception:
pass
- 最终交付目录只包含
.docx、博主信息.json和分析元数据.json - 更新
博主身份索引.xlsx(全局索引为数据表类产物,保留 XLSX 格式)
下游管道衔接
分析产出的 DOCX 报告不是终点,而是文案生成管道的上游素材源:
博主分析 DOCX 报告
│
▼ transform_to_libraries.py(外部转换器,位于 copywriter 管道 / 工作空间,未随本技能打包)
│ 解析 4 种 DOCX 格式 → 生成结构化 JSON 原料库
│ 含 ASR 深度清洗(型号错字 D两百→D200、痛点语义分级、无效视频过滤)
│
▼ copywriter 技能(~/.workbuddy/skills/copywriter/)
│ 选题合成(跨博主钩子×痛点×产品组合)→ LLM 写文案 → 说人话过滤器
│
▼ 纯口播文案 DOCX
ℹ️ 外部转换器说明:
transform_to_libraries.py不属于本技能,它随copywriter技能或工作空间(博主分析库根目录)提供。本技能只负责产出 DOCX 报告,转换步骤需在其所在管道单独运行。
刷新原料库:当有新的博主分析报告或增量更新后,需重新运行(在 copywriter 管道 / 工作空间执行,非本技能目录):
cd "{{LOCAL_ROOT}}/blogger_lib" && "{{PYTHON}}" transform_to_libraries.py
注意:asr_postprocess.py 现已包含型号中文数字修复(D两百→D200、A一百Pro→A100 Pro、PM二点五→PM2.5 等 6 种模式)。外部转换器 transform_to_libraries.py 的 clean_asr() 作为二级清洗补充,处理残留的 ASR 型号错字。两层清洗确保下游 JSON 原料库中的型号干净。
DOCX 统一清洗(方法B — 出口治理)
当 02_视频文案合集.docx 已生成后,可使用 scripts/clean_docx_transcripts.py 进行统一清洗:
# 单文件清洗
python scripts/clean_docx_transcripts.py "<docx路径>"
# 批量清洗博主分析库下所有 02_*.docx
python scripts/clean_docx_transcripts.py --all
# 预览模式(不写入,只打印清洗报告)
python scripts/clean_docx_transcripts.py "<docx路径>" --dry
功能:
- 解析 5 种 DOCX 格式(Aqara/华为/常州/杭州/深蓝)+ 已清洗统一格式(支持再清洗)
- 清洗口播文本(调用
asr_postprocess.clean_transcript全管道) - 清洗发布描述(去 emoji/hashtag/ASR元数据 + 品牌纠错)
- 剥离 ASR 元数据行
- 视频编号重新连续化(#001, #002, ...)
- 统一输出格式(标题 + stats摘要 + 视频条目 + 分隔线)
- 两步走生成(先算stats再写文档,避免stats显示0)
- 自动备份原始文件为
02_视频文案合集_原始备份.docx
断点续传机制
执行长任务(L4+级别)时,每完成一个Step即保存中间结果:
Checkpoint文件:.workbuddy/checkpoints/blogger_analyzer_{timestamp}.json
{
"blogger_id": "...",
"current_step": 3,
"completed_steps": [0, 1, 2],
"step_outputs": {
"step_1": "raw/metadata.json",
"step_2": "raw/transcripts/"
}
}
任务中断后,读取checkpoint从上次中断的步骤继续。
进度反馈
执行过程中定期展示进度:
[Step 1] 平台识别 ████████████████████ 100%
抖音博主:XXX | 粉丝:12.3万 | 分析级别:L3深度版
[Step 2] 内容提取 ████████░░░░░░░░░░░░ 40% (16/40)
✓ video_001.txt ✓ video_002.txt ⏳ video_003.txt...
[Step 3] 风格分析 ░░░░░░░░░░░░░░░░░░░░ 等待中
容错机制
- 平台识别失败 → 询问用户手动指定平台
- 单条视频提取失败 → 跳过,继续处理其他视频,记录到error_log
- LLM分析超时 → 自动重试(最多3次),降级为分段分析
- 格式转换失败 → 保留.md文件,提示用户手动转换
- 全部步骤完成 → 展示执行摘要(成功X条、失败Y条、耗时、成本)
关键教训与防错机制
以下教训来自实际执行中遇到的问题,已通过代码改进和流程变更来防止再次发生。
教训1:清理脚本必须操作源文件,而非中间副本
问题:deep_clean.py 清理了一个 JSON 文件,但报告生成脚本读取的是 .txt 文件。清理 JSON 后删除它,重新生成报告时又回到了未清理的原始 ASR 输出。
修复:asr_postprocess.py 直接清理 .txt 文件(原地覆盖),并在文件头添加 ---已清洗(asr_postprocess)--- 标记。清理后删除所有中间 JSON 文件。
教训2:ASR 必须传入领域 prompt
问题:SiliconFlow SenseVoiceSmall 不传 prompt 时,品牌名识别率极低(华为鸿蒙智家→华为鸿门/鸿梦/鸿焖/红木/红焖等 15+ 种错误变体)。
修复:两个 ASR 脚本均向 API 传入 prompt 参数,包含领域高频词汇。
教训3:视频去重必须在 ASR 之前
问题:TikHub API 偶尔返回重复视频(相同 aweme_id),导致 84 条中 3 条是重复的,浪费 ASR API 调用且在报告中产生重复内容。
修复:fetch_douyin_videos_api.py 在返回视频列表前自动按 aweme_id 去重。
教训4:两个 ASR 脚本必须有统一的后处理
问题:extract_douyin_transcripts.py 有一个最小化的纠错字典(12 条,含自映射错误),siliconflow_asr_batch.py 完全没有后处理。两者输出格式也不一致。
修复:创建 asr_postprocess.py 统一模块,两个脚本都导入并调用。输出格式统一为 视频序号: 001 / 视频ID: xxx / ... 格式。
教训5:质量验证是强制门控,不可跳过
问题:跳过质量验证直接进入报告生成,导致 emoji、日文歌词、品牌名错误出现在最终交付物中,用户多轮反馈后才修复。
修复:SKILL.md 中新增 Step 2.7 质量门控,必须在进入 Step 3 之前通过所有检查项。
教训6:避免代码重复,公共逻辑应抽取为共享模块
问题:extract_douyin_transcripts.py 和 siliconflow_asr_batch.py 有约 200+ 行完全重复的下载/音频提取/ASR调用/保存逻辑,每次修改需要同步两处,维护成本高。
修复:已创建 shared_utils.py 公共模块(含视频下载、音频提取、ASR 转写、文件保存、sec_uid 解析等函数),但截至当前两个 ASR 脚本尚未导入该模块——extract_douyin_transcripts.py 仍从 video-deconstruct-pro 的 utils 导入 load_env/format_readable_time 并自实现 download_video/extract_audio/save_transcript,siliconflow_asr_batch.py 也各自定义 download_video/extract_audio。公共逻辑尚未真正抽取消除,后续应迁移为 from shared_utils import ... 以去重。
教训7:交付目录必须只保留最终产物
问题:报告生成后,md_temp/(14个MD)和 raw/(脚本+JSON+转录)留在交付目录中,用户打开文件夹看到 133 个文件,分不清哪些是最终交付物。
修复:Step 7.4 清理步骤改为强制执行,格式转换验证后立即删除 md_temp/、raw/、charts/ 和所有 .md 文件,只保留 .docx 和 .xlsx。
合规声明
执行分析前展示:
⚠️ 合规提示:
1. 本工具通过公开网页接口获取视频元数据和字幕,不进行内容盗用
2. 分析结果仅供个人研究和内容策略参考
3. 请勿将分析结果用于商业侵权行为
4. 分析完成后,原始文案数据保存在本地,用户可控
5. 使用yt-dlp等工具时请遵守各平台服务条款
是否继续?[是] [取消]
依赖环境
| 依赖 | 状态 | 安装命令 |
|------|------|----------|
| Python 3.13 venv | ✅ | 已配置 |
| requests | ✅ | venv内(TikHub API 调用) |
| Playwright | ✅ | venv内(抖音降级方案) |
| python-docx | ✅ | venv内 |
| openpyxl | ✅ | venv内 |
| matplotlib | ✅ | Step 7.0 自动预检安装(pip install matplotlib) |
| ffmpeg | ✅ | pip install imageio-ffmpeg(自带静态二进制,不依赖系统PATH) |
| SILICONFLOW_API_KEY | ✅ | (通过 COPY_ENV_FILE / BLOGGER_ENV_FILE 环境变量指定,不要写死路径)(SiliconFlow免费ASR) |
| TIKHUB_API_KEY | ✅ | (通过 COPY_ENV_FILE / BLOGGER_ENV_FILE 环境变量指定,不要写死路径)(TikHub 抖音数据 API) |
| 短视频拆解引擎Skill | ✅ | 已安装,复用其douyin_analyzer.py + asr_transcribe.py |
⚠️ 依赖预检:extract_douyin_transcripts.py 依赖 video-deconstruct-pro Skill 的
asr_transcribe.py与utils模块(from utils import load_env, format_readable_time)。脚本在运行时通过sys.path.insert(0, <video-deconstruct-pro>/scripts)将该目录加入导入路径,因此实际依赖 video-deconstruct-pro 安装在标准路径~/.workbuddy/skills/video-deconstruct-pro/scripts/,而非 cwd 或 PYTHONPATH。若该 Skill 卸载或路径变更,import 会失败,执行前需确认该路径存在。
Skill 内置脚本
| 脚本 | 用途 |
|------|------|
| scripts/shared_utils.py | 公共工具模块(视频下载/音频提取/ASR转写/文件保存/sec_uid解析)。注意:该模块虽已创建,但两个 ASR 脚本当前尚未导入它,仍各自实现/从 video-deconstruct-pro 的 utils 导入 |
| scripts/fetch_douyin_videos_api.py | 抖音博主视频列表获取(TikHub API,全量分页,含 aweme_id 去重,推荐) |
| scripts/fetch_douyin_videos.py | 抖音博主视频列表获取(Playwright降级方案,~20条) |
| scripts/extract_douyin_transcripts.py | 抖音视频字幕提取(SSR→ASR→desc降级,ASR 内置后处理) |
| scripts/siliconflow_asr_batch.py | SiliconFlow SenseVoiceSmall 批量 ASR(独立脚本,内置后处理) |
| scripts/asr_postprocess.py | ASR 转写后处理统一模块(emoji/日文/品牌名清理 + 型号中文数字修复 + 噪声行移除 + 英文歌词过滤 + 质量验证) |
| scripts/clean_docx_transcripts.py | DOCX 统一清洗脚本(5种格式解析→统一输出 + 口播/描述清洗 + 编号连续化 + 两步走stats) |
| scripts/md_to_docx.py | Markdown转DOCX |
| scripts/md_to_xlsx.py | Markdown表格转XLSX(已弃用,仅保留供用户明确要求时使用) |
| scripts/visualization.py | 图表生成(matplotlib) |
外部复用脚本
| 脚本 | 来源 | 用途 |
|------|------|------|
| douyin_analyzer.py | video-deconstruct-pro | SSR解析 + 软字幕提取 + 视频下载 |
| asr_transcribe.py | video-deconstruct-pro | SiliconFlow SenseVoiceSmall免费ASR语音转文字 |
| utils.py | video-deconstruct-pro | SiliconFlow API配置 + 音频处理工具 |
Python路径: {{PYTHON}}
Venv路径: {{VENV_DIR}}/
输出目录: {{LOCAL_ROOT}}/blogger_lib/
ASR API Key: (通过 COPY_ENV_FILE / BLOGGER_ENV_FILE 环境变量指定,不要写死路径)
⚠️ 路径可移植性:以上为当前环境默认路径。
shared_utils.py支持以下环境变量覆盖,便于在不同机器上运行:
BLOGGER_ANALYZER_OUTPUT— 输出根目录(默认:{{LOCAL_ROOT}}/blogger_lib/)BLOGGER_ENV_FILE— .env 文件路径(默认:(通过 COPY_ENV_FILE / BLOGGER_ENV_FILE 环境变量指定,不要写死路径))BLOGGER_PYTHON_EXE— Python 解释器路径(默认: 当前 Python)TIKHUB_API_KEY/SILICONFLOW_API_KEY— API Key(优先从环境变量读取)
快速开始
用户说"分析这个博主"并给链接时,按以下流程执行:
- 解析链接 → 去重 → 历史检测
- 询问确认(级别、策略)
- 展示合规提示
- 执行分析流程(Step 1-7)
- 输出报告并 present_files
执行中需要用户确认的节点:
- 多账号身份确认
- 级别选择(自动判定 vs 手动指定)
- 增量更新 vs 完全重新分析
- 分析策略选择(独立/合并/对比)
- 合规提示确认
所有确认点在对话中展示,用户通过对话回复即可。完成分析后使用 present_files 展示所有产物文件。
SkillHub 发布版 · 部署配置(必读)
本技能不含任何 API 密钥与业务数据,已通过环境变量解耦。部署到新设备/账号时请自行提供:
- API 密钥(切勿写入技能文件):
TIKHUB_API_KEY(抖音数据)、SILICONFLOW_API_KEY(ASR);或把你的.env路径通过BLOGGER_ENV_FILE环境变量指定。 - 数据根:
{{LOCAL_ROOT}}为占位符,实际博主分析库请通过BLOGGER_ANALYSIS_DIR/BLOGGER_ANALYZER_OUTPUT环境变量指向。 - Python 运行时:需自备 venv 与依赖(openpyxl、python-docx、requests 等)。
- 未设置对应项时,技能会在运行时明确报错并提示缺失项。
安全说明:发布包内无任何
.env文件、无硬编码密钥值;密钥一律从环境变量读取。
Scan to join WeChat group