ドキュメント&知識ベース · JimLiu/baoyu-skills

baoyu-url-to-markdown

baoyu-fetch CLI(サイト固有のアダプターを備えた Chrome CDP)を使用して、任意の URL を取得して Markdown に変換します。X/Twitter、YouTube の文字起こし、Hacker News のスレッド、および Defuddle を介した一般的なページ用の組み込みアダプターが含まれています。インタラクション待機モードによってログインや CAPTCHA に対応します。ユーザーが Web ページを Markdown として保存したい場合に使用します。

L5 厳格管理 · 隔離環境と厳格な監査V2 人間監査済リバースAPI規約/コンプライアンス認証情報/セッションコマンド実行ネットワーク通信ファイル書き込みDual-pass Audit
Author JimLiuGitHub JimLiu/baoyu-skills ↗Stars 25926License MIT(仓库根 LICENSE:Copyright (c) 2026 Jim Liu;根 package.json 同声明 "license": "MIT")Commit 1567581c26
管理レベルは Skill の能力と推奨統制措置を示すものであり、品質や安全性の認証、利用可否の判定ではありません。使用の可否はユーザーおよび管理者が決定します。Agent 環境によって制約が異なるため、自動保護を仮定しないでください。第三者製 Skill の著作権は原著作者に帰属し、利用リスクは利用者が負います。

1仕組みと動作原理

エントリポイントはシェルラッパー + vendored な TS CLI:baoyu-fetch が直接 bun を exec して lib/cli.ts を実行し、CLI が URL に応じてアダプター(x / youtube / hn / generic)を選択します。

skills/baoyu-url-to-markdown/scripts/baoyu-fetch
exec bun "$script_dir/lib/cli.ts" "$@"
SKILL.md では agent に対し、${READER} を呼び出す前に bun install で依存関係を導入することを要求しています。CLI はデフォルトで非ヘッドレス(verification の discrepancy 項目を参照)であり、可視化された Chrome を起動します。

スクレイピングは puppeteer ではなく、実機 Chrome + 自作 CDP クライアント(chrome-launcher でブラウザを起動し、ws で DevTools に直接接続)に依存しています。

skills/baoyu-url-to-markdown/scripts/lib/browser/cdp-client.ts
import WebSocket from "ws";
ページ内での JS 実行には Runtime.evaluate(awaitPromise + returnByValue)を使用し、スクロール、クリック、DOM 読み取りはすべてこれを経由します。

X アダプターは DOM を読み取るだけでなくセッション機構を内蔵しています:まず CDP を使って x.com/twitter.com の cookie(auth_token と ct0 が必須)を読み取り、profile ディレクトリ配下の sidecar ファイルに cookie を平文で書き出し、次回実行時に再注入します。

skills/baoyu-url-to-markdown/scripts/lib/browser/cookie-sidecar.ts
await writeFile(filePath, JSON.stringify(data, null, 2));
ファイル名は x-session-cookies.json で、Chrome profile ディレクトリ内に配置されます(暗号化なし、パーミッション制限なし)。通常パスで cookie を読み取れない場合にログイン状態の復元に使用されます。

X のデータソースはページ自体が発行する GraphQL レスポンスです:ツールは CDP ネットワークログから /graphql/ の TweetDetail や TweetResultByRestId などのレスポンスボディを抽出して解析し、自動スクロールと「Show replies」のクリックでスレッドを展開します。

skills/baoyu-url-to-markdown/scripts/lib/adapters/x/payloads.ts
entry.url.includes("TweetDetail") ||
したがって、Twitter の非公開 API の署名ロジックをリバースエンジニアリングしているわけではありませんが、非公開エンドポイントの応答データを直接読み取っています。

YouTube アダプターは自作の InnerTube 呼び出しです:ページ内の ytcfg から INNERTUBE_API_KEY を取得し、ページコンテキスト上で POST /youtubei/v1/player を実行(credentials: 'include' でページの cookie を付与)、ANDROID クライアントを明示的に偽装します。

skills/baoyu-url-to-markdown/scripts/lib/adapters/youtube/transcript.ts
context: { client: { clientName: 'ANDROID', clientVersion: '20.10.38' } },
同一リポジトリの baoyu-youtube-transcript と同種のアプローチであり、公式 Data API を経由せずクライアント偽装を伴うリバースエンジニアリング/スプーフィング路線に該当します。

