基础工具与工作流 · daymade/claude-code-skills

douban-skill

Export and sync Douban (豆瓣) book/movie/music/game collections to local CSV files via Frodo API. Supports full export (all history) and RSS incremental sync (recent items). Use when the user wants to export Douban reading/watching/listening/gaming history, back up their Douban data, set up incremental sync, or mentions 豆瓣/douban collections. Triggers on: 豆瓣, douban, 读书记录, 观影记录, 书影音, 导出豆瓣.

L4 高权限 · 分级授权与审计V1 已固定执行命令安装依赖联网读写文件Dual-pass Audit
Author daymadeGitHub daymade/claude-code-skills ↗Stars 1385License MIT(仓库根 LICENSE,Copyright (c) 2025 daymade;GitHub API spdx MIT)Commit d5c4678cb5
管控等级描述 skill 的能力与建议配套的管控措施,不代表质量或安全认证,也不表示可用或不可用。是否使用由用户和管理者决定。不同 agent 宿主对权限的约束各不相同,请勿假定宿主一定会提供安全兜底。第三方 skill 版权归原作者,使用风险由使用者自行承担。

1实现原理 · 为什么它能做到

主路径绕过网页端:Douban 网页有 PoW(Proof of Work)反爬墙,作者实测 7 种抓取方案全挂,唯 Frodo API(官方移动 App 后端)可用——skill 的『为什么能实现』= 直连移动端 API。

douban-skill/SKILL.md
Douban uses PoW (Proof of Work) challenges on web pages, blocking all HTTP scraping. We tested 7 approaches — only the Frodo API works. **Do NOT attempt** web scraping
references/troubleshooting.md 存有 7 种失败方案与根因的完整日志;失败方案包括 browser_cookie3+requests、curl+cookies、Jina Reader 等。

Frodo 请求用免登录签名:python 脚本向 https://frodo.douban.com/api/v2/user/{id}/interests 发 GET,查询参数带 apiKey/_ts/_sig/os_rom;_sig 是 'GET&url编码路径&时间戳' 的 HMAC-SHA1(secret 硬编码),请求头伪装成 Douban Android App。

douban-skill/scripts/douban-frodo-export.py
raw = '&'.join(['GET', urllib.parse.quote(url_path, safe=''), timestamp])
签名只签 URL path 不签 query(第一个签名错误是 code 996);apiKey 与 HMAC_SECRET 是 APK 提取的公共移动端凭证(见下条),无登录/cookie。

凭证策略透明:脚本内硬编码的 API_KEY 与 HMAC_SECRET 是 Douban Android APK 的公开凭证、所有 App 用户共享、不标识个人;.gitleaks.toml 白名单明示这两处命中是 false positive。

douban-skill/scripts/douban-frodo-export.py
API_KEY = '0dad551ec0f84ed02907ff5c42e8ec70' HMAC_SECRET = b'bf7dddc7c9cfe6f7' BASE_URL = 'https://frodo.douban.com'
User-Agent 伪装 com.douban.frodo/7.22.0.beta9(231) Android/23(产品 Mate40/HUAWEI);.gitleaks.toml 注释:'the Frodo API key and HMAC secret are the PUBLIC Android APK credentials shared by every Douban app user…intentionally hardcoded so the skill works without any auth setup.'

全量导出逻辑:4 类(book/movie/music/game)× 3 状态(done/doing/mark)逐组合分页拉取,按 total 而非页大小判停(处理下架条目导致的短页),限速 1.5s/页 + 2s/类 + 重试退避,最终按输出文件聚合写 CSV。

douban-skill/scripts/douban-frodo-export.py
# --- Rate Limiting --- # 1.5s between pages, 2s between categories. Tested with 1200+ items. PAGE_DELAY = 1.5 CATEGORY_DELAY = 2.0 ITEMS_PER_PAGE = 50 MAX_PAGES_SAFETY = 500 # Guard against infinite pagination loops
文档记录最大静默 bug:旧版用 len(page_items)<count 判停导致 639 本只导出 499 本;现按 total 判停。preflight_check 先拉一页验证 user id(fail fast)。

