firecrawl-research-patterns について
Firecrawl Research Patternsは、Firecrawlの公開APIを使う調査ワークフロー集です。ウェブ検索やページ取得、論文の取得を行う研究者やエージェント向けで、再帰的な調査と生データの保存にも対応します。
主な機能
- 01APIによる検索とページ取得
- 02ソースに応じた論文取得方法の選択
- 03再帰的な検索と統合
- 04出典情報付きの生データ保存
- 05調査コーパスの再分析
- 06図を含む論文の処理
活用シーン
- 01テーマ検索とページ資料の保存
- 02論文取得と知見の要約
- 03追加質問による調査範囲の拡張
- 04既存コーパスを使った再分析
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ terrylica/ cc-skills --skill firecrawl-research-patternsインストール後、Claude Code で/firecrawl-research-patternsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/academic-paper-routing.mdapi-endpoint-reference.mdcorpus-persistence-format.mdevolution-log.mdrecursive-research-protocol.md詳細
Firecrawl を使ったリサーチパターン
リサーチワークフローで Firecrawl をプログラムから使用するためのパターンです。検索、スクレイプ、学術論文への振り分け、再帰的なディープリサーチの実行、将来の再分析に備えた生データの保存を扱います。
公開 Firecrawl API を使用してください。セルフホスト版はありません。 POST https://api.firecrawl.dev/v2/scrape は API キーなしで応答します。このリポジトリで実際に行う、低頻度かつ単発の変換にはこれで十分です。レート制限やキュー待ちは許容できるため、回避するためにプライベートなデプロイ環境を立ち上げないでください。
AI チャットの会話(ChatGPT/Gemini の共有リンク)をアーカイブする場合は、Skill(gh-tools:research-archival) を参照してください。
自己進化型スキル:このスキルは使用を通じて改善されます。手順に誤りがある、パラメーターが変更された、または回避策が必要だった場合は、先送りせず、すぐにこのファイルを修正してください。実際に再現できる問題がある場合にのみ更新してください。
最初に — TodoWrite タスクテンプレート
必須:リサーチ作業を始める前に、適切なテンプレートを選択して読み込んでください。
意図に基づく振り分け — AI チャットの共有 URL(chatgpt / gemini / claude)
AI チャットの共有 URL(chatgpt.com/share/*、chat.openai.com/share/*、gemini.google.com/share/*、g.co/gemini/share/*、claude.ai/share/*、claude.ai/chat/*)は、このスキルと Skill(gh-tools:research-archival) のどちらでも処理できます。URL パターンではなく、意図に基づいて選んでください。
| 意図 | スキル | 出力 |
|---|---|---|
| 分析用に、会話を一度だけ読み取る/テキストを抽出する | このスキル — パブリック API(Sec. 1) | data.markdown に返される Markdown。自分で保存してください。フロントマター、Issue、出典情報はありません。 |
| 本人確認、フロントマター、GitHub Issue との相互リンクを含む長期アーカイブ | Skill(gh-tools:research-archival) | docs/research/YYYY-MM-DD-{slug}-{type}.md + Discovery Provenance を含む Issue。 |
| ファイルをすでに持っていて、同じコーパスファイルに追加コンテンツをスクレイピングするだけ | このスキル | 自分で制御する追記モードのワークフロー。 |
どちらの方法も同じ Firecrawl バックエンドを使用します。
research-archivalも Firecrawl を呼び出します。こちらはその上にアーカイブ層を追加します。スクレイピング機能に差はありません。違いは、取得したデータをその後どう扱うかです。
意図にかかわらず、WebFetch には制限があります:Claude Code は chatgpt.com への WebFetch をハードブロックします。Firecrawl を使用してください。
チャットの共有 URL には Jina Reader より Firecrawl を優先してください。Jina は気づかれないまま切り詰めます。 2026-08-13 に、2 つの chatgpt.com/share/* URL を同じタイミングで測定しました。どちらも HTTP 200 を返し、エラーはありませんでした。
| リンク | Firecrawl v2/scrape | Jina r.jina.ai | Jina のカバー率 |
|---|---|---|---|
| 1 | 57,616 文字・76 個の見出し・128 行のテーブル | 9,397 文字・12 個の見出し・22 行のテーブル | 17% |
| 2 | 136,590 文字・85 個の見出し・69 行のテーブル | 15,960 文字・13 個の見出し・9 行のテーブル | 12% |
Firecrawl は、両方のページの本当の末尾(Sources/ChatGPT is AI and can make mistakes. のフッター)まで取得しました。Jina は文の途中で止まり、リンク 1 は "I would spend money on **Synol" で終わっていました。どちらもログイン画面には到達しておらず、Firecrawl の追加分もナビゲーション用の定型文ではありませんでした(最も繰り返されていた行は空白でした)。Jina の切り詰められた結果は、短いページを正常に取得したように見えるため、これが危険な失敗です。検出できるエラーがありません。
Jina を使う場合は -H "x-timeout: 30" も必要です。デフォルトでは、警告の Warning: 行だけを添えて、ログイン画面の内容("Log in to get answers")を約 321 バイト返します。Jina は単純な静的ページのフォールバックとして使用し、チャットの共有 URL や JavaScript でレンダリングされるページには使用しないでください。
テンプレート A — Firecrawl 検索と保存(単一)
1. No health check needed — the public API has no self-hosted liveness concern. Handle per-request failures instead (Section 1).
2. Execute search — POST /v2/search with query, limit, scrapeOptions
3. Persist raw results — save each result page to docs/research/corpus/ with frontmatter
4. Update corpus index — append entries to docs/research/corpus-index.jsonl
5. Extract findings — summarize key learnings from raw corpus files
テンプレート B — 学術論文の取得と保存
1. Identify source — classify URL/DOI per academic-paper-routing.md decision tree
2. Route to scraper — arxiv direct HTML, Semantic Scholar API, Firecrawl, or Jina Reader
3. Scrape content — execute fetch with appropriate method and timeout
4. Persist raw result — save to docs/research/corpus/ with academic-specific frontmatter
5. Update corpus index — append entry to corpus-index.jsonl
6. Summarize paper — extract key claims, methods, results from raw corpus file
テンプレート C — コーパスを使用した再帰的な詳細調査
1. No health check needed — the public API has no self-hosted liveness concern. Handle per-request failures instead (Section 1).
2. Initialize parameters — set breadth (default 4), depth (default 2), concurrency (default 2)
3. Generate search queries — LLM generates N queries from topic + prior learnings
4. Execute searches — Firecrawl /v2/search for each query via p-limit(concurrency)
5. Persist raw results — save ALL scraped pages to docs/research/corpus/ with provenance
6. Extract learnings — LLM extracts key findings + follow-up questions per result set
7. Recurse — for each follow-up, recurse with breadth=ceil(breadth/2), depth=depth-1
8. Base case — depth=0, return accumulated learnings
9. Synthesize report — LLM generates final markdown from all learnings
10. Write session report — save to docs/research/sessions/ with corpus file references
11. Update corpus index — append all new entries to corpus-index.jsonl
テンプレート D — コーパスのレビュー/再分析
1. Inventory corpus — read docs/research/corpus-index.jsonl, filter by session/topic/date
2. Read raw files — load matching corpus files from docs/research/corpus/
3. Re-analyze — extract new insights with current context/questions
4. Update session report — amend or create new session report in docs/research/sessions/
テンプレート E — 図をインラインで含む画像豊富な論文
論文にアーキテクチャ図、結果のプロット、アテンションマップなど、重要な視覚コンテンツが含まれる場合に使用してください。
1. Scrape text — use the public API (`/v2/scrape`, preserves absolute image URLs) or Jina fallback
2. Detect figures — scan scraped markdown for  patterns with .png/.jpg/.svg
3. Extract figure URLs — for arXiv: probe https://arxiv.org/html/{id}v{n}/x{N}.png until 404
4. Keep URLs inline — DO NOT rewrite to local relative paths (breaks GitHub rendering)
5. Ensure inline embedding — markdown body must have  for each figure
6. Catalog in frontmatter — add figure_count and figure_urls list (all absolute URLs)
7. Save corpus file — GFM markdown with inline absolute URLs renders on GitHub without hosting
8. Update corpus-index.jsonl — include has_figures: true, figure_count, figure_urls
セクション 1 — Firecrawl のプログラムからの利用
エンドポイント:https://api.firecrawl.dev のパブリック API です。API キーもホストもトンネルも不要で、認証なしで応答します。
curl -sS -X POST https://api.firecrawl.dev/v2/scrape \
-H 'Content-Type: application/json' \
-d '{"url":"<URL>","formats":["markdown"],"waitFor":8000,"timeout":60000}'
# -> {"success":true,"data":{"markdown":"..."}}
JavaScript でレンダリングされるページ(SPA、チャットの共有ページ、ダッシュボード)では、必ず waitFor を送信してください。指定しない場合、スクレイピングでハイドレーション前のシェルが返ることがあります。ログインが必要な SPA では、コンテンツではなくログイン画面が返されるうえ、その場合も HTTP 200 が返されます。200 は抽出に成功した証拠ではありません。期待するコンテンツが含まれているか確認してください。
セルフホストのデプロイを再開しないでください。 以前は gpu-host-2:3002 で稼働していました(コンテナ 5 個:api、playwright-service、nuq-postgres、rabbitmq、redis)が、2026-08-13 に廃止され、約 18 GB の容量を回収しました。パブリック API でこのリポジトリの利用量をまかなえます。再稼働させると、誰も直面していなかったレート制限を回避するために、約 18 GB と 5 個の常時稼働コンテナを犠牲にすることになります。
@mendable/firecrawl-js SDK ではなく fetch() を使う理由
公式 SDK は動的インポートに jiti を使用しており、Bun のモジュール解決と互換性がありません。fetch() を直接呼び出すほうがシンプルで信頼性が高く、依存関係もありません。
2 つのエンドポイント
| エンドポイント | 用途 | 使用する場面 |
|---|---|---|
POST /v2/search | 検索とスクレイピングの組み合わせ | 調査クエリ — スクレイピング済みの複数ページを返します |
POST /v2/scrape | 単一 URL のスクレイピング | URL が既知の場合 — 1 ページから Markdown を抽出します |
リクエストとレスポンスの仕様全体については、api-endpoint-reference.md を参照してください。
簡単な例
パブリック API のベース URL を使用します。プロジェクトで $FIRECRAWL_BASE 環境変数が設定されている場合はそこから取得し、設定されていない場合は FQDN を直接記述してください。
const FIRECRAWL_BASE =
process.env.FIRECRAWL_BASE ?? "https://api.firecrawl.dev";
検索(Markdown 付きの複数の結果を返します):
const res = await fetch(`${FIRECRAWL_BASE}/v2/search`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: "mixture of experts scaling laws",
limit: 5,
scrapeOptions: { formats: ["markdown"] },
}),
});
const { data } = await res.json(); // data: [{ url, markdown, metadata }]
スクレイピング(単一 URL):
const res = await fetch(`${FIRECRAWL_BASE}/v2/scrape`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
url: "https://arxiv.org/abs/2401.12345",
formats: ["markdown"],
waitFor: 3000, // ms — for JS-heavy pages
}),
});
const { data } = await res.json(); // data: { markdown, metadata }
エラー処理
// Always set a timeout
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 15_000);
try {
const res = await fetch(url, { ...opts, signal: controller.signal });
if (!res.ok) throw new Error(`Firecrawl: ${res.status} ${res.statusText}`);
const json = await res.json();
if (!json.data || (Array.isArray(json.data) && json.data.length === 0)) {
// Empty results — not an error, but no content to process
}
} finally {
clearTimeout(timeoutId);
}
セクション 2 — 学術論文の取得先の振り分け
ソースに基づいて、論文の取得に最も効果的な方法を選びます。完全な判断フローについては、academic-paper-routing.md を参照してください。
クイックリファレンス
| ソース | 最適な方法 | フォールバック |
|---|---|---|
| arxiv.org | 直接 HTML(/html/ID) | Firecrawl /v2/scrape |
| Semantic Scholar | API(api.semanticscholar.org) | タイトルで Firecrawl 検索 |
| ACL Anthology | Firecrawl /v2/scrape | PDF を直接ダウンロード |
| NeurIPS/ICML/ICLR | waitFor を指定した Firecrawl /v2/scrape | タイトルで検索 |
| IEEE Xplore | waitFor: 3000 を指定した Firecrawl | 著者のウェブサイト |
| ACM DL | waitFor: 3000 を指定した Firecrawl | 著者のウェブサイト |
| 著者のブログ | Jina Reader(r.jina.ai) | Firecrawl /v2/scrape |
| Google Scholar | Firecrawl /v2/search | 検索クエリを直接実行 |
DOI の解決
// DOI → publisher URL → route to appropriate scraper
const res = await fetch(`https://doi.org/${doi}`, { redirect: "follow" });
const publisherUrl = res.url; // e.g., https://dl.acm.org/doi/10.1145/...
// Then route publisherUrl through the decision tree above
セクション 3 — 再帰的な調査プロトコル
検索 → 抽出 → 再帰 → 統合を繰り返すパターンです。手順の全容については、recursive-research-protocol.md を参照してください。
アルゴリズムの概要
deepResearch(topic, breadth=4, depth=2, concurrency=2):
1. Generate N search queries (N = breadth) from topic + prior learnings
2. For each query (via p-limit concurrency):
a. Firecrawl /v2/search → get results
b. PERSIST each raw result to docs/research/corpus/
c. Extract learnings + follow-up questions
3. For each follow-up question:
→ Recurse with breadth=ceil(breadth/2), depth=depth-1
4. Base case: depth=0 → return accumulated learnings
5. Synthesize final report from all learnings
6. Write session report to docs/research/sessions/
デフォルトパラメーター(動作する実装に基づく)
| パラメーター | デフォルト | 最大 | 理由 |
|---|---|---|---|
breadth | 4 | — | 各レベルで並行して実行する検索クエリの数 |
depth | 2 | 5 | 再帰のレベル数(depth > 5 では収穫逓減となります) |
concurrency | 2 | — | 並行する Firecrawl リクエスト数(パブリック API のため控えめに) |
limit | 5 | — | 検索クエリごとの結果数 |
timeout | 15000ms | — | 検索ごとのタイムアウト |
トークン予算
検索ごとに最大5ページが返されます。LLM で処理する前に、各ページを約25,000トークンにトリミングします。
function trimToTokenLimit(text: string, maxTokens: number): string {
if (!text) return "";
const estimatedTokens = Math.ceil(text.length / 3.5);
if (estimatedTokens <= maxTokens) return text;
const maxChars = Math.floor(maxTokens * 3.5 * 0.8);
return text.slice(0, maxChars);
}
部分的な失敗を許容する原則
すべて失敗するより、部分的な結果が得られるほうが望ましいです。 クエリが失敗した場合は、ログを記録して残りのクエリを続行します。1つのクエリがタイムアウトしたからといって、調査セッション全体を中止してはいけません。
セクション4 — 生コーパスの永続化
重要な原則:Firecrawl でスクレイピングしたページはすべて、出所情報のメタデータとともに元の生の Markdownで永続化する必要があります。統合レポートではこれらの原本を参照しますが、置き換えることはありません。
フォーマットの完全な仕様はcorpus-persistence-format.mdを参照してください。
ディレクトリ構成
{project-root}/
├── docs/research/
│ ├── corpus/ # Raw scraped pages (committed)
│ │ └── YYYY-MM-DD-{slug}.md # One file per scraped URL
│ ├── sessions/ # Research session reports (committed)
│ │ └── YYYY-MM-DD-{topic-slug}.md # Synthesized report with corpus refs
│ └── corpus-index.jsonl # Append-only registry (committed)
コーパスファイルのフロントマター
---
source_url: https://arxiv.org/html/2401.12345
scraped_at: "2026-02-25T14:30:00Z"
scraper: firecrawl
firecrawl_endpoint: /v2/search
search_query: "mixture of experts scaling"
result_index: 2
research_session: "2026-02-25-moe-scaling"
depth_level: 1
claude_code_uuid: SESSION_UUID
content_tokens_approx: 4200
---
[RAW MARKDOWN FROM FIRECRAWL — NEVER MODIFIED]
主なルール
---より下の内容は、Firecrawl が返したそのままの Markdownです。要約、トリミング、再フォーマットは行いません- スクレイピングごとにURLあたり1ファイルとします。同じURLを複数のセッションでスクレイピングした場合、それぞれにタイムスタンプ付きのファイルを作成します
- ファイル名は
YYYY-MM-DD-{slug}.mdとします。slug はページタイトルまたはURLパスから作成したケバブケースで、最大60文字です - セッションレポートは
docs/research/sessions/に保存し、相対パスでコーパスファイルを参照します
コーパスインデックス(JSONL)
{
"url": "https://arxiv.org/html/2401.12345",
"file": "corpus/2026-02-25-moe-scaling-arxiv-2401-12345.md",
"scraped_at": "2026-02-25T14:30:00Z",
"session": "2026-02-25-moe-scaling",
"tokens": 4200,
"scraper": "firecrawl"
}
これが重要な理由
- LLM による再分析:将来のセッションで生のコーパスファイルを再読み込みし、より適切なプロンプトや新しいモデルを使って異なる知見を抽出できます
- 情報損失がない:統合時には詳細が失われますが、生ファイルには Firecrawl が取得したすべての情報が保持されます
- 重複排除への対応:JSONL インデックスを使うと、エージェントはコーパス内にすでに存在するURLをスキップできます
- Git との親和性:Markdown ファイルは差分を確認しやすく、JSONL は追記専用です
セクション5 — 廃止:セルフホスト運用
セルフホスト型デプロイ(gpu-host-2:3002、および Caddy の背後にあるポート 3003/3004)は、2026-08-13 に廃止されました。コンテナ、イメージ、ビルドキャッシュは削除され、約18 GBの容量が回収されました。セクション1の公開APIを使用してください。このリポジトリの利用規模を理由に、プライベートデプロイを再導入してはいけません。
セクション6 — 画像と図の取得
テキストのみを扱うスクレイパー(Jina、直接 Firecrawl)は文章を取得しますが、アーキテクチャ図、結果プロット、アテンションマップは失われます。画像を多く含む論文では、必ず図を取得してください。
画像を取得するタイミング
論文に次のいずれかが含まれる場合は、図を取得してください。
- アーキテクチャ図(モデル構造、アテンションパターン)
- ベンチマーク/結果の比較プロット
- 定性的な例(生成結果、可視化)
- アルゴリズムのフローチャートまたは疑似コードの図
arXiv HTML の図のURLの検出
arXiv HTML 論文では、図は連番の絶対URL(x1.png、x2.png、...)に保存されています。すべての図のURLを検出するためにプローブを実行してください。ローカルにはダウンロードしないでください。
ARXIV_ID="2312.00752"
ARXIV_VER="v2"
BASE_URL="https://arxiv.org/html/${ARXIV_ID}${ARXIV_VER}"
FIGURE_URLS=()
# Probe sequential URLs until 404 — collect absolute URLs only
for i in $(seq 1 50); do
url="${BASE_URL}/x${i}.png"
status=$(curl -s -o /dev/null -w "%{http_code}" "$url")
if [ "$status" != "200" ]; then
echo "Stopped at x${i}.png (${status}) — found ${#FIGURE_URLS[@]} figures"
break
fi
FIGURE_URLS+=("$url")
echo "Found: $url"
done
収集した絶対URLは Markdown の本文とフロントマターに直接記載します。ローカルコピーは不要です。
図をインラインで埋め込む(GFM)
GitHub で図がその場に表示されるよう、各図を絶対URLとしてコーパスの Markdown にインラインで記載する必要があります。
## Key Figures



./figures/x1.pngのような相対パスに書き換えてはいけません。画像が同じリポジトリにコミットされていない場合、相対パスは GitHub で機能しません。
スクレイピング済み Markdown から既存のインラインURLを抽出する
Firecrawl はスクレイピングした Markdown に絶対画像URLを埋め込みます。フロントマターの一覧を作成するため、これらを抽出してください。
CORPUS_FILE="docs/research/corpus/2026-03-13-mamba-ssm.md"
# Extract all absolute image URLs already in the markdown
grep -oE 'https://[^)]+\.(png|jpg|svg|gif|webp)' "$CORPUS_FILE" | sort -u
これらのURLはすでにインラインで記載されているため、フロントマターの figure_urls リストにコピーするだけです。
画像を多く含む論文のフロントマター
YAML フロントマターには、出所情報としてすべての図のソースURLを記載します。Markdown の本文には図をインラインで埋め込みます。
---
source_url: https://arxiv.org/html/2312.00752v2
scraped_at: "2026-03-13T00:00:00Z"
scraper: firecrawl
tags: [ssm, state-space-model, mamba, sequence-modeling]
content_tokens_approx: 4200
has_figures: true
figure_count: 12
figure_urls:
- https://arxiv.org/html/2312.00752v2/x1.png
- https://arxiv.org/html/2312.00752v2/x2.png
- https://arxiv.org/html/2312.00752v2/x3.png
- https://arxiv.org/html/2312.00752v2/x4.png
- https://arxiv.org/html/2312.00752v2/x5.png
---
図を含むコーパスインデックスのエントリ
{
"url": "https://arxiv.org/html/2312.00752v2",
"file": "corpus/2026-03-13-mamba-ssm.md",
"scraped_at": "2026-03-13T00:00:00Z",
"session": "2026-03-13-mamba-ssm",
"scraper": "firecrawl",
"has_figures": true,
"figure_count": 12,
"figure_urls": [
"https://arxiv.org/html/2312.00752v2/x1.png",
"https://arxiv.org/html/2312.00752v2/x2.png"
]
}
Firecrawl と Jina Reader の比較:実証的な比較(arXiv)
arXiv:2312.00752v2(Mamba 論文)で検証済み — 両方のスクレイパーを実行し、同じ URL を使用:
| スクレイパー | バイト数 | 行数 | 単語数 | 図(絶対 URL のインライン形式) | GitHub での数式 |
|---|---|---|---|---|---|
Firecrawl /v2/scrape | 99,104 | 1,267 | 13,182 | 13 ✅ | ❌ Unicode と LaTeX が二重に出力され、$...$ なし |
| Jina Reader | 84,832 | 596 | 10,761 | 12 ✅ | ❌ Unicode と LaTeX が二重に出力され、$...$ なし |
| LaTeX ソースからの Pandoc | — | — | — | \includegraphics 経由 | ✅ $inline$ + ```math ``` ブロック |
結論:この論文では、Firecrawl は Jina よりも バイト数が 17%、行数が 2.1 倍、単語数が 22%多く、図が 1 つ多く取得されます。これは、チャットの共有データで測定された大きな差と一貫しています。どちらも図の URL を絶対 URL のインライン形式で出力するため、どちらのスクレイパーでも URL を再構築する必要はありません。
推奨する arXiv ワークフロー:
- Firecrawl
POST /v2/scrape(推奨)— より完全なコンテンツを取得し、図をインラインで出力します - Jina Reader(フォールバック、静的ページのみ)— コンテンツは 17%少なくなりますが、図の絶対 URL は取得できます
- スクレイパーの種類にかかわらず、プローブループを使用して
figure_urlsのフロントマターカタログを構築します - GitHub で人間が読みやすい数式を表示するには、arXiv の LaTeX ソースから Pandoc を使用します(以下を参照)
数式のレンダリング:実証済みのアプローチ
2026 年 3 月、arXiv:2312.00752v2(Mamba 論文)で検証済みです。
Firecrawl/Jina の数式出力:GitHub では読みづらい
Firecrawl と Jina Reader はどちらも、数式の内容を二重に出力して抽出します。各数式は、Unicode 形式のレンダリング結果の直後に生の LaTeX ソースが続く形で現れ、\displaystyle 接頭辞と \\bm{} エスケープを伴う Markdown の表セルに詰め込まれます。実証テストからの例:
| | h′(t)\\displaystyle h^{\\prime}(t) | \=𝑨h(t)+𝑩x(t)\\displaystyle=\\bm{A}h(t)+\\bm{B}x(t) | | (1a) |
$...$ の区切り記号がないため、GitHub ではこれを数式としてレンダリングできません。生の LaTeX 部分は LLM で解析可能(数式自体は含まれています)ですが、GitHub 上では人間にとって完全に読みづらい出力になります。
LLM での利用:Firecrawl の二重出力されたコンテンツで十分です。LaTeX ソースが埋め込まれているため、LLM で抽出できます。
GitHub で人間が読みやすい形式で表示する場合:arXiv の LaTeX ソースの tarball から Pandoc を使用します(以下を参照)。
arXiv の LaTeX ソースからの Pandoc(人間が読みやすい数式)
GitHub の MathJax/KaTeX がネイティブにレンダリングできる、適切な $inline$ と ```math ``` の表示ブロックを生成します:
ARXIV_ID="2312.00752"
# Download arXiv LaTeX source tarball
curl -L "https://arxiv.org/src/${ARXIV_ID}" -o "${ARXIV_ID}-src.tar.gz"
mkdir -p "${ARXIV_ID}-src"
tar xzf "${ARXIV_ID}-src.tar.gz" -C "${ARXIV_ID}-src/"
# Find main .tex entry point and section files
ls "${ARXIV_ID}-src/"*.tex
ls "${ARXIV_ID}-src/src/"*.tex 2>/dev/null # some papers put sections in src/
# Option A: Convert individual section files (safer — avoids macro parse errors)
pandoc "${ARXIV_ID}-src/src/background.tex" \
--to gfm+tex_math_dollars \
--wrap=none \
-o "${ARXIV_ID}-background.md"
# Option B: Convert full main.tex (may fail on custom macros like \iftoggle)
pandoc "${ARXIV_ID}-src/main.tex" \
--to gfm+tex_math_dollars \
--wrap=none \
-o "${ARXIV_ID}-pandoc.md"
インストール方法:brew install pandoc。LaTeX ソースを公開している arXiv 論文(大半が公開しています)で利用できます。
Pandoc の出力品質(実証済み):
- インライン数式:
$x(t) \in \R \mapsto y(t) \in \R$✅ GitHub でレンダリングされます - 表示数式:
```math\n\begin{align}\nh'(t) &= \A h(t) + \B x(t)\n\end{align}\n```✅ GitHub でレンダリングされます - カスタムマクロ(
\A、\B、\R、\dt、\dA、\dB):⚠️ KaTeX では未定義です — マクロはそのまま出力され、プリアンブルの\newcommand定義がないと GitHub で部分的に表示に失敗する場合があります
カスタムマクロへの対処:main.tex のプリアンブルにある \newcommand ブロックを出力に先頭追加します:
# Extract custom macro definitions from preamble
grep '\\newcommand\|\\renewcommand\|\\def ' "${ARXIV_ID}-src/main.tex" > macros.tex
# Pandoc does not read preamble macros — include them explicitly in a math block at the top:
echo '```math' > preamble-block.md
cat macros.tex >> preamble-block.md
echo '```' >> preamble-block.md
cat preamble-block.md "${ARXIV_ID}-pandoc.md" > "${ARXIV_ID}-with-macros.md"
arXiv の LaTeX で確認されている Pandoc の解析エラー:
| エラーの原因 | 原因 | 回避策 |
|---|---|---|
\iftoggle{arxiv} | 未定義のトグルマクロ(etoolbox パッケージ) | main.tex ではなくセクションファイルを変換します |
\begin{figure*} | 2 段組みの図環境によって構造が崩れます | head -N を使用して、壊れた \end タグを避けます |
\bm{}、\mathbf{} | そのまま出力され、KaTeX でレンダリングされない場合があります | 論文のマクロファイルで対応する定義を確認します |
アンチパターン
| # | アンチパターン | 失敗する理由 | 正しい方法 |
|---|---|---|---|
| 1 | @mendable/firecrawl-js SDK の使用 | jiti の動的インポートは Bun で動作しません | fetch() を直接呼び出します |
| 2 | waitFor を使わずに有料サイトを検索する | JS SPA は空のシェルを返します | IEEE、ACM DL には waitFor: 3000 を使用します |
| 3 | depth を 5 より大きく設定する | クエリが指数関数的に増加し、収穫逓減になります | depth を 5 に制限します(clampDepth()) |
| 4 | fetch() にタイムアウトを設定しない | 到達できないページで無期限に停止します | 常に AbortController と 15 秒のタイムアウトを使用します |
| 5 | 長いページコンテンツをトリミングしない | LLM のコンテキストウィンドウを超過します | ページごとに trimToTokenLimit(text, 25_000) を使用します |
| 6 | 部分的な失敗で処理を中断する | 完了済みの作業がすべて失われます | 失敗を記録し、残りのクエリを続行します |
| 7 | 稼働確認で実行を制御する | パブリック API にはヘルスエンドポイントがなく、停止するホストもありません | リクエストごとの失敗に対処します。1 回再試行し、その後フォールバックします。セクション 1 を参照してください。 |
| 8 | 元の生データを保存せず、統合結果だけを保存する | ソース資料が失われ、再分析できなくなります | Firecrawl の生の Markdown は常にコーパスに保存します |
| 9 | 図の URL をローカルの相対パスに書き換える | ./figures/x1.png のような相対パスは GitHub で機能せず、画像が表示されません | Markdown 本文内では絶対 URL をそのまま保持し()、フロントマターの figure_urls リストに一覧を記載します。セクション 6 を参照してください |
参考資料
- API エンドポイントリファレンス —
/v2/searchと/v2/scrapeの仕様 - 学術論文のルーティング — 論文ソースの判断ツリー
- 再帰的リサーチプロトコル — 再帰パターンのステップごとの手順
- コーパス永続化形式 — 生コンテンツのアーカイブ形式とディレクトリ構成
- 変更履歴 — このスキルの変更履歴(日時付き)
実行後の振り返り
このスキルの実行後、終了する前に次の点を確認してください。
- コマンドは成功しましたか? — 成功していない場合は、失敗の原因となった手順またはエラーテーブルを修正します。
- パラメーターや出力に変更はありましたか? — 基盤となるツールのインターフェースに変更があった場合は、使用例とパラメーターテーブルを更新して一致させます。
- 回避策が必要でしたか? — 別のフラグや追加手順など、その場で工夫する必要があった場合は、次回の実行で同じ回避策が不要になるよう、この SKILL.md を更新します。
問題が実際に発生し、再現可能な場合にのみ更新してください。推測で更新しないでください。