実行中の Chrome デバッグセッションを再利用可能:まず ps aux を走査して同一プロファイルかつ --remote-debugging-port を持つプロセスを探すか、プロファイル内の DevToolsActivePort ファイルを読み取って検出時に接続します。

skills/baoyu-url-to-markdown/scripts/lib/browser/profile.ts
const activePort = parseDevToolsActivePort(path.join(options.profileDir, "DevToolsActivePort"));
--cdp-url ws://… による任意のデバッグエンドポイントへの直接接続もサポートしており、設計に組み込まれたセッション乗っ取り機能にあたります。

ログインウォールや CAPTCHA に遭遇した際は強行突破せず待機モードを提供:ページ上に Cloudflare や reCAPTCHA などの出現を検知すると可視化された Chrome をポップアップ表示して手動解除を促し、進行を検知するか Enter 入力で処理を再開します。

skills/baoyu-url-to-markdown/scripts/lib/browser/interaction-gates.ts
text.includes("verify you are human") ||
デフォルトで 10 分の待機時間と 1.5 秒ごとのポーリングを設定。これが SKILL.md に記載された「Handles login/CAPTCHA via interaction wait modes」の具体的な実装です。

Markdown 生成のメインパイプラインはローカルの Defuddle/Readability + 品質スコアリングであり、品質が不十分な場合にのみターゲット URL をサードパーティサービス https://defuddle.md に渡してよりクリーンな Markdown を取得します。

skills/baoyu-url-to-markdown/scripts/lib/extract/html-to-markdown.ts
const DEFUDDLE_API_ORIGIN = "https://defuddle.md";
これが SKILL.md に「Quality Gate」が存在する理由です。ヘッドレス取得では低品質なコンテンツが暗黙的に返される可能性があるため、agent による再検査が必要です(--debug-dir により document.json/markdown.md/page.html/network.json のダンプが可能)。

2コア機能

01任意の URL → クリーンな Markdown(デフォルトは stdout、--output によるファイル保存、--format json による構造化ドキュメント出力に対応)
02サイトアダプター:X/Twitter(長文ポストや記事を含む)、YouTube(字幕)、Hacker News(ネストされたコメントツリー)、汎用 Web ページ
03YouTube 字幕取得(ページコンテキストの InnerTube + キャプション XML 解析)
04ログイン/CAPTCHA インタラクティブ待機モード(interaction 自動検出 / force 手動制御)
05メディアのダウンロードとリンク書き換え(--download-media で imgs/ および videos/ に保存、--media-dir で指定可能)
06デバッグ検証:--debug-dir で document.json / markdown.md / page.html / network.json(リクエストヘッダーおよびレスポンスボディを含む)を出力
07X セッション永続化(cookie sidecar のエクスポート/再注入)および CDP デバッグセッションの再利用
08品質ゲートウェイ(Quality Gate)ワークフロー(ヘッドレスの結果を暫定扱いとし、人間/agent による再検査後にインタラクティブモードで再取得可能)

3外部依存関係

KindDependency / Endpoint
package@mozilla/readability ^0.6.0(正文提取)
packagedefuddle ^0.17.0(本地 markdown 提取)
packagejsdom ^30.0.1(HTML 清洗/解析,未开 runScripts)
packageturndown + turndown-plugin-gfm(HTML→markdown)
packagechrome-launcher ^1.2.1(浏览器启动)
packagews ^8.18.3(CDP WebSocket 客户端)
packageunified + remark-parse + remark-gfm(媒体链接收集与重写)
clibun(CLI 运行时;shell 包装 exec bun)
cliChrome/Chromium 二进制(chrome-launcher,可用 --browser-path 指定)
clips aux(POSIX 进程扫描)与 osascript(macOS 窗口激活)
networkChrome DevTools HTTP/WebSocket 端点
api第三方 markdown 服务 defuddle.md(质量不足时把目标 URL 发过去)
networkYouTube watch 页、InnerTube player、caption 轨与 i.ytimg.com 缩略图
networkHacker News 条目页(jsdom 解析)
networkX/Twitter 页面与页面自身发出的 /graphql/ 请求(工具只观察,不构造请求)
network用户指定 URL 与页面内媒体 URL(下载时带伪造的桌面 Chrome UA)

