Crawl4AIとは、LLMへの入力に最適化された出力を返すPython製のオープンソースWebクローラーである。
requests と BeautifulSoup を組み合わせれば、簡単なWebスクレイピングは数行で書けます。けれど、現代のサイトは多くがReactやVueで構築され、JavaScriptが実行されるまで本文HTMLが空のままという作りに。古典的な手法では中身がほぼ取れない、という壁にぶつかった人は少なくないはず。
その壁を、Playwrightベースのブラウザ自動化と、LLMへの受け渡しを前提にした出力整形でまとめて越えにいくのが Crawl4AI です。GitHub上では unclecode/crawl4ai として公開され、星の数も急増中。本記事ではv0.8.x系を前提に、インストールから10種類の主要機能、運用上の注意点までを順に整理していきます。
・Crawl4AIはPlaywright+Chromiumを内蔵したPython製OSSクローラーで、JS必須サイトも標準で扱える
・HTML→Markdown変換、CSS構造化抽出、LLM抽出、深層クロールなど10前後の機能を1ライブラリで完結
・ローカルLLMや商用APIと組み合わせれば、スキーマが不安定なサイトからも構造化データを取り出せる
Crawl4AIの全体像
まず、Crawl4AI が何者で、どこに位置づけられるツールなのかを地図として描きます。単なるスクレイパーではなく、LLM活用を前提とした「収集→整形→構造化」のパイプラインを1つにまとめたフレームワーク、という見立てが分かりやすい。
Crawl4AIとは何か
Crawl4AI(クロールフォーエーアイ)は、LLM時代のWebデータ収集に向けて設計されたオープンソースのPythonライブラリです。GitHubの公式リポジトリ unclecode/crawl4ai で開発が進められており、ブラウザ自動化の Playwright と Chromium をバックエンドに据え、JavaScriptで描画されるサイトでも安定して中身を取得できる構造になっています。
特徴は3つ。まず、ページのHTMLをそのまま返すのではなく、LLMに食わせやすい Markdown 形式へ自動変換する点。次に、CSSセレクタによる構造化抽出と、LLMを使ったスキーマ自由形式の抽出の両方を、同じAPIで切り替えられる点。最後に、スクリーンショット・リンク解析・並列クロール・深層クロールなど、実運用で必要になる周辺機能を1つのライブラリにまとめてある点です。
「スクレイピングのライブラリ」と「ブラウザ自動化のラッパー」と「LLM入力アダプタ」を別々に組まなくて済む、というのが大きな利点。Webクローリング全体をAIエージェントに組み込みたいときの第一候補になりつつあります。
一般的なスクレイピングとの違い
従来型のスクレイピングは、おおむね「requests でHTMLを取得し、BeautifulSoupで解析する」という流れ。これは静的サイトには有効ですが、JavaScript実行を前提に組まれたSPAでは本文がほぼ取れない、という弱点を抱えています。
代わりに Playwright を直接呼び出してブラウザ自動化する方法も成立。ただ、その場合は「DOMが安定するまで待つ処理」「不要要素の除去」「Markdown変換」「セッション管理」「並列実行」などをすべて自前で書くことに。Crawl4AI はこれらを最初から備えており、薄いラッパーで一通り片付くのが違いです。
なぜ「LLM向け」なのか
LLMはトークン課金で動くため、入力に余計なナビゲーションや広告HTMLが混ざると、コストも精度も悪化。Crawl4AI は本文と思われる領域を自動的に絞り込み、Markdownへ変換するモードを備えています。LLMにとって読みやすい形まで前処理を済ませてから渡せる、ここが「LLM向け」と呼ばれるゆえん。
Crawl4AIが解決する現代Web収集の課題
ツールの良し悪しは、解決する課題の大きさで決まります。ここでは、なぜ今あえて新しいクローラーが必要なのか、現代サイトが抱える事情を整理。
JavaScript必須サイトの増加
ECサイトの商品一覧、SNSのタイムライン、ニュースサイトの「もっと読む」ボタン、ダッシュボード型の管理画面。いずれも、初期HTMLには「読み込み中」と書かれているだけで、本文はJavaScriptが走った後にAPI経由で挿入される構造になっています。
この種のサイトでは、requests.get(url).text を実行しても本文は1文字も含まれていない、という事態が普通に起こります。ヘッドレスブラウザを起動し、JavaScriptを実行し、DOMが落ち着くまで待つ。この一連の処理なしには、もはや「ページの中身を取得した」と言えない、というのが現実的な認識でしょう。
Crawl4AI は内部で Playwright + Chromium を立ち上げ、ページがロードされてから一定の安定条件を満たすまで自動で待機します。ユーザーが書くのは「URLを渡して、結果を受け取る」というシンプルな関数呼び出しだけ。
bot検知と無限スクロール
加えて、CloudflareやAkamaiなどのbot検知を備えたサイトが増えていることも見逃せません。User-AgentやTLSフィンガープリントを偽装する程度では弾かれてしまうケースも多いのが現状。
Crawl4AI は実ブラウザを立ち上げる方式のため、JavaScriptランタイムやWebGL、Canvasフィンガープリントといった「実ブラウザらしさ」が自然と備わります。完全な検知回避は保証されませんが、スクリプト型クライアントよりは通過率が高い構成。
無限スクロールについても、js_code 引数でスクロール処理を注入し、追加コンテンツの読み込み待ちを入れるという定石があります。
LLMに渡す前処理の標準化
LLM活用を前提にした場合、最大のボトルネックは「ノイズの多いHTMLをいかに整形するか」という点です。広告、関連記事一覧、フッター、ソーシャルシェアボタン。これらをそのままLLMに渡すと、トークンを浪費した上に肝心の本文への注意力も下がります。
Crawl4AI は HTML → Markdown 変換を標準装備しており、fit_markdown のような本文絞り込みオプションも用意。整形済みMarkdownをそのまま LangChain や LlamaIndex に渡せる、というワークフロー設計になっています。前処理をライブラリ側に寄せたい人には強力な選択肢ですね。
Crawl4AIの動作環境とインストール手順
ここからは実際の環境構築に入ります。Python のインストールから、Playwright とブラウザの依存関係まで順に押さえていきましょう。
pip install crawl4aiの基本
Crawl4AI はPyPIで配布されているため、まずは標準的な pip でのインストールが基本となります。Python 3.9 以降が推奨。仮想環境内で pip install -U crawl4ai を実行すれば、本体ライブラリの導入が完了します。
非同期処理を内部で多用するため、Jupyter NotebookやGoogle Colabで動かす場合は nest_asyncio を併せて入れておくと、イベントループ衝突によるエラーを避けられます。後述するLLM抽出機能を使う場合は、スキーマ定義に pydantic を使う場面が多いため、これも一緒に入れておくと作業が滑らか。
ブラウザ依存関係のセットアップ
Crawl4AI 本体を入れただけでは、まだ Chromium が手元にない状態。Playwright のCLIから別途インストールする必要があります。具体的には python -m playwright install chromium を実行すると、専用ディレクトリに Chromium バイナリがダウンロードされます。
Linux環境の場合、Chromium が依存するシステムライブラリ群を別途入れることに。ベース記事のサンプルコードでは、apt 経由で libnss3 / libnspr4 / libatk1.0-0 / libcups2 / libdrm2 / libxkbcommon0 / libxcomposite1 / libxdamage1 / libxfixes3 / libxrandr2 / libgbm1 / libasound2 などをまとめてインストールしている流れ。Playwright自身も playwright install-deps chromium というコマンドで、必要な依存関係を自動解決してくれます。
WindowsやmacOSでは依存関係解決はOS側に任せられるため、playwright install chromium 1行で済むケースがほとんどです。
初回起動時のつまずきポイント
実際に動かしてみると、いくつか定番のトラブルに当たります。
最も多いのは、Linuxサーバー(特にDocker内やColab)でChromiumの起動に失敗するケース。これは大半が依存ライブラリの不足が原因で、上述の playwright install-deps chromium を root権限で実行することで解決します。
次に多いのが、Jupyter環境での RuntimeError: This event loop is already running というエラー。これは nest_asyncio.apply() を冒頭で呼んでおくことで解消できます。
ここまでが下準備。次から、いよいよコードでCrawl4AIを動かしていきます。
基本クロール:最小構成で1ページを取得する
最初に取り組むのは、URLを1つ指定してページの中身を取ってくる基本パターン。Crawl4AI のAPIは、この基本形をきちんと押さえれば応用が効きやすい構造になっています。
AsyncWebCrawlerの役割
Crawl4AI の中心となるクラスが AsyncWebCrawler です。名前の通り非同期APIを採用しており、内部で Playwright のブラウザインスタンスを立ち上げ、ページのロード・JavaScript実行・DOM安定待ちまでを一手に引き受けます。
最小構成は、async with AsyncWebCrawler() as crawler: のコンテキストマネージャでクローラーを起動し、await crawler.arun(url=…) でページを取得する、という2行に近い形。返り値は CrawlResult オブジェクトで、ここに HTML・Markdown・メタデータ・リンク一覧・スクリーンショットなど、取得した情報がまとめて入る作りになっています。
非同期APIのメリットは、後で並列クロールに進んだときに効いてきます。1ページ目の本文を解析している間に2ページ目のリクエストを投げる、という設計が自然に書けるのが利点。
BrowserConfigとCrawlerRunConfig
Crawl4AI には設定オブジェクトが2系統あります。1つは BrowserConfig、もう1つは CrawlerRunConfig。役割を混同しやすいため、ここで切り分けておきましょう。
BrowserConfig は「ブラウザ自体の設定」を司ります。ヘッドレスで動かすか、画面付きで動かすか。User-Agentをどうするか。プロキシを通すか、ビューポートのサイズはいくつにするか。これらは1セッション中はあまり変えない設定群で、AsyncWebCrawlerのコンストラクタに渡す形。
一方の CrawlerRunConfig は「個々のクロール実行ごとに変えたい設定」を担当します。キャッシュをバイパスするか、抽出戦略は何を使うか、JavaScriptコードを注入するか、スクリーンショットを撮るか。arun() の config 引数に渡すことで、ページごとに異なる挙動を指定できる仕組み。
この2層構造を理解しておくと、後で「セッションは維持したいが抽出戦略だけ変えたい」というニーズに自然に応えられます。
返り値からどんな情報が取れるか
arun() が返す CrawlResult には、HTML・Markdown・cleaned_html・media(画像URL一覧)・links(内部/外部リンク)・metadata(タイトル・description等)など、複数のフィールドが詰まっています。Markdown の生成は標準でON。何も指定しなくても result.markdown でLLMに渡せる本文が得られる、というのが体験として軽い。
最初のうちは print(result.markdown[:1000]) で先頭部分を眺めるだけでも、変換品質の高さが体感できるはず。
Markdown生成機能の使いどころ
Crawl4AI が他のクローラーと一線を画す最大のポイント。それが、HTMLから本文を抽出してMarkdown化する機能です。
LLM入力向けのノイズ除去
LLMにHTMLをそのまま渡すと、<div> や <span> のような構造タグ、CSSクラス名、データ属性などがすべてトークンとして消費されます。GPT-4クラスのモデルでも、長文HTMLからの情報抽出は精度が落ちやすく、コストも跳ね上がるのが実情。
Crawl4AI は内部で複数段階の整形を経て、本文と思われる箇所を抜き出してMarkdownに変換します。標準モードでは比較的素直なHTML→Markdown変換になりますが、ノイズが多いサイトに対しては fit_markdown という整形済みのMarkdownも別フィールドで提供。広告や関連記事リンクを排除した、本文中心の出力が得られる仕組みになっています。
実際にニュースサイトで試すと、見出し・本文・引用が階層構造を保ったまま落ちてくる。LLMに渡したときの引用精度が体感でわかるレベルで上がる、というのが大きな価値です。
保存と再利用の運用
取得したMarkdownはそのままファイルに保存しておくと、後段の処理で再利用しやすくなります。例えば、毎日同じサイトをクロールして差分を抽出する、社内のRAG(Retrieval Augmented Generation)データベースに投入する、という使い方。
ファイル名にはURLのスラッグや取得日時を入れておくと管理が楽。カインズが190万行の表計算地獄を脱出した事例のように、AIエージェントが業務データを自動で加工していく流れの中では、Web収集の出力形式をMarkdownに統一しておくことが、後段のチェーン化を楽にする大事な設計判断になります。
整形オプションの調整
Markdownの粒度はオプションで微調整可能です。ヘッダーをどこから拾うか、コードブロックをそのまま残すか、画像Markdownを生成するかどうか、といった項目。サイトごとに最適値が違うため、まずは標準設定で試して、不満が出たら絞り込みパラメータを足していく、という順番が現実的でしょう。
「本文が広告に侵食されている」と感じたら、fit_markdown を使う、word_count_threshold を上げて短いブロックを切り捨てる、CSS抽出と組み合わせる、といった手段で対応できます。
CSSセレクタによる構造化抽出
Markdownはあくまで「読み物として整形された文字列」。一覧ページから商品名と価格を取り出す、求人サイトから職種・給与・勤務地を抜く、といった構造化データの収集には別のアプローチが必要になります。
スキーマの書き方
Crawl4AI には JsonCssExtractionStrategy という抽出戦略が用意されています。これはCSSセレクタとフィールド名を組み合わせたスキーマを定義し、ページから自動で構造化データを引き抜く仕組み。
スキーマはPythonの辞書で書きます。トップレベルに name(スキーマ名)、baseSelector(繰り返し要素の親)、fields(フィールド定義のリスト)を置くのが基本形。各フィールドには name(出力時のキー)、selector(CSSセレクタ)、type(text / attribute / html / nested 等)を指定します。
例えば商品一覧ページなら、baseSelector を商品カードの class に設定し、fields で商品名・価格・画像URLをそれぞれ拾う、という書き方。CrawlerRunConfig の extraction_strategy に渡すと、result.extracted_content にJSON文字列で結果が入ってきます。
CSSセレクタが書ける人なら、5分から10分でスキーマが完成。Pythonコードで複雑な抽出ロジックを書かなくて済むのがメリットです。
ネスト構造の取り出し
商品ページに「サイズごとの在庫」「複数のレビュー」のような繰り返し構造が含まれる場合、nested 型のフィールドが活きてきます。フィールドの type を nested または nested_list に指定し、その中にさらに fields を持たせる、という入れ子構造。
これにより、1回の抽出で「商品 → レビュー一覧 → 各レビューの著者・本文・星数」までを階層的なJSONで取り出せる、という設計が可能。後段でDBに正規化するかRAGに食わせるか、用途に合わせて加工しやすい形で確保できます。
スキーマ抽出が向かないケース
便利な反面、CSS抽出には弱点もあります。サイトのHTML構造が頻繁に変わる場合、毎回スキーマをメンテする必要が出てくる、という運用負荷。また、構造が個体ごとに大きく異なる「半構造化サイト」(個人ブログ・PDF由来のWebページ等)では、CSSセレクタを安定して書けないこともあるでしょう。
そうしたケースでは、後述の LLM ベース抽出に切り替えるか、両者をハイブリッドで使うのが現実的な選択肢になります。
JavaScript実行とセッション管理
ここまでは「ページを開いて読む」までの話。実際のスクレイピングでは「ボタンを押す」「フォームを送る」「ログイン状態を維持する」といった操作が必要な場面が多発します。
js_code引数の活用
CrawlerRunConfig の js_code 引数に文字列を渡すと、ページロード後にその JavaScript がブラウザコンテキストで実行されます。複数行のコードを文字列のリストで渡すことも可能。
典型的な使い方は、無限スクロールサイトの「もっと読む」を発火させるパターン。window.scrollTo(0, document.body.scrollHeight) を実行して下までスクロールし、その後 wait_for 引数で新しい要素の出現を待つ、という流れ。これだけで、初期表示では取れなかった2ページ目以降のコンテンツが回収できます。
ボタンクリックも同様で、document.querySelector(‘.load-more’).click() をjs_codeに渡すだけ。Playwrightを直接書く場合と比べて、コード量が圧倒的に減ります。
セッションIDで状態を保持する
ログイン後の画面を取得したい、複数ページを連続で巡回したい、という場合に重要なのが session_id の概念です。CrawlerRunConfigに同じsession_idを指定して arun() を複数回呼ぶと、ブラウザコンテキスト・Cookie・ローカルストレージが共有されます。
これにより、1回目でログインフォームを送信し、2回目以降は認証済み状態でページを開く、という流れが組めるわけ。クッキーのexport/importを自前で書かなくても、セッションが自動的に持続します。
対話的な操作の組み立て方
実際にログイン後の画面を取りに行く流れを書くと、以下のような順序になります。
- 1回目の arun() でログインページを開き、js_code で username / password を入力してフォームを送信
- 2回目の arun() で、同じ session_id を使って認証後の対象ページにアクセス
- 必要なら3回目以降で続きのページや個別詳細をクロール
この一連の操作を、ブラウザを再起動せずに一気通貫で進められる、というのがセッション機能の本質的な価値です。
パスワードはコード内に直書きせず、環境変数か `.env` ファイルから読み込むこと。Crawl4AI はあくまでクローラーであり、認証情報の安全な管理は利用者側の責任になります。GitHub等の公開リポジトリへ誤って認証情報をpushしないよう、`.gitignore` の整備も忘れずに。
ここまでが Crawl4AI の基本機能。インストールから単一ページ取得、Markdown化、CSS抽出、JS実行、セッション管理までを一通り押さえました。後半では、並列クロールや深層クロール、LLM抽出、運用上の注意点、仕様一覧、FAQへと続いていきます。
スクリーンショット・リンク解析・並列クロール
ここからは、実運用で効いてくる機能群。単一ページを取るだけの使い方から一歩進んで、サイト全体を効率よく回すための道具です。
スクリーンショットで検証精度を上げる
CrawlerRunConfig(screenshot=True) を指定すると、対象ページのフルスクリーンショットが取得できる仕組み。取得結果はBase64エンコードされた画像として返却されるため、ファイルとしてデコード保存すれば検証に使えます。抽出が失敗したときに「そもそもページがどう見えていたか」を後から確認できるのは大きな武器。bot検知でブロックされていないか、遅延読み込みの要素が描画されたか、といった判断が目視で可能になる。
リンク解析で次のクロール対象を見つける
Crawl4AI は取得結果のなかに、内部リンク・外部リンクを自動で分類した一覧を返します。これを使えば、記事ページから関連ページへ、カテゴリページから詳細ページへ、といった遷移を機械的に辿れるわけ。深層クロールと組み合わせれば、手書きでURLリストを管理する手間が大幅に減ります。
並列クロールのスループット
arun_many() に複数URLを渡すと、ブラウザコンテキストを共有したまま並列でクロールを走らせられます。1本ずつ順番に回すのに比べて、大量URL処理のスループットは段違い。ただし並列数を上げすぎると相手サーバーへの負荷が一気に増えるため、max_concurrent で制御すること。一般論として、同一ドメインへの同時接続は数本程度に抑えるのが礼儀です。
深層クロールでサイト全体を探索
単一URLを起点に、リンクを辿ってサイト全体を回るのが深層クロール(Deep Crawl)の役目。Crawl4AI では、探索戦略(BFS / DFS)・深さ制限・ドメイン制約・URLフィルタを組み合わせて設計します。
探索戦略の選び方
- BFS(幅優先): トップページから順に「近い階層」を先に回る。サイトマップ的な網羅に向く
- DFS(深さ優先): 1本のリンクを深く辿る。記事シリーズや連載の掘り下げに向く
深さはmax_depth、取得上限はmax_pagesで制御。ドメイン外への流出を防ぐには、allowed_domains を必ず設定してください。設定漏れで外部サイトに飛び火するのは、クローラー設計でよくある事故のひとつ。
レート制限と礼儀正しさ
対象サーバーに負荷をかけないための設定として、リクエスト間隔の遅延(delay)や同時接続数の上限を入れること。robots.txt の尊重も含め、「相手サイトを落とさない」という原則は常に守るべき姿勢です。
LLMベースの構造化抽出
CSSセレクタが書けないページ、またはページごとに構造が揺れるサイトでは、LLMExtractionStrategy が有効。Pydanticでスキーマ(取り出したいフィールドの型定義)を宣言し、ページ本文をLLMに渡して構造化JSONを返させる仕組みです。
LLMExtractionStrategyの基本
指定できるのは、プロバイダ名(OpenAI・Anthropic・ローカルLLM等)、APIキー、スキーマ、抽出指示プロンプト。Markdown化された本文がLLMに送られるため、CSSルールを書かなくても意味ベースで情報を取り出せます。
ローカルLLMと商用APIの使い分け
大量URLを処理する場合、商用API課金は一気に膨らむリスクが現実味を帯びる。近年はローカルLLMによる自律的なコード検証・修正の事例がコミュニティで増えており、Crawl4AI × ローカルLLMの組み合わせでコストゼロの自動抽出環境を作ることも技術的には可能です。精度が求められる本番用途は商用API、量が効く前処理はローカル、という使い分けが現実的。
実運用で押さえるべき注意点
強力な道具ほど、使い方次第で迷惑行為にもなり得る。Crawl4AIを本番投入する前に、以下を整理してください。
User-Agent偽装や過度な待機時間ジッター、Cloudflare突破のためのフィンガープリント偽装などは、対象サイトの利用規約違反になるケースが多い。技術的にできることと、法的・倫理的にやってよいことは別問題です。
収集対象サイトとの付き合い方
- robots.txt の指示に従う
- 利用規約のスクレイピング禁止条項を事前確認
- 連絡可能なUser-Agentを設定(問い合わせ先を明示)
- レート制限を自主的に守る
データ保管とコンプライアンス
個人情報を含むページを機械的に収集する場合は、個人情報保護法・GDPR等の規制対象。業務用途では、法務チェックを通したうえで収集範囲を定義するのが筋です。AIエージェントによる自動化の潮流は、カインズのVertex AI Agent Builder事例のように、データ基盤の整備とセットで成立します。
仕様まとめ
- 名称
- Crawl4AI
- 提供形態
- オープンソース(GitHub: unclecode/crawl4ai)
- 言語
- Python(async対応)
- ベース技術
- Playwright + Chromium
- 主要機能
- 基本クロール / Markdown生成 / CSS構造化抽出 / JS実行 / セッション管理 / スクリーンショット / リンク解析 / 並列クロール / 深層クロール / LLMベース抽出
- 料金
- 本体無料。LLM抽出で商用APIを使う場合はその従量課金のみ
- 公式ドキュメント
- docs.crawl4ai.com
よくある質問
Q. Crawl4AIは無料で使えますか?
本体はオープンソースで無料。LLM抽出機能で商用API(OpenAI等)を利用する場合のみ、そのAPI料金が発生します。ローカルLLMに繋げば追加費用ゼロで運用も可能。
Q. Playwrightを直接使うのと何が違いますか?
Crawl4AIはPlaywrightをラップし、Markdown変換・構造化抽出・セッション管理・並列処理・LLM連携をすぐ使える形にまとめた高レベルAPI。Playwright単体だと自前で書く必要がある「LLMに渡す前処理」が標準装備されているのが本質的な違いです。
Q. 日本語サイトでも問題なく動きますか?
動きます。ChromiumがUTF-8をそのまま扱うため、日本語ページのHTML取得もMarkdown化も問題なく可能。LLM抽出も、プロンプトを日本語で書けば日本語データをそのまま構造化できます。
まとめ
Crawl4AIは、LLM時代のWeb収集で「とりあえずこれを使っておけば足りる」と言える実用標準の候補。基本クロール→Markdown化→CSS抽出→JS実行→LLM抽出、という順で段階的に機能を覚えれば、単純スクレイピングから高度な自律収集まで幅広くカバーできます。まずは1ページ取得を動かし、次に構造化、最後にLLM抽出という学習導線を意識してみてください。


コメント