ブログに戻ります

AIリサーチアシスタントのためのソース発見ステップを構築する

Michael Lee
Michael Lee

Expert Network Defense Engineer

14-Sep-2026

TL;DR:

  • AIエージェントのためのGoogle検索APIは、ソース候補を提供します。 結果のURLとスニペットは発見データであり、回答の確認された証拠ではありません。
  • 明示的なハンドオフを構築します。 クエリのコンテキスト、候補の識別子、選択理由、および情報取得状況を保持し、引用をレビューされたコンテンツにさかのぼって追跡できるようにします。
  • ローカルアダプターから始めます。 以下のプログラムは、保存されたキャプチャをレビューキューに変換します。認証された収集とフルテキストの取得は、別々の前提条件のままです。

AI研究アシスタントは、URLsのリストを伴う説得力のある段落を返すことができますが、基本的な質問は未解決のままです:どのページが各文を実際に支持しているのでしょうか? 検索を追加するだけではその問題は解決しません。ワークフローは、目的地を発見することと、それを読み証拠として使用することを区別する必要があります。

Scrapeless Google Search API は、ソース発見ステップに適しています。このガイドでは、検索スニペットを完成した研究コーパスとして扱うことなく、AIエージェントのためのGoogle検索APIの使用方法を示します。ローカルアダプターは、次の作業者またはレビューアが各候補がキューに追加された理由を理解するのに十分なコンテキストを保持します。

発見契約の定義

発見作業は、研究質問と正確なクエリから始まります。質問は、送信されたリクエストの外にアプリケーションメタデータとして保持します。いくつかのクエリは一つの質問を探求できますが、それぞれの個別のコンテキストは回収可能であるべきです。

出力契約は、URL、観察されたテキスト、ソース順序、およびレビュー状態を含む候補レコードのセットです。それは確認された回答を含みません。候補は、レビュアーがそれを読んだ後、関連性がある、ない、アクセスできない、または優先されることがあります。

ダウンストリームシステムには明確なルールを示してください:取得され、レビューされた資料のみが主張を支えることができます。検索のみの候補は別の調査を示唆することができますが、それらは静かに回答の証拠リストに入ることはできません。この境界は、失敗を可視化するもので、回答生成者が欠落した証拠を信頼性のあるテキストで満たすことを許可しません。

前提条件とリクエストパラメータ

ローカルプログラムにはPythonと保存されたJSONキャプチャが必要です。標準ライブラリモジュールのみを使用します。キャプチャは、requesthttp_statusresponserun_id、およびreceived_atを含むアプリケーションエンベロープです。これらの外部名は、収集者のフィールドであり、確定されたAPIレスポンスラッパーではありません。

ライブコレクションにはアカウントAPIキーが必要です。 Google検索リクエストワークフロー では、POST https://api.scrapeless.com/api/v1/scraper/requestx-api-tokenヘッダー、およびアクターscraper.google.searchが文書化されています。検索パラメータはinput内に入れます。

リクエストを形成する前に、Google検索パラメータを確認してください。国、言語、およびクエリの文言が検索コンテキストを決定します。フルURLモードを使用する場合、他の入力パラメータは無視されます。提出されたURLを保持し、後で効果的な設定を考案することがないようにします。

注意: この文書に対して認証されたAPIコールやフルテキストの取得は行われませんでした。実行可能なステップは、合成キャプチャでテストされたローカルトランスフォームです。ライブデータを収集するか、保留中のタスクを解決するには、まず現在のドキュメントでアカウントワークフローを確認し、その実際の出力を検査してください。

結果を読む前にレスポンス状態を保持する

HTTP 200はタスクデータを運び、HTTP 201は保留中のタスクを表します。利用可能な場合は、戻されたtaskIdを保持します。保留中のタスクは、あなたの確認された完了ワークフローが最終結果を生成するまで保留されたままでなければなりません。アダプターは情報取得エンドポイントを推測しません。

完了したレスポンスについては、文書化されたorganic_results配列を検査します。欠落または誤った型のフィールドはunmapped状態を生成し、存在している空の配列はemptyを生成します。これらの結果には次のステージに対して異なる意味があります。

JSON値モデルは、nullやネストされた値を消去せずに生のレスポンスを保持することをサポートします。アダプターが狭い候補リストを生成した後でさえ、キャプチャを記録のソースとして保持します。