增量同步走 RSS:douban-rss-sync.mjs 拉取 https://www.douban.com/feed/people/{id}/interests(近 ~10 条,无分页),用 ~/.douban-rss-state.json 状态 + CSV 行去重做每日增量。

douban-skill/scripts/douban-rss-sync.mjs
const RSS_URL = `https://www.douban.com/feed/people/${DOUBAN_USER}/interests`;
RSS 只返回最新约 10 条——文档建议先 Full Export 再叠加 RSS 日更;目录默认 ~/Downloads/douban-sync/<user_id>/(平台自适应,DOUBAN_OUTPUT_DIR 可覆盖)。

CSV 输出为 Excel 兼容格式:UTF-8 BOM(utf-8-sig)、固定列 title/url/date/rating/status/comment,rating 转 ★ 星号串,date 只取 YYYY-MM-DD。

douban-skill/scripts/douban-frodo-export.py
def write_csv(filepath, rows): """Write rows to a CSV file with UTF-8 BOM for Excel compatibility.""" with open(filepath, 'w', newline='', encoding='utf-8-sig') as f:
四文件:书.csv(读过+在读+想读)、影视.csv、音乐.csv、游戏.csv;重复运行安全(覆盖重写 + RSS 状态去重)。

2核心能力

01书/影/音/游戏收藏全量导出(分页拉 Frodo API,含 preflight 快速失败)
02RSS 增量同步(近 ~10 条/日,状态文件 + CSV 去重)
03Excel 兼容 CSV(UTF-8 BOM)+ 跨平台 Downloads 目录自适应
04接受完整 profile URL 自动提取 user id + 字符白名单校验
05预检用户存在性(fail fast on wrong ID)
06防爬路径文档化:明确『不要尝试网页抓取』并记录 7 种失败方案
07无第三方依赖:Python 3.6+ stdlib only / node 内置模块

3外部依赖

KindDependency / Endpoint
apiDouban Frodo API(官方移动 App 后端,HMAC-SHA1 签名 + 硬编码公开 app 凭证 + 伪装 App UA)
networkDouban RSS 订阅源(增量同步)
networksubject URL 前缀(book/movie/music/game 域名,仅写入 CSV 作为链接,不请求)

4管控建议与判定依据

