content-parser について
content-parser は、対応プラットフォームの URL からコンテンツを抽出・整形するエージェントスキルです。本文、メタデータ、参照先を返し、単独の抽出やコンテンツ生成前の処理に使えます。
主な機能
- 01URL コンテンツとメタデータの抽出
- 02参照リンクの取得
- 03要約の任意生成
- 04コンテンツの最大長設定
- 05X/Twitter の投稿数設定
活用シーン
- 01後続のコンテンツ生成用に記事を抽出
- 02リンクを解析してページ情報を確認
- 03X/Twitter プロフィールの投稿を取得
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ marswaveai/ skills --skill content-parserインストール後、Claude Code で/content-parserを入力して読み込まれたか確認します。
同梱ファイルreferences/supported-platforms.md
詳細
使用する場面
- ユーザーが URL を提示し、その内容の抽出や閲覧を希望している
- 別のスキルが生成前に URL からソース資料を解析する必要がある
- ユーザーが「この URL を解析して」「このリンクから内容を抽出して」と依頼している
- ユーザーが「解析链接」「提取内容」と依頼している
使用しない場面
- ユーザーがすでにテキストを持っており、URL の解析が不要な場合
- ユーザーが音声/動画コンテンツの生成を希望している場合(コンテンツの抽出ではないため)
- ユーザーがローカルファイルの読み取りを希望している場合(標準のファイル読み取りツールを使用してください)
目的
対応プラットフォームの URL からコンテンツを抽出し、正規化します。本文、メタデータ、参照情報を含む構造化データを返します。コンテンツ生成スキルの前処理として、または単独でのコンテンツ抽出に役立ちます。
厳守事項
- シェルスクリプトは使用しないでください。以下の「API リファレンス(インライン)」セクションを参照して curl コマンドを組み立ててください
- API キーとヘッダーについては、以下の「API リファレンス(インライン)」セクションを参照してください
- ポーリング、エラー、インタラクションのパターンについては、以下の「API リファレンス(インライン)」セクションを参照してください
- URL は有効な HTTP(S) URL である必要があります
- 何らかの操作を行う前に、必ず
shared/config-pattern.mdに従って設定を読み込んでください ~/Downloads/または.listenhub/にはファイルを保存しないでください。現在の作業ディレクトリに保存してください
ステップ -1:API キーの確認
shared/config-pattern.md の「API キーの確認」に従ってください。キーがない場合は、ただちに停止してください。
ステップ 0:設定
shared/config-pattern.md のステップ 0(質問なしで開始)に従ってください。
ファイルが存在しない場合 — デフォルト設定で通知せずに作成し、続行してください:
mkdir -p ".listenhub/content-parser"
echo '{"autoDownload":true}' > ".listenhub/content-parser/config.json"
CONFIG_PATH=".listenhub/content-parser/config.json"
CONFIG=$(cat "$CONFIG_PATH")
設定に関する質問はしないでください。 そのままインタラクションフローに進んでください。
ファイルが存在する場合 — 設定を通知せずに読み込み、続行してください:
CONFIG_PATH=".listenhub/content-parser/config.json"
[ ! -f "$CONFIG_PATH" ] && CONFIG_PATH="$HOME/.listenhub/content-parser/config.json"
CONFIG=$(cat "$CONFIG_PATH")
設定フロー(ユーザーが再設定を開始した場合のみ)
ユーザーが明示的に再設定を依頼した場合にのみ実行してください。現在の設定を表示します:
当前配置 (content-parser):
自动下载:{是 / 否}
次に質問してください:
- autoDownload:「抽出したコンテンツを現在のディレクトリに自動保存しますか?」
- 「はい(推奨)」→
autoDownload: true - 「いいえ」→
autoDownload: false
- 「はい(推奨)」→
すぐに保存してください:
NEW_CONFIG=$(echo "$CONFIG" | jq --argjson dl {true/false} '. + {"autoDownload": $dl}')
echo "$NEW_CONFIG" > "$CONFIG_PATH"
CONFIG=$(cat "$CONFIG_PATH")
インタラクションフロー
ステップ 1:URL の入力
自由入力です。ユーザーに質問してください:
コンテンツを抽出する URL を入力してください。
ステップ 2:オプション(任意)
抽出オプションを設定するかどうか、ユーザーに尋ねてください:
Question: "Do you want to configure extraction options?"
Options:
- "No, use defaults" — Extract with default settings
- "Yes, configure options" — Set summarize, maxLength, or Twitter tweet count
「はい」の場合は、追加の質問をしてください:
- 要約:コンテンツの要約を生成しますか?(はい/いいえ)
- 最大長:コンテンツの最大長を設定しますか?(自由入力。例:「5000」)
- Twitter 件数(URL が Twitter/X のプロフィールの場合のみ):取得するツイート数はいくつですか?(1~100、デフォルトは20)
ステップ 3:確認と抽出
内容を要約します:
Ready to extract content:
URL: {url}
Options: {summarize: true, maxLength: 5000, twitter.count: 50} / default
Proceed?
API を呼び出す前に、明示的な確認を待ってください。
ワークフロー
-
URL を検証:HTTP(S) である必要があります。必要に応じて正規化します(
references/supported-platforms.mdを参照)。 -
リクエストボディを作成:
{ "source": { "type": "url", "uri": "{url}" }, "options": { "summarize": true/false, "maxLength": 5000, "twitter": { "count": 50 } } }ユーザーがデフォルトを選択した場合は、
optionsを省略します。 -
送信(フォアグラウンド):
POST /v1/content/extract→taskIdを取得します。 -
抽出処理中であることをユーザーに伝えます。
-
ポーリング(バックグラウンド):次の 正確な bash コマンドを、
run_in_background: trueおよびtimeout: 300000で実行します。注:ステータスフィールドは.data.status(processStatusではありません)、間隔は 5 秒、値はprocessing/completed/failedです。TASK_ID="<id-from-step-3>" for i in $(seq 1 60); do RESULT=$(curl -sS "https://api.marswave.ai/openapi/v1/content/extract/$TASK_ID" \ -H "Authorization: Bearer $LISTENHUB_API_KEY" \ -H "X-Source: skills" 2>/dev/null) STATUS=$(echo "$RESULT" | tr -d '\000-\037\177' | jq -r '.data.status // "processing"') case "$STATUS" in completed) echo "$RESULT"; exit 0 ;; failed) echo "FAILED: $RESULT" >&2; exit 1 ;; *) sleep 5 ;; esac done echo "TIMEOUT" >&2; exit 2 -
通知を受け取ったら、結果をダウンロードして提示します。
autoDownloadがtrueの場合、抽出したタイトルからスラッグを生成します。タイトルがない場合は、ドメイン名を使います。スラッグの生成と重複排除については、shared/config-pattern.md§ Artifact Naming に従います。{slug}.mdを現在のディレクトリに書き込みます — 抽出したコンテンツ全体を Markdown 形式で保存します。{slug}.jsonを現在のディレクトリに書き込みます — API レスポンスデータ全体をそのまま保存します。
SLUG="{title-slug}" # e.g. "topology-wikipedia" # Dedup: check if files exist BASE="$SLUG"; i=2 while [ -e "${SLUG}.md" ] || [ -e "${SLUG}.json" ]; do SLUG="${BASE}-${i}"; i=$((i+1)); done echo "$CONTENT_MD" > "${SLUG}.md" echo "$RESULT" > "${SLUG}.json"次の内容を提示します。
内容提取完成! 来源:{url} 标题:{metadata.title} 长度:~{character count} 字符 消耗积分:{credits} 已保存到当前目录: {slug}.md {slug}.json -
抽出したコンテンツのプレビュー(先頭約 500 文字)を表示します。
-
コンテンツを別のスキル(例:
/podcast、/tts)で使用することを提案します。
所要時間の目安:コンテンツのサイズとプラットフォームによって 10~30 秒です。
API リファレンス(インライン)
認証
環境変数:LISTENHUB_API_KEY(形式:lh_sk_...)
~/.zshrc(macOS)または ~/.bashrc(Linux)に保存します。
export LISTENHUB_API_KEY="lh_sk_..."
取得方法:https://listenhub.ai/settings/api-keys にアクセスします(Pro プランが必要です)。
ベース URL:https://api.marswave.ai/openapi/v1
必須ヘッダー(すべてのリクエスト):
Authorization: Bearer $LISTENHUB_API_KEY
Content-Type: application/json
X-Source: skills
X-Source: skills ヘッダーは、リクエストが Claude Code のスキル(CLI ツール)から送信されたことを示します。
curl テンプレート:
curl -sS -X POST "https://api.marswave.ai/openapi/v1/{endpoint}" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Source: skills" \
-d '{ ... }'
GET リクエストでは -d を省略し、-X POST を -X GET に変更します。
セキュリティに関する注意事項:
- 出力に API キー全体を記録または表示しないでください。
- API キーは HTTPS 経由でのみ送信されます。
- 機密情報や秘密情報をコンテンツ入力として渡さないでください。処理のために外部 API に送信されます。
POST /v1/content/extract
URL のコンテンツ抽出タスクを作成します。ポーリング用の taskId が返されます。
リクエストボディ:
| フィールド | 必須 | 型 | 説明 |
|---|---|---|---|
| source | はい | object | 抽出元 |
| source.type | はい | string | "url" である必要があります |
| source.uri | はい | string | コンテンツ抽出元となる有効な HTTP(S) URL |
| options | いいえ | object | 抽出オプション |
| options.summarize | いいえ | boolean | 要約を生成するかどうか |
| options.maxLength | いいえ | integer | コンテンツの最大長 |
| options.twitter | いいえ | object | Twitter/X 固有のオプション |
| options.twitter.count | いいえ | integer | 取得するツイート数(1~100、デフォルトは 20) |
レスポンス:
{
"code": 0,
"message": "success",
"data": {
"taskId": "69a7dac700cf95938f86d9bb"
}
}
エラーコード:
| コード | 意味 |
|---|---|
| 29003 | 検証エラー("source.uri" is required、"source.uri" must be a valid uri) |
| 21007 | API キーが無効です |
GET /v1/content/extract/{taskId}
抽出タスクのステータスと結果を取得します。
パスパラメーター:
| パラメーター | 型 | 説明 |
|---|---|---|
| taskId | string | 24 文字の 16 進数のタスク ID |
レスポンスの状態:
- processing — タスクはまだ実行中です
- completed — 抽出が完了し、データを利用できます
- failed — 抽出に失敗しました。
failCodeとmessageを確認してください
レスポンス(processing):
{
"code": 0,
"message": "success",
"data": {
"taskId": "69a7dac700cf95938f86d9bb",
"status": "processing",
"createdAt": "2025-04-09T12:00:00Z",
"data": null,
"credits": 0,
"failCode": null,
"message": null
}
}
レスポンス(completed):
{
"code": 0,
"message": "success",
"data": {
"taskId": "69a7dac700cf95938f86d9bb",
"status": "completed",
"createdAt": "2025-04-09T12:00:00Z",
"data": {
"content": "Extracted text content...",
"metadata": {
"title": "Article Title",
"author": "Author Name",
"publishedAt": "2025-04-01T08:00:00Z"
},
"references": [
"https://example.com/related-article"
]
},
"credits": 5,
"failCode": null,
"message": null
}
}
レスポンス(failed):
{
"code": 0,
"message": "success",
"data": {
"taskId": "69a7dac700cf95938f86d9bb",
"status": "failed",
"createdAt": "2025-04-09T12:00:00Z",
"data": null,
"credits": 0,
"failCode": "EXTRACT_FAILED",
"message": "Unable to extract content from the provided URL"
}
}
主なフィールド:
| フィールド | 型 | 説明 |
|---|---|---|
| status | string | processing、completed、または failed |
| data.data.content | string | 抽出されたテキストコンテンツ |
| data.data.metadata | object | ページのメタデータ(title、author、publishedAt) |
| data.data.references | array | 参照された URL(文字列の配列) |
| credits | integer | 消費されたクレジット数 |
| failCode | string | エラーコード(成功時は null) |
| message | string | エラーメッセージ(成功時は null) |
エラーコード:
| コード | 意味 |
|---|---|
| 29003 | taskId の形式が無効です |
| 25002 | タスクが見つかりません |
ポーリングのパターン
5 秒間隔で最大 60 回ポーリングします。run_in_background: true と timeout: 300000 を指定して実行してください。
2 段階のパターン:
- 送信(フォアグラウンド):作成リクエストを POST し、レスポンスから
taskIdを抽出します。 - ポーリング(バックグラウンド):
run_in_background: trueを指定してポーリングループを実行します。完了すると自動的に通知されます。
正確なポーリング用 bash コマンドは、Workflow セクション(ステップ 5)に記載されています。
エラー処理
HTTP ステータスコード:
| コード | 意味 | 対応 |
|---|---|---|
| 200 | 成功 | レスポンス本文を解析します |
| 400 | 不正なリクエスト | パラメーターを確認します |
| 401 | API キーが無効です | LISTENHUB_API_KEY を再確認します |
| 402 | クレジットが不足しています | ユーザーにチャージを案内します |
| 403 | アクセス禁止 | このリソースへの権限がありません |
| 429 | レート制限 | 指数バックオフを行い、遅延後に再試行します |
| 500/502/503/504 | サーバーエラー | 最大 3 回再試行します |
再試行の戦略:
- 429 レート制限:15 秒待ってから再試行します(指数バックオフ)
- 5xx サーバーエラー:5 秒間隔で最大 3 回再試行します
- ネットワークエラー:最大 3 回再試行します
アプリケーションのエラーコード:
| コード | 意味 |
|---|---|
| 21007 | ユーザーの API キーが無効です |
| 25429 | レート制限(アプリケーションレベル) |
例
ユーザー:「この記事を解析してください:https://en.wikipedia.org/wiki/Topology」
エージェントのワークフロー:
- URL:
https://en.wikipedia.org/wiki/Topology - オプション:デフォルト(オプションを省略)
- 抽出を送信します
curl -sS -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Source: skills" \
-d '{
"source": {
"type": "url",
"uri": "https://en.wikipedia.org/wiki/Topology"
}
}'
- 完了するまでポーリングします:
curl -sS "https://api.marswave.ai/openapi/v1/content/extract/69a7dac700cf95938f86d9bb" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "X-Source: skills"
- 抽出されたコンテンツのプレビューを提示し、次のアクションを提案します。
ユーザー:「@elonmusk の最近のツイートを抽出してください。50 件取得してください」
エージェントのワークフロー:
- URL:
https://x.com/elonmusk - オプション:
{"twitter": {"count": 50}} - 抽出を送信します
curl -sS -X POST "https://api.marswave.ai/openapi/v1/content/extract" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Source: skills" \
-d '{
"source": {
"type": "url",
"uri": "https://x.com/elonmusk"
},
"options": {
"twitter": {
"count": 50
}
}
}'
- 完了するまでポーリングし、結果を提示します。