ローカル候補アダプターを構築する

このコードをsource_candidates.pyとして保存します。キャプチャファイルでpython3 source_candidates.py capture.jsonを実行します。派生したJSONを標準出力に印刷し、入力ファイルは変更されません。APIリクエスト、ページ取得、またはモデル呼び出しは行われません。

python Copy
import argparse
import json
from pathlib import Path
from urllib.parse import urlsplit


def candidates(record):
    if not isinstance(record, dict):
        raise ValueError('Capture must be an object')
    status = record.get('http_status')
    payload = record.get('response')
    base = {'run_id': record.get('run_id'), 'request': record.get('request'),
            'received_at': record.get('received_at'), 'candidates': []}
    if status == 201:
        task = payload.get('taskId') if isinstance(payload, dict) else None
        return dict(base, state='pending', task_id=task)
    if status != 200:
        return dict(base, state='transport_error' if status is None else 'http_error')
    rows = payload.get('organic_results') if isinstance(payload, dict) else None
    if not isinstance(rows, list) or any(not isinstance(row, dict) for row in rows):
        return dict(base, state='unmapped')
    output, seen = [], set()
    for ordinal, row in enumerate(rows):
        link = row.get('link')
        reason, host = None, None
        try:
            parsed = urlsplit(link) if isinstance(link, str) else None
            if (parsed is None or parsed.scheme not in ('http', 'https')
                    or not parsed.hostname or parsed.username or parsed.password):
                reason = 'invalid_web_url'
            else:
                host = parsed.hostname.lower()
        except ValueError:
            reason = 'invalid_web_url'
        if reason is None and link in seen:
            reason = 'duplicate_exact_url'
        if reason is None:
            seen.add(link)
        output.append({'candidate_id': f'source-{ordinal}', 'ordinal': ordinal,
                       'position': row.get('position'), 'title': row.get('title'),
                       'url': link, 'hostname': host, 'snippet': row.get('snippet'),
                       'review_state': 'excluded' if reason else 'needs_review',
                       'exclusion_reason': reason, 'evidence_state': 'discovery_only'})
    return dict(base, state='observed' if rows else 'empty', candidates=output)


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('capture')
    args = parser.parse_args()
    result = candidates(json.loads(Path(args.capture).read_text(encoding='utf-8')))
    print(json.dumps(result, ensure_ascii=False, indent=2))

候補識別子はランにローカルであり、run_id と組み合わせて下流に送ります。正確な重複URLは除外された行として表示され、キューは結果を静かに破棄するのではなく、説明を保持します。他のURLのバリアントは、レビューを保留として別々に保持されます。

URLチェックは、URLコンポーネント解析を使用して、ホストの欠如、サポートされていないスキーム、および埋め込まれた資格情報を拒否します。これは入力形状のチェックであり、ネットワークフェッチャーのセキュリティ境界ではありません。後の取得サービスは、アドレス解決やリダイレクトを含む独自の宛先ポリシーを施行しなければなりません。

Scrapelessでのスクレイピングの開始

Scrapelessを使ってウェブスクレイピングと自動化のワークフローを強化しましょう!
今すぐサインアップして $5の無料クレジット を取得しましょう — クレジットカードは不要です。

今すぐScrapelessダッシュボードで無料クレジットを請求してください。

ソースを選択し、コンテンツを別々に取得する

各適格候補を質問に対してレビューします。選択または除外の理由を記録し、必要な事実を直接確立する証拠を優先します。高いオーガニックポジションは検索観察であり、信頼性スコアではありません。

選択されたURLは別の取得ステップに入ります。そのステップは要求されたURL、最終宛先、取得時間、コンテンツ参照、および結果を保持する必要があります。アクセス不可の宛先は引き続きアクセス不可のままであり、欠落した本文のスニペットを代わりにして取得済みと呼ぶことはしないでください。

Googleによる検索スニペットの説明は、なぜ抜粋が単なるリードなのかを説明しています。表現はクエリ依存であり、引用する必要がある部分と一致しない可能性があります。事実に基づく回答を導き出す前に、取得したソースを確認してください。

ページコンテンツを信頼できないデータとして扱います。ページにはアシスタントに向けた指示が含まれている可能性がありますが、それらの指示はあなたの研究タスクやツールの権限を変更するものではありません。取得した証拠と実行可能な指示の間の区別を、周囲のアプリケーションで明確に保ってください。