建议配套管控措施
面向 Agent
分级或逐次授权,建议在沙箱运行
面向管理者
审批流程、可回滚、全程审计
判定依据(文件路径与关键语句摘要)
  • scripts/: 执行本地脚本或命令: scripts/douban-frodo-export.py(python3 或 uv run)
  • scripts/ 或 SKILL.md: 声明动态安装外部语言包依赖
  • 网络端点: 声明外部网络访问: GET https://frodo.douban.com/api/v2/user/{user_id}/interests?type=…&status=
  • 本地工作目录: 文件读写与工件输出: ~/Downloads/douban-sync/<user_id>/{书,影视,音乐,游戏}.csv(UTF-8 BOM;DOUBAN_OUTPUT_
审计说明: 。无个人凭证读取(硬编码的是 APK 公开凭证并配 gitleaks allowlist 明示)、输出仅落本地 CSV;黄色来自:① 网络外发——免登录直连 frodo.douban.com(官方移动后端)与 www.douban.com RSS,外发对象单域可预期;② 访问方式属灰区——用 APK 提取的公开凭证 + 伪造 Android App User-Agent 冒充官方移动客户端、绕过网页 PoW 反爬墙做分页全量采集(对任意公开 user id),是能力级『移动端 API 冒充 + 批量采集』面,有 ToS/风控/接口稳定性风险(作者已在文档中如实记录 7 种方案取舍)。数据仅存本地、无个人密钥接触、无隐蔽外发,故不到橙色/红色,判黄。

5第二遍独立确认

  • [ok] Frodo 端点与签名实现真实存在 — fetch_json 用 urllib.request.urlopen 请求 f'{BASE_URL}{api_path}?{query}';compute_signature 只签 urlencoded path;apiKey/_ts/_sig/os_rom 参数逐字在 preflight_check/fetch_all_interests 中。
  • [ok] 硬编码凭证属性(公共 APK 凭证非个人密钥) — 脚本注释 + .gitleaks.toml allowlist(regexes 列两个值)互相印证:'the Frodo API key and HMAC secret are the PUBLIC Android APK credentials';脚本不读任何个人凭证。
  • [ok] 分页判停按 total 而非页大小(历史 bug 已修) — fetch_all_interests 中 'if len(all_items) >= total: break' 与 troubleshooting.md 的 639→499 教训记录一致;MAX_PAGES_SAFETY=500 保险存在。
  • [ok] RSS 增量与去重逻辑 — douban-rss-sync.mjs 的 RSS_URL、STATE_FILE (.douban-rss-state.json)、isAlreadyInFile 去重、CSV_HEADER BOM 前缀 '' 逐字可查。
  • [ok] 注入面反查:user_id 白名单双实现 — python:re.match(r'^[A-Za-z0-9._-]+$', user_id) 后 sys.exit(1);mjs:同正则校验 + douban.com/people/ URL 提取;两处都在发起请求前。
  • [ok] 网络端点清单无漏网 — 全目录扫描仅 frodo.douban.com(运行时)与 www.douban.com(RSS);subject URL 前缀仅拼 CSV 链接;无遥测/无第三方回调。
  • [ok] 功能声明 vs 实际能力夸大检查 — description 的每项能力(全量导出/RSS 增量/CSV BOM/免登录/preflight)都有代码行兑现;限制清单(长评笔记广播不导出等)与实现一致(interests API 无评论正文导出)。
  • [ok] 元数据(commit/license/stars) — 本地 HEAD == pin d5c4678cb5d4fd6acc9c922690df035dbd33d247;GitHub API:MIT、stars 1385(2026-09-09 实采)、pushed_at 2026-09-09T12:33:29Z。

6结论

  • 真能导出:豆辨无官方导出、网页 PoW 反爬,唯 Frodo 移动端 API 可走通——这是被 7 种失败验证过的唯一可行路径。
  • 零第三方依赖:Python stdlib / node 内置即可跑,无 cookie/无浏览器/无登录。
  • 防呆细节到位:total 判停、500 页保险、指数重试、限速、BOM、user_id 白名单——导出不会静默丢数据。
  • 诚实边界 + 凭证透明:不能导出什么写得清楚,公共 APK 凭证用 gitleaks allowlist 主动声明。
  • 全量+RSS 增量双轨,可长期自动备份。
  • 适合: 适合豆瓣用户备份自己的书影音游标记历史(导出 CSV 归档/迁移/做年度盘点)、配合 RSS 做每日增量同步的长期备份场景;对数据主权敏感、想脱离平台锁定的人有用。技术门槛低:设 DOUBAN_USER 环境变量即可跑。
    不适合: 不适合需要导出长评/读书笔记/广播等 Frodo interests API 之外内容的人;不适合需要按单一类型筛选或访问私有/登录态数据的场景(静默返回 0 条);不适合要在生产环境批量采集他人豆瓣数据的用途(ToS/合规风险,作者也未如此主张);不适合对『冒充移动 App 客户端访问未公开 API』有合规顾虑的组织环境。
    Install Agent-Ready
    ① Verified Mirror 2026-09-09
    Option A · Direct DownloadDownload douban-skill.tar.gz
    sha256: afd320841b31f4f4…
    Option B · Copy Guide for Agent
    install.json
    agent 读 JSON 指南后会自动从本站下载安装,无需更多说明。
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit d5c4678cb5.