ワークフロー&基本ツール · daymade/claude-code-skills

douban-skill

Frodo APIを介して豆瓣(Douban)の本/映画/音楽/ゲームのコレクションをローカルのCSVファイルにエクスポートおよび同期します。全履歴のフルエクスポートおよび最新アイテムのRSS増分同期に対応しています。読書/鑑賞/試聴/プレイ履歴のエクスポート、Doubanデータのバックアップ、増分同期の設定を行いたい場合、または「豆瓣/douban」のコレクションに言及された際に使用します。トリガーワード:豆瓣, 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仕組みと動作原理

Web版を回避するメインルート:DoubanのWeb版にはPoW(Proof of Work)スクレイピング防止機構があり、作者が検証した7種類のスクレイピング手法は全滅しました。公式モバイルアプリのバックエンドであるFrodo APIのみが利用可能であり、本スキルが実現できる理由はモバイル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(シークレットはハードコード)であり、リクエストヘッダーはDouban Android Appに偽装されています。

douban-skill/scripts/douban-frodo-export.py
raw = '&'.join(['GET', urllib.parse.quote(url_path, safe=''), timestamp])
署名はURLパスのみを対象とし、クエリパラメータは含みません(最初の署名エラーコードは996)。apiKey および HMAC_SECRET はAPKから抽出された公開モバイル認証情報であり(次項参照)、ログインやCookieは不要です。

透明性のある認証情報ポリシー:スクリプト内にハードコードされている API_KEY と HMAC_SECRET はDouban Android APKの公開認証情報であり、全アプリユーザーで共有され、個人を特定するものではありません。.gitleaks.toml のホワイトリストで、これら2箇所の検知が偽陽性(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 には「FrodoのAPIキーとHMACシークレットは全Doubanアプリユーザーが共有する公開Android APK認証情報であり、認証設定なしでスキルを実行できるよう意図的にハードコードされている」旨のコメントがあります。

フルエクスポートロジック:4カテゴリ(book/movie/music/game)× 3ステータス(done/doing/mark)の全組み合わせをページング取得します。ページサイズではなく total に基づいて終了判定を行い(取り下げ項目による不足ページに対応)、1.5秒/ページ + 2秒/カテゴリのレート制限とリトライバックオフを実施した上で、出力ファイルごとに集約して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
ドキュメントには最大のサイレントバグが記録されています。旧バージョンでは len(page_items)<count で終了判定を行っていたため639件中499件しかエクスポートされませんでしたが、現在は total 基準に修正されています。preflight_check で最初に1ページ取得し、ユーザーIDを検証します(フェイルファスト)。

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 で上書き可能)。

Excel互換のCSV出力:UTF-8 BOM(utf-8-sig)を採用し、固定カラム(title/url/date/rating/status/comment)、★星マーク文字列に変換された rating、YYYY-MM-DD に統一された date で出力されます。

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 の4ファイルを出力。再実行しても安全です(フルエクスポートの上書き+RSS状態による重複排除)。

2コア機能

01本/映画/音楽/ゲームのコレクション全量エクスポート(Frodo APIのページング取得、事前検証によるフェイルファストを含む)
02RSS増分同期(直近約10件/日、状態管理ファイル+CSV重複排除)
03Excel互換CSV(UTF-8 BOM)+クロスプラットフォーム対応のDownloadsディレクトリ自動判別
04プロフィールURLからのユーザーID自動抽出+文字ホワイトリスト検証
05ユーザー存在確認の事前チェック(無効なIDに対するフェイルファスト)
06スクレイピング対策の文書化:「Webスクレイピングを試行しないこと」を明記し、7つの失敗手法を記録
07サードパーティ依存ゼロ:Python 3.6+ 標準ライブラリのみ/Node.js 組み込みモジュールのみ

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偽装により公式モバイルクライアントを装い、Web版のPoW対策を回避してページング全量収集(任意の公開ユーザーID対象)を行っており、これは機能レベルでの「モバイルAPI偽装+一括収集」に該当し、利用規約、不正検知、APIの安定性リスクを伴います(作者もドキュメントで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結論

  • 確実にエクスポート可能:Doubanには公式エクスポート機能がなくWeb版のPoW対策も厳しい中、FrodoモバイルAPIのみが有効であることを7つの失敗検証を経て確立しています。
  • サードパーティ依存ゼロ:Python標準ライブラリおよびNode組み込みモジュールのみで動作し、Cookie、ブラウザ、ログイン設定が不要です。
  • 充実したエラー防止設計:totalによる終了判定、500ページ安全上限、指数バックオフ、レート制限、BOM対応、user_idホワイトリストにより、サイレントなデータ欠損を防ぎます。
  • 明確な境界と透明な認証情報:エクスポート不可な範囲を明記し、公開APK認証情報はgitleaks allowlistで明示的に宣言しています。
  • 全量エクスポート+RSS増分同期のデュアルトラックにより、持続的な自動バックアップが可能です。
  • 最適な用途: Doubanユーザーが自身の書籍・映画・音楽・ゲームの記録履歴をバックアップしたい場合(アーカイブ、移行、年間まとめ用のCSVエクスポート)、およびRSSを組み合わせた日次増分同期による長期バックアップシナリオに最適です。データ主権を重視し、プラットフォームのロックインから脱却したいユーザーに適しています。技術的ハードルも低く、DOUBAN_USER 環境変数を設定するだけで実行可能です。
    不向きな用途: Frodo interests APIの対象外である長文レビュー、読書ノート、つぶやき(广播)などのエクスポートを求めるユーザーには不向きです。単一カテゴリのみの抽出や非公開/ログイン必須データの取得が必要なシナリオには適していません(サイレントに0件が返されます)。本番環境で他人のDoubanデータを大量収集する用途(利用規約/コンプライアンスリスクがあり、作者も推奨していません)や、「公式クライアントを偽装して非公開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.