4推奨統制措置と判定根拠

安全運用のための推奨統制措置
Agent 向け
隔離環境で実行、都度明示的な認可
管理者向け
厳格な認可、全量監査、コンプライアンス確認
判定根拠(ファイルパスと抜粋)
  • SKILL.md / 脚本: 未公開またはリバースエンジニアリングされた非公開 API の呼び出し / クライアント識別子の偽装
  • SKILL.md / 脚本参数: 自動検出の回避、ホストサンドボックスの無効化、または SSL 証明書検証のスキップ
  • SKILL.md / 会话存储: ブラウザのユーザーログイン状態およびセッション Cookie の読み取りまたは再利用
  • 本地凭据 / 浏览器配置: ユーザーのログイン Cookie/セッション/キーチェーンの読み取り: CDP Network.getCookies を経由して x.com/twitter.com の cookie を読み取り(auth_token および ct0 が必須)
  • scripts/: ローカルスクリプトまたはコマンドの実行: {baseDir}/scripts/baoyu-fetch <url> …(shell exec bun → lib/cli.ts、初回は bun i が必要)
  • 网络端点: 外部ネットワークアクセスの宣言: ユーザーが指定した対象 URL(実ブラウザでのレンダリング。汎用ページは Readability/Defuddle/defuddle.md を経由)
  • 本地工作目录: ファイルの読み書きと成果物の出力: --output で指定された Markdown/JSON(親ディレクトリは自動作成)
