Gemini API の Search Grounding で Google 検索を自動化する
IT技術
はじめに
仕事してると「同じような検索を何十回もやってるな...」ってこと、ありませんか?
エンジニアに限らずいろんな業種であると思います。
- 営業の人が架電リストの会社を1件ずつ調べて電話番号メモる
- 経理の人がインボイス対応で法人番号を国税庁サイトで1社ずつ検索する
- マーケの人が競合企業の従業員数とか売上を調べまくる
- 店舗の営業時間や住所をひたすらコピペする
こういう「パターンは同じだけど、対象が違う検索」を何百回もやるの、正直しんどいですよね。
最近はAIの発達がすごく、こういう作業はおおかた自動化できるようになっています。今回は、Gemini API とSearch Grounding を使って企業情報の保管をしていきましょう。これが簡単で結構すごくて、要は「Gemini に Google 検索させる」機能です。モデルが勝手に検索して、最新の情報を取ってきてくれます。
この記事では、企業情報の取得を例に、Search Grounding の使い方とか、モデルごとの精度の違いとか、コストの話をまとめます。プロンプトを変えれば企業情報以外にも使えるので、参考になれば。
実装には、Google Apps Script(GAS) を使いました。スプレッドシートと連携しやすいし、サーバー不要でサクッと動かせるので便利です。
注意: Search Grounding を使っても精度は100%ではありません。あくまで「手作業を大幅に減らせる」ツールであって、重要なデータは最終的に人間が確認する必要があります。
Gemini API のセットアップ
事前準備
Search Grounding を使うには、以下の準備が必要です。
- Google Cloud プロジェクトの作成 - Google Cloud Console で新規プロジェクトを作成
- 課金アカウントの設定 - クレジットカードを登録(無料枠内なら請求されない)
- Gemini API の有効化 - プロジェクトで「Generative Language API」を有効化
この辺は「Gemini API 始め方」とかで検索すると詳しい記事がたくさん出てくるので、省略します!
ちなみに、Vertex AI 経由でサービスアカウントや Google アカウント認証を使う方法もありますが、今回はサクッと試したかったので API キー方式にしました。本番環境で使う場合は、API キーの漏洩リスクを考えて Vertex AI + Google アカウント認証の方が良いかもしれません。
API キーの取得
- Google AI Studio にアクセス
- 「Create API key」をクリック
- 発行された API キーをコピー
GAS での設定
GAS エディタで以下の手順で API キーを保存します。
- 「プロジェクトの設定」(歯車アイコン)を開く
- 「スクリプトプロパティ」セクションで「プロパティを追加」
- キー:
GEMINI_API_KEY、値: 取得した API キー
基本的な API 呼び出し
1function callGeminiAPI(prompt) {
2 const apiKey = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
3 const endpoint = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`;
4
5 const requestBody = {
6 contents: [{
7 role: 'user',
8 parts: [{ text: prompt }]
9 }],
10 generationConfig: {
11 temperature: 0.1, // 正確性重視のため低めに設定
12 maxOutputTokens: 4096
13 }
14 };
15
16 const options = {
17 method: 'post',
18 contentType: 'application/json',
19 payload: JSON.stringify(requestBody),
20 muteHttpExceptions: true
21 };
22
23 const response = UrlFetchApp.fetch(endpoint, options);
24 return JSON.parse(response.getContentText());
25}モデル比較検証
検証に使用したプロンプト
以下のプロンプトで各モデルを検証しました(詳細は「プロンプト設計のポイント」を参照)。
1あなたは日本の企業情報データベースの専門家です。
2以下の情報から、企業の詳細情報を調査・推定してください。
3
4【入力情報】
5- 会社名: 株式会社ライトコード
6
7【調査手順】
81. 企業の正式なウェブサイトを検索
92. 国税庁サイトで法人番号を検索
103. 採用ページ等から従業員数を推定
11
12【出力形式】
13JSON形式で以下を返してください:
14{
15 "companyName": "正式な会社名",
16 "website": "https://example.co.jp",
17 "houjinBangou": "1234567890123",
18 "prefecture": "東京都",
19 "employeeRange": "51-100名以下",
20 "confidence": "high"
21}
22
23【重要なルール】
24- 不明な項目は null を使用
25- URLは必ず http:// または https:// で開始検証したモデル
| モデル | 特徴 |
|---|---|
| gemini-2.0-flash | 高速・低コスト・バランス型 |
| gemini-2.5-flash | Flash改良版・中コスト |
| gemini-2.5-pro | Pro・高精度・高コスト |
実際の検証結果:「株式会社ライトコード」での比較
同一プロンプト + Search Grounding 有効で各モデルを検証しました。
※ Gemini 3.0系(gemini-3.0-flash / gemini-3.0-pro)は記事執筆時点でPreview版のため、今回の検証対象外としています。
| 項目 | gemini-2.0-flash | gemini-2.5-flash | gemini-2.5-pro |
|---|---|---|---|
| 会社名 | 株式会社ライトコード | 株式会社ライトコード | 株式会社ライトコード |
| ウェブサイト | https://rightcode.co.jp/ | https://rightcode.co.jp/ | https://rightcode.co.jp/ |
| 法人番号 | 7290801018296 ✅ | 7290801018296 ✅ | 7290801018296 ✅ |
| 都道府県 | 福岡県 ✅ | 福岡県 ✅ | 福岡県 ✅ |
| 従業員数 | 35-50名 | 31-50名 | 21-50名 |
| トークン数 | 744 | 3,294 | 5,613 |
モデル選定の結論
| モデル | 精度 | 速度 | コスト | 総合評価 |
|---|---|---|---|---|
| gemini-2.0-flash | ◎ | ◎ | ◎ | 採用 |
| gemini-2.5-flash | ◎ | ○ | △ | - |
| gemini-2.5-pro | ◎ | △ | × | - |
結論: 他の企業でもいくつか調べましたが、精度面ではモデル間の差はほとんど見られませんでした。主な違いはトークン消費量とコストです。コスト効率を考慮し、gemini-2.0-flash を採用しました。
Search Grounding の威力
Search Grounding とは
Gemini API に google_search ツールを有効化すると、モデルがリアルタイムで Google 検索を実行し、最新の情報を取得できます。
有効化方法
リクエストボディに tools パラメータを追加するだけです。
1const requestBody = {
2 contents: [{
3 role: 'user',
4 parts: [{ text: prompt }]
5 }],
6 tools: [{ google_search: {} }], // ← これを追加
7 generationConfig: {
8 temperature: 0.1,
9 maxOutputTokens: 4096
10 }
11};Search Grounding あり/なし の比較
同一プロンプト、同一モデル(gemini-2.0-flash)で「株式会社ライトコード」を検証した結果
| 項目 | Search なし | Search あり | なし | あり |
|---|---|---|---|---|
| 会社名 | 株式会社ライトコード | 株式会社ライトコード | ○ | ○ |
| ウェブサイト | https://www.rightcode.co.jp/ | https://rightcode.co.jp/ | × | ○ |
| 法人番号 | 2011001088 (10桁) | 7290801018296 (13桁) | × | ○ |
| 都道府県 | 東京都 | 福岡県 | × | ○ |
| 従業員数 | 11-50名 | 35-50名 | ○ | ○ |
| 信頼度 | high | medium | - | - |
| トークン数 | 359 | 744 | - | - |
Search なしは「自信満々で間違える」
上記の結果で最も注目すべき点
Search なしは confidence: "high" なのに、ほぼ全て間違っている!
- 法人番号は 13桁 が正しいのに 10桁 を返している(明らかに捏造)
- 本社は 福岡県 なのに 東京都 と回答
これは LLM の「ハルシネーション(幻覚)」の典型例です。学習データにない情報を、もっともらしく捏造してしまいます。
Search Grounding が実行した検索クエリ
API レスポンスの groundingMetadata.webSearchQueries で、実際に実行された検索を確認できます。
1[
2 "株式会社ライトコード 公式サイト",
3 "株式会社ライトコード 本社",
4 "株式会社ライトコード 国税庁法人番号",
5 "株式会社ライトコード 従業員数",
6 "株式会社ライトコード 売上"
7]プロンプトで「調査手順」を明示することで、Search Grounding が適切な検索を実行するよう誘導できます。
なぜここまで差が出るのか
Search なしの場合:
- モデルの学習データ(2023年頃まで)に含まれる情報のみ
- 法人番号のような最新データは取得できない
- しかも「自信満々」で間違った情報を返す
Search ありの場合:
- リアルタイムで企業の公式サイトを検索
- 国税庁サイトから法人番号を取得
- 採用ページから従業員数を推定
- 情報ソースが明確なので信頼性が高い
コスト構造と管理
料金体系
※ 2026年1月時点の情報です。最新の料金は公式ページをご確認ください。
| 項目 | 費用 |
|---|---|
| Gemini 2.0 Flash API | ほぼ無料(微量のトークン課金) |
| Search Grounding 無料枠(Free Tier) | 500回/日(Flash/Flash-Lite共有) |
| Search Grounding 無料枠(Paid Tier) | 1,500回/日(Flash/Flash-Lite共有) |
| Search Grounding 超過分 | $35/1,000リクエスト(約 ¥5.5/件) |
注意点
Search Groundingの無料枠はFree Tierで500回/日、Paid Tierで1,500回/日です。超過すると1件あたり約5.5円かかります。筆者は気づかずに8,000円ほど使ってしまいました...。
無料枠のリセットタイミング
- 太平洋時間(PT)午前0時
大量処理する場合は、リセット時刻を跨いで2日に分けると無料枠を有効活用できます。
プロンプト設計のポイント
基本構造
1あなたは日本の企業情報データベースの専門家です。
2以下の情報から、企業の詳細情報を調査・推定してください。
3
4【入力情報】
5- 会社名: ${companyName || "不明(要特定)"}
6- Eメール: ${email}
7- ウェブサイト: ${website}
8
9【調査手順】
101. メールドメインから会社名を特定
112. 企業の正式なウェブサイトを検索
123. 国税庁サイトで法人番号を検索
134. 採用ページ等から従業員数を推定
14
15【出力形式】
16JSON形式で以下を返してください:
17{
18 "companyName": "正式な会社名",
19 "website": "https://example.co.jp",
20 "phone": "03-1234-5678",
21 "houjinBangou": "1234567890123",
22 "prefecture": "東京都",
23 "employeeRange": "51-100名以下",
24 "revenueRange": "1-5億円未満",
25 "confidence": "high"
26}
27
28【重要なルール】
29- 不明な項目は null を使用("不明" や "なし" は禁止)
30- URLは必ず http:// または https:// で開始
31- 都道府県は47都道府県から選択精度を上げるコツ
- 調査手順を明示: Search Grounding が何を検索すべきか具体的に指示
- 出力形式を厳密に: JSON のキー名やバリデーションルールを明記
- 温度を低く設定:
temperature: 0.1で一貫性のある回答を得る - フリーメール除外: Gmail 等からは会社名を推定しないよう指示
大量データ処理の工夫
GASのコードで工夫した箇所もいくつか挙げておきます。
並列処理
GAS の UrlFetchApp.fetchAll() で複数リクエストを並列実行します。
1function getCompanyInfoBatch(dataList) {
2 const apiKey = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
3 const endpoint = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`;
4
5 // リクエストを配列で準備
6 const requests = dataList.map(data => ({
7 url: endpoint,
8 method: 'post',
9 contentType: 'application/json',
10 payload: JSON.stringify(buildRequestBody(data)),
11 muteHttpExceptions: true
12 }));
13
14 // 並列実行
15 const responses = UrlFetchApp.fetchAll(requests);
16
17 return responses.map((response, index) => {
18 try {
19 return JSON.parse(response.getContentText());
20 } catch (e) {
21 return { error: e.message, index: index };
22 }
23 });
24}GAS の実行時間制限対策
GAS は 6分でタイムアウトするため、バッチ処理で対応します。
1function runBatchProcess() {
2 const BATCH_SIZE = 500; // 1回の実行で処理する件数
3 const PARALLEL_COUNT = 30; // 同時実行数
4 const START_TIME = new Date();
5 const TIMEOUT_MS = 5 * 60 * 1000; // 5分でストップ(余裕を持たせる)
6
7 // 処理対象を取得
8 const rows = getUnprocessedRows();
9
10 for (let i = 0; i < rows.length; i += PARALLEL_COUNT) {
11 // タイムアウトチェック
12 if (new Date() - START_TIME > TIMEOUT_MS) {
13 Logger.log(`タイムアウト: ${i}件まで処理完了`);
14 return;
15 }
16
17 const batch = rows.slice(i, i + PARALLEL_COUNT);
18 const results = getCompanyInfoBatch(batch);
19 writeResultsBatch(results);
20
21 Utilities.sleep(1000); // API制限対策
22 }
23}バッチ書き込みで高速化
1件ずつ書き込むと遅いため、範囲指定で一括書き込みします。
1function writeResultsBatch(results) {
2 const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
3
4 // 対象範囲の既存値を一括取得
5 const range = sheet.getRange(startRow, startCol, results.length, colCount);
6 const values = range.getValues();
7
8 // メモリ上で更新
9 results.forEach((result, index) => {
10 values[index][0] = result.companyName;
11 values[index][1] = result.phone;
12 // ... 他の項目
13 });
14
15 // 一括書き込み
16 range.setValues(values);
17}まとめ
今回の実装で得た知見
- Search Grounding は必須: Search なしでは法人番号が10桁(本来13桁)で返ってくるなど、致命的な誤りが発生
- Search なしの「高信頼度」は危険:
confidence: "high"なのに間違っている = ハルシネーションの典型 - 無料枠を意識: Free Tierは500回/日、Paid Tierは1,500回/日。超過すると約 ¥5.5/件のコストが発生
- プロンプト設計が重要: 「調査手順」を明示することで Search Grounding が適切な検索を実行
注意点:精度は100%ではない
繰り返しになりますが、Search Grounding を使っても、取得できる情報の精度は100%ではありません。
- 検索結果に情報がなければ取得できない(非公開企業、小規模事業者など)
- 古い情報が検索上位に残っている場合、古いデータを返すことがある
- 同名の別会社を誤って取得する可能性がある
あくまで「手作業を大幅に減らすツール」として使い、重要なデータは最終的に人間がチェックすることをおすすめします。特にビジネスで使う場合は、取得したデータの正確性を確認する運用フローを組み込んでおくと安心です。
参考リンク
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!カジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ
趣味は映画を見ることです。




