Web検索とスクレイピングツール
学習後できること
- web_searchツールを設定して、AIアシスタントがBrave SearchまたはPerplexity Sonarを使用してWeb検索できるようにする
- web_fetchツールを設定して、AIアシスタントがWebページのコンテンツをスクレイピングして抽出できるようにする
- 2つのツールの違いと使用シナリオを理解する
- APIキーと高度なパラメータ(地域、言語、キャッシュ時間など)を設定する
- 一般的な問題(APIキーエラー、スクレイピング失敗、キャッシュ問題など)をトラブルシューティングする
現在の課題
AIアシスタントのナレッジベースは静的であり、リアルタイムのWeb情報にアクセスできません:
- AIは今日のニュースを知りません
- AIは最新のAPIドキュメントや技術ブログを検索できません
- AIは特定のWebサイトの最新コンテンツを取得できません
AIアシスタントを「Web接続」させたいが、次のことが不明です:
- BraveとPerplexityのどちらを使用すべきか?
- APIキーはどこから取得するか?どう設定するか?
- web_searchとweb_fetchの違いは?
- 動的なWebページやログインが必要なサイトをどう扱うか?
いつ使用するか
- web_search:情報の高速検索、複数のWebサイトの検索、リアルタイムデータ(ニュース、価格、天気など)の取得が必要な場合
- web_fetch:特定のWebページの完全なコンテンツ抽出、ドキュメントページの読み取り、ブログ記事の分析が必要な場合
ツール選択ガイド
| シナリオ | 推奨ツール | 理由 |
|---|---|---|
| 複数のソースの検索 | web_search | 1回のクエリで複数の結果を返す |
| 単一ページのコンテンツ抽出 | web_fetch | 完全なテキストを取得、Markdownをサポート |
| 動的ページ/ログインが必要 | browser | JavaScriptの実行が必要 |
| シンプルな静的ページ | web_fetch | 軽量で高速 |
🎒 開始前の準備
前提条件
このチュートリアルでは、クイックスタートを完了し、Gatewayがインストールされ起動していることを前提としています。
- Gatewayデーモンが実行中
- 基本的なチャネル設定が完了(少なくとも1つの使用可能な通信チャネル)
- 少なくとも1つの検索プロバイダーのAPIキーが準備完了(BraveまたはPerplexity/OpenRouter)
注意
web_searchとweb_fetchは軽量ツールであり、JavaScriptを実行しません。ログインが必要なWebサイトや複雑な動的ページについては、browserツールを使用してください。
コアコンセプト
2つのツールの違い
web_search:Web検索ツール
- 検索エンジン(BraveまたはPerplexity)を呼び出して検索結果を返す
- Brave:構造化された結果(タイトル、URL、説明、公開日時)を返す
- Perplexity:AIが合成した回答と引用リンクを返す
web_fetch:Webページコンテンツスクレイピングツール
- 指定されたURLにHTTP GETリクエストを送信
- Readabilityアルゴリズムを使用して主要なコンテンツを抽出(ナビゲーション、広告などを削除)
- HTMLをMarkdownまたはプレーンテキストに変換
- JavaScriptは実行しない
なぜ2つのツールが必要なのか?
┌─────────────────┐ web_search ┌──────────────────┐
│ ユーザーがAIに質問│ ──────────────────→ │ 検索エンジンAPI │
│ "最新のニュース" │ │ (Brave/Perplexity) │
└─────────────────┘ └──────────────────┘
↓ ↓
AIが5つの結果を取得 検索結果を返す
↓
┌─────────────────┐ web_fetch ┌──────────────────┐
│ AIが結果を選択 │ ──────────────────→ │ 対象Webページ │
│ "リンク1を開く" │ │ (HTTP/HTTPS) │
└─────────────────┘ └──────────────────┘
↓ ↓
AIが完全なコンテンツを取得 Markdownを抽出典型的なワークフロー:
- AIがweb_searchを使用して関連情報を検索
- AIが検索結果から適切なリンクを選択
- AIがweb_fetchを使用して特定のページコンテンツをスクレイピング
- AIがコンテンツに基づいてユーザーの質問に回答
キャッシュメカニズム
両方のツールは重複リクエストを減らすために組み込みキャッシュを備えています:
| ツール | キャッシュキー | デフォルトTTL | 設定項目 |
|---|---|---|---|
| web_search | provider:query:count:country:search_lang:ui_lang:freshness | 15分 | tools.web.search.cacheTtlMinutes |
| web_fetch | fetch:url:extractMode:maxChars | 15分 | tools.web.fetch.cacheTtlMinutes |
キャッシュのメリット
- 外部APIの呼び出し回数を減らす(コスト節約)
- 応答速度を向上させる(同じクエリはキャッシュから返す)
- 頻繁なリクエストによるレート制限を回避
ここから始める
ステップ1:検索プロバイダーを選択
Clawdbotは2種類の検索プロバイダーをサポートしています:
| プロバイダー | メリット | デメリット | APIキー |
|---|---|---|---|
| Brave(デフォルト) | 高速、構造化された結果、無料層 | 従来の検索結果 | BRAVE_API_KEY |
| Perplexity | AI合成回答、引用、リアルタイム | PerplexityまたはOpenRouterのアクセスが必要 | OPENROUTER_API_KEY または PERPLEXITY_API_KEY |
推奨される選択
- 初心者:Braveの使用を推奨(無料層で日常使用には十分)
- AIの要約が必要:Perplexityを選択(生の結果ではなく合成された回答を返す)
ステップ2:Brave Search APIキーを取得
Braveを使用する理由:寛大な無料層、高速、構造化された結果で解析しやすい
2.1 Brave Search APIに登録
- https://brave.com/search/api/ にアクセス
- アカウントを作成してログイン
- Dashboardで "Data for Search" プランを選択("Data for AI"ではない)
- APIキーを生成
2.2 APIキーを設定
方法A:CLIを使用(推奨)
# インタラクティブ設定ウィザードを実行
clawdbot configure --section webCLIはAPIキーの入力を求め、~/.clawdbot/clawdbot.jsonに保存します。
方法B:環境変数を使用
APIキーをGatewayプロセスの環境変数に追加:
# ~/.clawdbot/.env に追加
echo "BRAVE_API_KEY=あなたのAPIキー" >> ~/.clawdbot/.env
# Gatewayを再起動して環境変数を有効化
clawdbot gateway restart方法C:設定ファイルを直接編集
~/.clawdbot/clawdbot.jsonを編集:
{
"tools": {
"web": {
"search": {
"apiKey": "BRAVE_API_KEY_HERE",
"provider": "brave"
}
}
}
}期待される結果:
- 設定保存後、Gatewayを再起動
- 設定済みのチャネル(WhatsAppなど)でメッセージを送信:「最新のAIニュースを検索して」
- AIが検索結果を返すはず(タイトル、URL、説明)
ステップ3:web_searchの高度なパラメータを設定
~/.clawdbot/clawdbot.jsonでさらにパラメータを設定できます:
{
"tools": {
"web": {
"search": {
"enabled": true, // 有効にするか(デフォルトtrue)
"provider": "brave", // 検索プロバイダー
"apiKey": "BRAVE_API_KEY_HERE",
"maxResults": 5, // 返回結果数(1-10、デフォルト5)
"timeoutSeconds": 30, // タイムアウト時間(デフォルト30)
"cacheTtlMinutes": 15 // キャッシュ時間(デフォルト15分)
}
}
}
}3.1 地域と言語を設定
検索結果をより正確に:
{
"tools": {
"web": {
"search": {
"provider": "brave",
"apiKey": "BRAVE_API_KEY_HERE",
"maxResults": 10,
// オプション:AIが呼び出し時にこれらの値を上書き可能
"defaultCountry": "US", // デフォルト国(2文字コード)
"defaultSearchLang": "en", // 検索結果の言語
"defaultUiLang": "en" // UI要素の言語
}
}
}
}よく使用される国コード:US(アメリカ)、DE(ドイツ)、FR(フランス)、CN(中国)、JP(日本)、ALL(全世界)
よく使用される言語コード:en(英語)、zh(中国語)、fr(フランス語)、de(ドイツ語)、es(スペイン語)
3.2 時間フィルタを設定(Brave専用)
{
"tools": {
"web": {
"search": {
"provider": "brave",
"apiKey": "BRAVE_API_KEY_HERE",
// オプション:AIが呼び出し時に上書き可能
"defaultFreshness": "pw" // 過去1週間の結果をフィルタ
}
}
}
}Freshnessの値:
pd:過去24時間pw:過去1週間pm:過去1ヶ月py:過去1年YYYY-MM-DDtoYYYY-MM-DD:カスタム日付範囲(例:2024-01-01to2024-12-31)
ステップ4:Perplexity Sonarを設定(オプション)
AI合成の回答を好む場合、Perplexityを使用できます。
4.1 APIキーを取得
方法A:Perplexity直通
- https://www.perplexity.ai/ にアクセス
- アカウントを作成してサブスクリプション
- SettingsでAPIキーを生成(
pplx-で始まる)
方法B:OpenRouter経由(クレジットカード不要)
- https://openrouter.ai/ にアクセス
- アカウントを作成してチャージ(暗号通貨またはプリペイドをサポート)
- APIキーを生成(
sk-or-v1-で始まる)
4.2 Perplexityを設定
~/.clawdbot/clawdbot.jsonを編集:
{
"tools": {
"web": {
"search": {
"enabled": true,
"provider": "perplexity",
"perplexity": {
// APIキー(オプション、環境変数でも設定可能)
"apiKey": "sk-or-v1-...", // または "pplx-..."
// Base URL(オプション、ClawdbotはAPIキーに基づいて自動推論)
"baseUrl": "https://openrouter.ai/api/v1", // または "https://api.perplexity.ai"
// モデル(デフォルトperplexity/sonar-pro)
"model": "perplexity/sonar-pro"
}
}
}
}
}Base URLの自動推論
baseUrlを省略すると、ClawdbotはAPIキーの接頭辞に基づいて自動的に選択:
pplx-...→https://api.perplexity.aisk-or-...→https://openrouter.ai/api/v1
4.3 Perplexityモデルを選択
| モデル | 説明 | 適用シナリオ |
|---|---|---|
perplexity/sonar | 高速Q&A + Web検索 | シンプルなクエリ、高速検索 |
perplexity/sonar-pro(デフォルト) | マルチステップ推論 + Web検索 | 複雑な問題、推論が必要 |
perplexity/sonar-reasoning-pro | 思考連鎖分析 | 深度研究、推論プロセスが必要 |
ステップ5:web_fetchツールを設定
web_fetchはデフォルトで有効で、追加設定なしで使用できます。パラメータを調整できます:
{
"tools": {
"web": {
"fetch": {
"enabled": true, // 有効にするか(デフォルトtrue)
"maxChars": 50000, // 最大文字数(デフォルト50000)
"timeoutSeconds": 30, // タイムアウト時間(デフォルト30)
"cacheTtlMinutes": 15, // キャッシュ時間(デフォルト15分)
"maxRedirects": 3, // 最大リダイレクト回数(デフォルト3)
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_7_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
"readability": true // Readabilityを有効にするか(デフォルトtrue)
}
}
}
}5.1 Firecrawlバックアップを設定(オプション)
Readability抽出が失敗した場合、Firecrawlをバックアップとして使用できます(APIキーが必要):
{
"tools": {
"web": {
"fetch": {
"readability": true,
"firecrawl": {
"enabled": true,
"apiKey": "FIRECRAWL_API_KEY_HERE", // またはFIRECRAWL_API_KEY環境変数を設定
"baseUrl": "https://api.firecrawl.dev",
"onlyMainContent": true, // メインコンテンツのみ抽出
"maxAgeMs": 86400000, // キャッシュ時間(ミリ秒、デフォルト1日)
"timeoutSeconds": 60
}
}
}
}
}Firecrawlのメリット
- JavaScriptのレンダリングをサポート(有効化が必要)
- より強力なスクレイピング回避能力
- 複雑なWebサイト(SPA、シングルページアプリケーション)をサポート
Firecrawl APIキーを取得:
- https://www.firecrawl.dev/ にアクセス
- アカウントを作成してAPIキーを生成
- 設定で設定または環境変数
FIRECRAWL_API_KEYを使用
ステップ6:設定を検証
web_searchを確認:
設定済みのチャネル(WebChatなど)でメッセージを送信:
TypeScript 5.0の新機能を検索して期待される結果:
- AIが5つの検索結果を返す(タイトル、URL、説明)
- Perplexityを使用している場合、AIが要約した回答と引用リンクを返す
web_fetchを確認:
メッセージを送信:
https://www.typescriptlang.org/docs/handbook/intro.html のコンテンツを取得して期待される結果:
- AIがそのページのMarkdown形式のコンテンツを返す
- ナビゲーション、広告などの無関係な要素が削除されている
ステップ7:高度な機能をテスト
地域フィルタをテスト:
ドイツのTypeScriptトレーニングコースを検索してAIはcountry: "DE"パラメータを使用して地域固有の検索を行えます。
時間フィルタをテスト:
先週のAI分野のニュースを検索してAIはfreshness: "pw"パラメータを使用して過去1週間の結果をフィルタリングできます。
抽出モードをテスト:
https://example.com を取得してプレーンテキスト形式で返してAIはextractMode: "text"パラメータを使用してMarkdownではなくプレーンテキストを取得できます。
チェックポイント ✅
次の設定が正しいことを確認してください:
- [ ] Gatewayが実行中
- [ ] 少なくとも1つの検索プロバイダーが設定済み(BraveまたはPerplexity)
- [ ] APIキーが正しく保存済み(CLIまたは環境変数経由)
- [ ] web_searchテスト成功(検索結果を返す)
- [ ] web_fetchテスト成功(ページコンテンツを返す)
- [ ] キャッシュ設定が合理的(過度なリクエストを回避)
クイック検証コマンド
# Gateway設定を表示
clawdbot configure --show
# Gatewayログを表示
clawdbot gateway logs --tail 50落とし穴の注意
一般的なエラー1:APIキーが未設定
エラーメッセージ:
{
"error": "missing_brave_api_key",
"message": "web_search needs a Brave Search API key. Run `clawdbot configure --section web` to store it, or set BRAVE_API_KEY in Gateway environment."
}解決策:
clawdbot configure --section webを実行- APIキーを入力
- Gatewayを再起動:
clawdbot gateway restart
一般的なエラー2:スクレイピング失敗(動的Webページ)
問題:web_fetchがJavaScriptを必要とするコンテンツをスクレイピングできない。
解決策:
- WebサイトがSPA(シングルページアプリケーション)か確認
- そうである場合、browserツールを使用
- またはFirecrawlバックアップを設定(APIキーが必要)
一般的なエラー3:キャッシュによりコンテンツが古い
問題:検索結果またはスクレイピングされたコンテンツが古い。
解決策:
cacheTtlMinutes設定を調整- またはAI対話で明示的に「キャッシュを使用しない」と要求
- Gatewayを再起動してメモリキャッシュをクリア
一般的なエラー4:リクエストタイムアウト
問題:大きなページまたは低速なWebサイトをスクレイピングする際にタイムアウト。
解決策:
{
"tools": {
"web": {
"search": {
"timeoutSeconds": 60
},
"fetch": {
"timeoutSeconds": 60
}
}
}
}一般的なエラー5:内部ネットワークIPがSSRFでブロック
問題:内部ネットワークアドレス(例:http://localhost:8080)へのスクレイピングがブロックされる。
解決策:
web_fetchはデフォルトで内部ネットワークIPをブロックしてSSRF攻撃を防止します。内部ネットワークに実際にアクセスする必要がある場合:
- browserツールを使用(より柔軟)
- または設定を編集して特定のホストを許可(ソースコードの変更が必要)
このレッスンのまとめ
- web_search:Web検索ツール、Brave(構造化結果)とPerplexity(AI合成回答)をサポート
- web_fetch:Webページコンテンツスクレイピングツール、Readabilityを使用して主要なコンテンツを抽出(HTML → Markdown/text)
- 両方に組み込みキャッシュ(デフォルト15分)、重複リクエストを減少
- Brave APIキーはCLI、環境変数、または設定ファイルで設定可能
- Perplexityは直通とOpenRouterの2つの方法をサポート
- JavaScriptが必要なWebサイトについては、browserツールを使用
- 設定パラメータには:結果数、タイムアウト時間、地域、言語、時間フィルタなどが含まれる
次のレッスンの予告
次のレッスンでは**Canvas可視化インターフェースとA2UI**を学びます。
学習内容:
- Canvas A2UIプッシュメカニズム
- 可視化インターフェース操作
- AIアシスタントにCanvas要素を制御させる方法
付録:ソースコード参照
クリックして展開するとソースコードの場所を表示
更新日時:2026-01-27
| 機能 | ファイルパス | 行番号 |
|---|---|---|
| web_searchツール定義 | src/agents/tools/web-search.ts | 409-483 |
| web_fetchツール定義 | src/agents/tools/web-fetch.ts | 572-624 |
| Brave Search API呼び出し | src/agents/tools/web-search.ts | 309-407 |
| Perplexity API呼び出し | src/agents/tools/web-search.ts | 268-307 |
| Readabilityコンテンツ抽出 | src/agents/tools/web-fetch-utils.ts | - |
| Firecrawl統合 | src/agents/tools/web-fetch.ts | 257-330 |
| キャッシュ実装 | src/agents/tools/web-shared.ts | - |
| SSRF保護 | src/infra/net/ssrf.ts | - |
| 設定Schema | src/config/zod-schema.core.ts | - |
重要な定数:
DEFAULT_SEARCH_COUNT = 5:デフォルト検索結果数MAX_SEARCH_COUNT = 10:最大検索結果数DEFAULT_CACHE_TTL_MINUTES = 15:デフォルトキャッシュ時間(分)DEFAULT_TIMEOUT_SECONDS = 30:デフォルトタイムアウト時間(秒)DEFAULT_FETCH_MAX_CHARS = 50_000:デフォルト最大スクレイピング文字数
重要な関数:
createWebSearchTool():web_searchツールインスタンスを作成createWebFetchTool():web_fetchツールインスタンスを作成runWebSearch():検索を実行して結果を返すrunWebFetch():スクレイピングを実行してコンテンツを抽出normalizeFreshness():時間フィルタパラメータを正規化extractReadableContent():Readabilityを使用してコンテンツを抽出