監査ノート: (悪意あるコードの混入ではなく、機能/ポリシーレベルの判定です。コード構造は明瞭で難読化はなく、ハードコードされたシークレットや TLS/サンドボックスのダウングレードもありません)。判定に至る 3 つの理由:①【リバースエンジニアリング/偽装】YouTube アダプターは公式 Data API を使わず、ページコンテキスト上で InnerTube リクエストを自作構築し('const response = await fetch(\'/youtubei/v1/player?key=\' + apiKey + \'&prettyPrint=false\', {' で credentials: \'include\' を付与、キーは window.ytcfg から取得)、公式クライアントを明示的に偽装しています('context: { client: { clientName: \'ANDROID\', clientVersion: \'20.10.38\' } },')。これは同一リポジトリの baoyu-youtube-transcript と同種のポリシー違反です。②【平文での認証情報保存とデバッグセッションの乗っ取り】X アダプターは auth_token/ct0 を含む x.com/twitter.com の cookie を平文で <chrome-profile-dir>/x-session-cookies.json に書き出し('await writeFile(filePath, JSON.stringify(data, null, 2));'、暗号化なし)、必要に応じて再注入します。また、DevToolsActivePort / ps aux を介して既存の Chrome デバッグセッションを乗っ取る仕組みを持ち(--cdp-url で任意の ws デバッグエンドポイントに接続可能)、--debug-dir ではリクエストヘッダーとレスポンスボディを完全にダンプします('const networkDump = await network.toJSON({ includeBodies: true });')。③【サードパーティへの外部送信とリクエスト偽装】ローカル抽出の品質が不十分な場合、対象 URL をサードパーティの https://defuddle.md に送信して Markdown を取得します。メディア取得時にはデスクトップ Chrome の UA を偽装し、ページ内容に応じて後続のクロール対象や出力ファイル名が決定されます。なお補足として、cookie は宣言された目的(ログイン必須の X コンテンツ取得)でのみ使用されており、TLS のダウングレードやエスケープ漏れによるスクリプト挿入はなく、jsdom によるページスクリプト実行も行わず、CAPTCHA に対しては強行突破ではなく待機モードを採用しています。

5二重目の独立検証

  • [ok] YouTube 适配器的逆向/冒充 — transcript.ts 有 window.ytcfg?.data_?.INNERTUBE_API_KEY、页面内 POST /youtubei/v1/player?key=…(credentials: 'include')与 context.client.clientName='ANDROID' 三处,与 Main 终裁的『逆向 youtubei + 冒充官方客户端』一致。
  • [ok] X cookie 明文 sidecar 落盘 — cookie-sidecar.ts 用 Network.getCookies 取 cookie 后 JSON.stringify 明文写入 <profile>/x-session-cookies.json(x/index.ts 指定 filename),无加密无 chmod;convert.ts 在开头尝试回灌、finally 里导出。
  • [ok] 接管已运行调试会话 — profile.ts 解析 DevToolsActivePort 并 spawnSync('ps', ['aux']) 匹配 profileDir + --remote-debugging-port;chrome-launcher.ts 支持 --cdp-url ws:// 直连与复用日志 'Reusing Chrome debugger at …'。
  • [ok] 网络日志含请求头与响应体(--debug-dir 落盘) — network-journal.ts 记录 requestHeaders / requestBody / 响应体(Network.getResponseBody),convert.ts 在写 debug 前调用 toJSON({ includeBodies: true }) 并写入 network.json。
  • [ok] 第三方 defuddle.md 兜底 — DEFUDDLE_API_ORIGIN=https://defuddle.md,构建 URL 后 fetch;通用适配器仅在 outputFormat==='markdown' 时启用该兜底,JSON 模式不会外发目标 URL。
  • [discrepancy] 文档与实现不一致(默认无头) — SKILL.md 第 93 行写 '# Default: headless capture, markdown to stdout'、quality-gate.md 亦写 'Default | Headless Chrome',但 cli.ts 默认 headless: false(convert.ts 在非交互模式传该值),实际会启动可见 Chrome(--no-startup-window)。使用前应知道默认并非无头。
  • [discrepancy] 文档与实现不一致(默认 profile 路径) — SKILL.md 写默认 ./baoyu-skills/chrome-profile,代码实际解析为按 OS 的绝对路径(XDG_DATA_HOME / Application Support / APPDATA 下的 baoyu-skills/chrome-profile),从不使用 cwd 相对路径。
  • [discrepancy] 文档未披露 cookie 导出 — SKILL.md 只写 BAOYU_CHROME_PROFILE_DIR 为『Chrome user data directory』,从未提及会导出 X cookie 到 sidecar 文件;该行为只在代码中可见——这是本次侦查中风险披露落差最大的一处。

6結論

  • 1 つの CLI で 4 種類のサイトに対応し、「取得できれば成功」とみなさず品質ゲートウェイプロセスを備えている点。
  • ログインが必要なページへの適切な対処:インタラクティブ待機モードによりユーザーが手動でログイン/CAPTCHA を解除でき、進捗を検知して自動再開する点。
  • 自作 CDP クライアントによる依存関係の最小化と高い制御性:puppeteer スタックを導入せず、chrome-launcher + ws のみで構成されている点。
  • 優れたデバッグ性:--debug-dir を指定するだけで document、markdown、page.html、network の 4 種のフォレンジック検証用ファイルを一括取得できる点。
  • 完全なメディアローカライズ:--download-media でリンクをダウンロード・書き換えし、imgs/videos を Markdown と同一ディレクトリに自己完結型で保持できる点。
  • 最適な用途: Web ページ、X の長文スレッド、YouTube 字幕、HN の議論を Markdown として保存したい個人やコンテンツ制作者に最適です。ローカルへのアーカイブ、メディアファイルの一括保存、ログインウォールの処理(1回の手動解除)が必要で、実機 Chrome および自作 CDP パイプラインの利用を許容できるユースケースに向いています。
    不向きな用途: 企業のコンプライアンス順守やプライバシー配慮が求められる環境(平文の X cookie sidecar、デバッグログのディスク保存、サードパーティ defuddle.md への外部送信)、無人での大規模バッチスクレイピング(対話型待機と実ブラウザ実行によるオーバーヘッド)、安定した公式 API が必須のパイプライン、イントラネット/社内プライベート URL や他者アカウントのセッションを対象とする用途には適していません。
    Install Agent-Ready
    ① Verified Mirror 2026-09-15
    Option A · Direct DownloadDownload baoyu-url-to-markdown.tar.gz
    sha256: 15be54497a8d6c30…
    Option B · Copy Guide for Agent
    install.json
    Agent はこの JSON ガイドから自動的にダウンロードして検証します。
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit 1567581c26.