主張をレビューされたパッセージに結びつける

引用記録は、提案された主張を支持するパッセージとその取得元にリンクする必要があります。候補のアイデンティティは出所として保持しますが、パッセージの位置と取得記録を別々に保存します。URLだけでは、そのページが主張の表現を支持していることを示していません。

スコープと関連性をチェックしてください。ソースが一つの製品バージョンや一つの市場について議論している場合があります。アシスタントは、そのタイトルがトピックと一致するからといって、すべての構成に一般化すべきではありません。矛盾するソースは、未解決の質問や資格を伴う回答を生じるべきであり、検索ポジションに基づく恣意的な選択は行うべきではありません。

出所モデルは、証拠、処理した活動、および責任のある人またはシステムの間で有用な区別を提供します。あなたの実装は、これらの関係を保持しながら、よりシンプルな記録を使用することができます。

レビューされたソースが主張をサポートしない場合は、それを除外するか、ギャップを特定してください。ソースの発見は証拠ワークフローを改善しますが、サポートされていないモデル出力の削除を保証するものではありません。

エージェントを接続する前にアダプターをチェックする

現在のオーガニック配列、空の配列、欠落したフィールド、形式が不正なアイテム、HTTP 201、HTTPエラーのためのローカルチェックを実行します。重複URLや無効なスキームを含めてください。これらのフィクスチャは、アプリケーションの決定をテストしますが、APIの現在のカバレッジをテストするものではありません。

除外された行が元の観察を保持し、すべての候補が discovery_only であることを確認してください。プロダクションでアダプターを採用する前に、実際のアカウントキャプチャを検査してください。そのスキーマが異なる場合は、マッピングを明示的に更新し、比較のために元のレスポンスを保持してください。

エージェントフレームワークはこの境界でオプションです。JSON契約を消費できる任意の呼び出し元はレビューキューを使用できますが、特定のSDKまたはツールプロトコルとの互換性は独自の統合テストが必要です。ローカルプログラムはそのようなハンドシェイクを主張しません。

結論

検索発見を小さく、明示的に保ってください:リクエストを保持し、収集結果を分類し、レビュー状態を持つ候補を生成します。取得および引用確認は、その後、明確な入力契約を持ち、未説明のリンクのリストを引き継ぐことはありません。

同じソースレビューの規律は、コンテンツギャップ分析をサポートすることができます。これは、編集チームが新しい記事を割り当てる前に証拠を必要とする場合です。

次の検索観察を構築する

Scrapeless Google Search API を使用して、このワークフローの検索証拠を収集します。コレクション予算を計画する際には、Scrapelessの価格 を確認し、リクエスト構成の横に Google Searchパラメータ を置いておいてください。

コミュニティとの実装については、Discord または Telegram でお話ししましょう。

FAQ

Q: アダプターはページ全体のテキストを取得しますか?

いいえ。保存された検索データを候補に処理します。全文取得は別のステップで、その結果と証拠記録があります。

Q: 最初のオーガニック結果は自動的に引用できますか?

位置がページがあなたの主張を支持することを確立するわけではありません。引用する前に関連する部分を取得してレビューしてください。

Q: HTTP 201 はどうなりますか?

アダプターは pending を返し、利用可能な場合はタスク識別子を保持します。保留中の結果を取得したり、空の検索としてカウントしたりはしません。

Q: URL解析は候補を取得するのを安全にしますか?

いいえ。アダプターは基本的なURLの形をチェックします。フェッチャーは依然として解決されたアドレスとリダイレクトを処理するための宛先ポリシーが必要です。

Q: これは特定のエージェントフレームワークを必要としますか?

いいえ。デモされた境界はローカルJSONです。フレームワークの統合とライブアカウントのワークフローには別の確認が必要です。

Scrapelessでは、適用される法律、規制、およびWebサイトのプライバシーポリシーを厳密に遵守しながら、公開されているデータのみにアクセスします。 このブログのコンテンツは、デモンストレーションのみを目的としており、違法または侵害の活動は含まれません。 このブログまたはサードパーティのリンクからの情報の使用に対するすべての責任を保証せず、放棄します。 スクレイピング活動に従事する前に、法律顧問に相談し、ターゲットウェブサイトの利用規約を確認するか、必要な許可を取得してください。

最も人気のある記事

カタログ