移植自 mac-agent-os 的 mediacrawler_adapter:不起子进程、不开页面,用浏览器里那份
登录态直接调抖音 Web 接口。产物键名照抄 store/douyin,所以 ingest 那条链路一个字不用改。
**目前能用的(真环境实测,非推断)**:
profile/other : 200, 7075 字节 —— 博主主页指标(粉丝/获赞/作品数/昵称)
aweme/detail : 200, 45425 字节 —— 单条作品详情(含点赞/评论/收藏/分享)
**目前不能用的:作品列表 `aweme/post`。** 两个互相独立的原因:
1. 这个接口被抖音单独升级成了真校验:不带 x-tt-argus 回 403「Uifid Not Found」,
带上 dummy 值回 200 + **空 body**。也就是说「头在不在」骗得过,「真校验」过不了。
同一套头打 profile/other 和 aweme/detail 都是通的 —— 抖音是挑着接口加保护的,
挑中的恰好是「批量拉作品列表」这个最敏感的动作。
2. 改走页面截获也不行:CDP 浏览器打开博主主页会落到「验证码中间页」(当天大量探测的
代价,过几小时要重测)。
所以现在的边界是:**已知作品的指标刷新能做,自动发现新作品做不了**。
**排查中控住变量后得到的两条事实**(都写进注释了):
· `Accept` / `Accept-Language` / `Referer` 才是主页接口能返回真数据的原因 —— 只有
UA+client hints+Cookie 时是 200 但仅 121 字节的空壳,补上这三个头变 7074 字节。
(我先前猜的 sec-ch-ua 不是关键。)
· 因此 UA 与 client hints 必须**成套地取自同一个浏览器**,所以 BrowserIdentity 一次
从 CDP 取齐 cookie + UA + hints,而不是各自写死。
「200 + 空 body 必须当场报错」也是刻意写死的:放过去它会在下游变成「这个博主没作品」,
把一次失败伪装成一条正常结果 —— 爬虫那条路正是这么栽的,还被翻译成「账号被封」。
测试 +11:cookie 解析、请求头成套性(含 uifid 缺失/回退)、产物键名与 store 对齐、
以及 _get 的三条失败路径(空 body / 403 带网关原话 / 正常返回)。
14 KiB
🎬 口播素材智能采集与分析系统
完全本地运行的口播灵感工坊——采集、AI 分析、智能下载、统一检索,隐私安全零成本。
版本:v1.0.0
适用环境:Mac M1 / 16GB RAM / macOS
作者:ghai
日期:2026-04-28
一、这是什么?
一个个人口播创作者的素材灵感管理系统。解决的核心问题:
| 痛点 | 解决方案 |
|---|---|
| 素材散布在抖音/小红书/B站 | 一键采集元数据到本地 SQLite |
| 收藏夹大量 404 | AI 判断价值 → 自动下载到本地 |
| 看标题判断不了口播价值 | 本地 LLM 自动提取金句/情绪/结构 |
| 不想上云、不想付费 | 全部跑在本机,零网络依赖(采集除外) |
一句话:搜得到、看得懂、存得住、找得快。
二、系统架构
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ collect.py │────→│ analyze.py │────→│ app.py │
│ 多平台采集 │ │ AI 分析 │ │ Web 界面 │
└──────┬──────┘ └──────┬───────┘ └──────┬──────┘
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ JSONL 存档 │ │ oMLX 本地LLM │ │ SQLite 索引 │
│ data/raw/ │ │ Qwen2.5-VL │ │ data/db │
└──────────────┘ └──────────────┘ └──────┬───────┘
│
┌──────▼───────┐
│downloader.py │
│ yt-dlp 下载 │
└──────┬───────┘
│
▼
~/workbuddy-agent-os/agent-local/materials/
技术选型
| 组件 | 选型 | 为什么 |
|---|---|---|
| 采集引擎 | MediaCrawler (Playwright) | 主流平台支持最全 |
| AI 大脑 | oMLX + Qwen2.5-VL-3B-8bit | 本地免费,3B 模型足够 JSON 输出 |
| 结构化存储 | SQLite (WAL 模式) | 零配置,16GB 无压力 |
| 媒体下载 | yt-dlp | 支持平台最多 |
| Web 界面 | Gradio | Python 原生,开发最快 |
| 配置管理 | YAML | 人类可读,注释友好 |
三、快速开始
3.1 环境准备
# 确认 Python 环境
~/.workbuddy/binaries/python/envs/agent-os/bin/python3 --version
# 应输出: Python 3.13.12
# 确认 oMLX 运行中
curl -s http://localhost:8000/v1/models -H "Authorization: Bearer omlx" | python3 -c "import sys,json; [print(m['id']) for m in json.load(sys.stdin)['data']]"
# 应输出: Qwen2.5-VL-3B-Instruct-8bit
3.2 安装依赖
~/.workbuddy/binaries/python/envs/agent-os/bin/pip install gradio yt-dlp
3.3 初始化数据库
cd ~/workbuddy-agent-os/agent-sync/05_tools/05_crawl/content-inspiration
~/.workbuddy/binaries/python/envs/agent-os/bin/python3 collect.py --init-db
# 输出: [OK] 数据库初始化完成
3.4 开始使用
# 1. 采集素材(需要先配置 MediaCrawler Cookie)
python collect.py -p xiaohongshu -k "普通人逆袭"
# 2. AI 分析(需要 oMLX 运行中)
python analyze.py
# 3. 启动 Web 界面
python app.py
# 打开 http://127.0.0.1:7860
# 4. 下载视频(在 Web 界面标记后)
python downloader.py
四、项目结构
content-inspiration/
├── SKILL.md # 技能身份证(system/user 能力说明)
├── README.md # 本文件(完整项目说明)
├── config.yaml # 所有配置(平台/模型/存储/下载/Web)
├── schema.sql # 数据库表结构(3 张表)
├── requirements.txt # Python 依赖清单
│
├── collect.py # 采集脚本(MediaCrawler 封装)
├── analyze.py # AI 分析脚本(oMLX 调用 + JSON 解析)
├── downloader.py # 下载脚本(yt-dlp 封装)
├── app.py # Web 界面(Gradio)
├── utils.py # 通用工具(配置/数据库/日志/JSONL)
│
├── data/
│ ├── raw/ # JSONL 原始采集存档
│ │ └── 2026-04-28_xiaohongshu_普通人逆袭.jsonl
│ └── database.db # SQLite 素材库
│
└── logs/ # 运行日志(按日期分割)
├── collect_20260428.log
└── analyze_20260428.log
与 AgentOS 的关系
~/workbuddy-agent-os/agent-sync/ ← 坚果云同步 + Git
└── 05_tools/05_crawl/
└── content-inspiration/ ← 本项目
├── 代码 + 配置 + 数据库 (同步)
└── data/raw/*.jsonl (同步)
~/workbuddy-agent-os/agent-local/ ← 本机专属,不同步
└── materials/
├── video/ ← 下载的视频
└── audio/ ← 下载的音频
- 项目代码和数据库跟随 agent-os 同步
- 下载的视频/音频在本机专属目录,不占用同步空间
- AI 分析结果可通过 AgentOS 的 inbox_refine 归档到知识库
五、配置说明(config.yaml)
# 平台和关键词
platforms:
- xiaohongshu # 目前最成熟
- douyin # 需要 Cookie
- bilibili # 支持
keywords:
- "普通人逆袭"
- "情感故事"
- "科普冷知识"
max_count: 20 # 每关键词每次采集上限
# 本地 LLM(oMLX,非 Ollama)
llm:
model: "Qwen2.5-VL-3B-Instruct-8bit"
base_url: "http://localhost:8000/v1" # oMLX 端口
api_key: "omlx" # oMLX 固定 key
timeout: 120 # 每条分析超时
temperature: 0.3 # 低温度保证稳定
# 存储路径
storage:
raw_dir: "data/raw"
db_path: "data/database.db"
media_dir: "~/workbuddy-agent-os/agent-local/materials/video"
audio_dir: "~/workbuddy-agent-os/agent-local/materials/audio"
# Web 界面
web:
host: "127.0.0.1"
port: 7860
title: "口播灵感工坊"
# 下载配置
download:
rate_limit: "1M" # 速率限制,防 IP 封禁
retries: 3 # 重试次数
六、脚本详细说明
collect.py — 采集脚本
功能:从主流平台采集内容元数据(标题、描述、封面、互动数据等),不下载视频本体。
# 初始化数据库
python collect.py --init-db
# 指定平台和关键词采集
python collect.py -p xiaohongshu -k "科普冷知识"
# 指定数量
python collect.py -p xiaohongshu -k "情感故事" -n 10
# 按 config.yaml 批量采集(遍历所有平台×关键词)
python collect.py
输出:
data/raw/YYYY-MM-DD_平台_关键词.jsonl— 原始数据存档data/database.db— 写入 materials 表(自动去重)
前置条件:MediaCrawler 已安装并配置好 Cookie。
analyze.py — AI 分析脚本
功能:对未分析的素材调用本地 oMLX(Qwen2.5-VL-3B),提取口播可用信息。
# 分析所有未分析的素材
python analyze.py
# 只分析前 10 条(测试用)
python analyze.py -n 10
# 只看有多少待分析(不执行)
python analyze.py --dry-run
# 重试之前失败的记录
python analyze.py --retry-failed
输出:写入 analysis 表,字段包括:
tags— AI 标签(科普、情感、冷知识…)golden_quote— 可直接引用的金句core_idea— 核心立意structure— 口播脚本结构emotion— 整体情绪worth_downloading— 是否推荐下载
注意:串行执行(每次只处理一条),16GB Mac 不会 OOM。每条间隔 1 秒。
downloader.py — 下载脚本
功能:下载标记为 pending 的素材视频到本地。
# 下载所有标记为待下载的
python downloader.py
# 下载所有 AI 推荐的
python downloader.py --all
# 限制数量
python downloader.py -n 5
# 手动指定 URL
python downloader.py -u "https://v.douyin.com/xxx"
输出:文件保存到 ~/workbuddy-agent-os/agent-local/materials/video/,文件名格式:
xiaohongshu_作者名_标题前20字_日期.mp4
app.py — Web 界面
功能:本地浏览器访问的素材管理界面。
python app.py
# 打开 http://127.0.0.1:7860
功能清单:
- 🔍 关键词搜索(标题/描述/标签/金句)
- 📋 平台/情绪/下载状态筛选
- 📊 实时统计(总数/已分析/已下载/AI推荐)
- 📖 素材详情(AI 分析完整结果)
- 📥 一键标记下载
- 📝 金句可直接复制
utils.py — 工具函数
| 函数 | 用途 |
|---|---|
load_config() |
加载 config.yaml |
get_db() / init_db() |
数据库连接/初始化 |
setup_logger() |
日志配置 |
parse_jsonl() / save_jsonl() |
JSONL 读写 |
check_omlx() |
检测 oMLX 可用性 |
truncate_text() |
文件名安全截断 |
七、数据库设计
materials 表(素材元数据)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | INTEGER | 主键 |
| platform | TEXT | 平台(xiaohongshu/douyin/bilibili) |
| original_id | TEXT | 平台内唯一 ID |
| url | TEXT | 原始链接 |
| title | TEXT | 标题 |
| description | TEXT | 描述/正文 |
| author | TEXT | 作者 |
| cover_url | TEXT | 封面图 |
| music_name | TEXT | BGM |
| like_count | INTEGER | 点赞数 |
| analyzed | INTEGER | 0未分析/1已分析/2失败 |
| download_status | TEXT | none/pending/downloading/done/failed |
| local_files | TEXT | JSON(本地文件路径) |
| raw_json | TEXT | 完整原始数据备份 |
analysis 表(AI 分析结果)
| 字段 | 类型 | 说明 |
|---|---|---|
| material_id | INTEGER | 关联素材 |
| tags | TEXT | AI 标签(逗号分隔) |
| golden_quote | TEXT | 金句 |
| core_idea | TEXT | 核心立意 |
| structure | TEXT | 脚本结构 |
| emotion | TEXT | 情绪 |
| worth_downloading | TEXT | yes/no/maybe |
| download_reason | TEXT | 下载理由 |
| raw_model_output | TEXT | 模型原始输出(调试) |
collect_batches 表(采集批次记录)
记录每次采集的平台、关键词、数量、状态,方便回溯。
八、知识库索引卡片
采集并分析后的素材,可以在知识库中生成索引卡片(存入 03_knowledge/50_resources/):
文件名格式:{hostname}_{YYYYMMDD}_{slug}.md
示例:Redmi-12C_20260428_xiaohongshu-普通人逆袭.md
---
title: 普通人逆袭合集
source_url: https://www.xiaohongshu.com/explore/xxx
local_path: ~/workbuddy-agent-os/agent-local/materials/video/xiaohongshu_作者_标题.mp4
type: video
platform: xiaohongshu
collected_by: Redmi-12C
collected_at: 2026-04-28
tags: [口播素材, 励志, 逆袭]
---
一句话说明:适合逆袭主题口播开头,情绪张力强。
collected_by 字段防止多机同步时文件名冲突。
九、MediaCrawler 配置(前置条件)
安装
cd ~/workbuddy-agent-os/agent-sync/05_tools/05_crawl
git clone https://github.com/NanmiCoder/MediaCrawler.git
cd MediaCrawler
~/.workbuddy/binaries/python/envs/agent-os/bin/pip install -r requirements.txt
配置 Cookie
各平台需要在首次使用前扫码登录获取 Cookie:
cd ~/workbuddy-agent-os/agent-sync/05_tools/05_crawl/MediaCrawlerpython main.py --platform xhs --lt qrcode- 扫描终端显示的二维码
- Cookie 自动保存,后续无需重复登录
配置本项目
安装完成后,更新 config.yaml:
crawler:
project_path: "~/workbuddy-agent-os/agent-sync/05_tools/05_crawl/MediaCrawler"
十、性能与资源管理(16GB Mac)
| 场景 | 内存占用 | 建议 |
|---|---|---|
| 采集(Playwright) | ~500MB | 关闭其他浏览器 |
| AI 分析(Qwen2.5-VL-3B) | ~2GB | 关闭其他大型应用,串行执行 |
| Web 界面(Gradio) | ~300MB | 轻量,无压力 |
| 下载(yt-dlp) | ~100MB | 速率限制 1MB/s |
关键原则:分析期间不同时运行其他 AI 任务,每次只处理一条记录。
十一、常见问题
Q: oMLX 返回 500 错误?
A: Qwen3-8B-MLX-4bit 有已知问题。本系统使用 Qwen2.5-VL-3B-Instruct-8bit,不受影响。
Q: 采集没有数据?
A: 检查 MediaCrawler Cookie 是否过期,重新扫码登录。
Q: AI 分析结果不准确?
A: 3B 模型有限,可通过调整 temperature(降低=更稳定)或更换更强模型改善。
Q: 视频下载失败?
A: 抖音/小红书链接有时效性,采集后尽快下载。也可尝试 --retry-failed。
Q: 如何接入 AgentOS 自动化?
A: 可在 WorkBuddy 中创建定时自动化,例如每天凌晨执行 python analyze.py。
十二、合规提醒
- ⚠️ 仅供个人学习研究,禁止大规模抓取或商业化
- 下载的视频仅供分析借鉴,口播内容须二次原创
- 所有数据本地存储,注意定期备份
十三、未来扩展
- 定时自动采集 + 热点推送
- 向量语义搜索(接入 ChromaDB + Qwen3-Embedding)
- 提示词模板可视化编辑
- 素材标签归一化
- 简易剪辑时间线