Files
MediaCrawler/mac-agent-os-main/05_tools/05_crawl/content-inspiration
butubb 2112c1a870
Deploy VitePress site to Pages / build (push) Canceled after 0s
Deploy VitePress site to Pages / Deploy (push) Canceled after 0s
feat(monitor): 抖音 Web 接口客户端 —— 绕开爬虫子进程,直接发 HTTP
移植自 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 带网关原话 / 正常返回)。
2026-10-10 17:12:25 +08:00
..

🎬 口播素材智能采集与分析系统

完全本地运行的口播灵感工坊——采集、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:

  1. cd ~/workbuddy-agent-os/agent-sync/05_tools/05_crawl/MediaCrawler
  2. python main.py --platform xhs --lt qrcode
  3. 扫描终端显示的二维码
  4. 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)
  • 提示词模板可视化编辑
  • 素材标签归一化
  • 简易剪辑时间线