はじめに
3ヶ月ほど前に使う機会があったGoogle Custom Search JSON API
の使い方をまとめた記事です。
手順
前提条件:
Googleアカウントを所持していること
1. 検索エンジンIDの作成
検索エンジン名を任意のものにします。
今回は特定のサイトのみの検索結果にし、https://qiita.com
にして追加します。
特定のサイトは、複数サイトを選択することができ、論文のみの検索にするときためにはhttps://scholar.google.com
やhttps://www.openaire.eu
などを複数追加するといいと思います。
エンジン名と検索対象が追加できると同じ画面下の作成ボタンをクリックして作成!
作成が完了し、画面が変わるとカスタマイズボタンをクリック
概要ページで基本的な情報や、検索対象などを確認することができます。
検索エンジンIDは後でコード内で使用します。
2. APIキーの取得
APIキーを作成します。上記のリンク内にあるキーを取得
のボタンをクリックし
Create a new project
でAPIキーを作成します。
作成が完了すると以下の画面が表示されます。
SHOW KEY
をクリックしてAPIキー
を表示することができます。
このAPIキーは後でコード内で使用します。
実装
まず、プロジェクトのディレクトリを作成し、VSCodeで開きます。
mkdir custom_search_demo
cd custom_search_demo
code .
rootディレクトリ
にmain.go
を作成します。
main.go
ファイルは、Google Custom Search API
を利用するために、主に以下の機能を実装しています。
- Ginフレームワークを使用したウェブサーバーの設定
- 検索リクエストを処理するエンドポイントの作成
- APIから取得した検索結果を返すロジック
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
)
// SearchRequest は検索リクエストを表す構造体です
type SearchRequest struct {
Query string `json:"query" binding:"required"`
}
// SearchResult は検索結果を表す構造体です
type SearchResult struct {
Items []SearchItem `json:"items"`
}
// SearchItem は検索結果の各アイテムを表す構造体です
type SearchItem struct {
Title string `json:"title"`
Link string `json:"link"`
Snippet string `json:"snippet"`
}
func main() {
r := gin.Default()
// エンドポイントの設定
r.POST("/search", handleSearch)
// ポートの設定
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
// サーバーの起動
r.Run(":" + port)
}
// handleSearch は検索リクエストを処理するハンドラーです
func handleSearch(c *gin.Context) {
// request body から検索クエリを取得
var req SearchRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"リクエストが正しくありません": err.Error()})
return
}
// Google Custom Search API を使って検索を実行
results, err := performGoogleSearch(c, req.Query)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"ハンドラー内でエラーが発生しました": err.Error()})
return
}
// レスポンスを返す
c.JSON(http.StatusOK, results)
}
// performGoogleSearch は Google Custom Search API を使って検索を実行します
func performGoogleSearch(ctx context.Context, query string) (*SearchResult, error) {
// env ファイルの読み込み
err := godotenv.Load()
if err != nil {
fmt.Println(".envファイルの読み込みに失敗しました")
}
// Google Custom Search API のエンドポイントのsetup
baseURL := "https://www.googleapis.com/customsearch/v1"
apiKey := os.Getenv("GOOGLE_API_KEY")
searchEngineID := os.Getenv("SEARCH_ENGINE_ID")
if apiKey == "" || searchEngineID == "" {
return nil, fmt.Errorf("APIキーまたは検索エンジンIDが設定されていません")
}
// エンドポイントを作成
req, err := http.NewRequestWithContext(ctx, "GET", baseURL, nil)
if err != nil {
return nil, fmt.Errorf("エンドポイントの作成に失敗しました: %v", err)
}
// クエリパラメータを設定
q := req.URL.Query()
q.Set("key", apiKey)
q.Set("cx", searchEngineID)
q.Set("q", query) // 検索クエリ
// URL にクエリパラメータをセット
req.URL.RawQuery = q.Encode()
// クライアントの作成
client := &http.Client{}
// Google Custom Search API にリクエストを送信
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("”リクエストの送信に失敗しました: %v", err)
}
defer resp.Body.Close()
// Google Custom Search API からのレスポンスをチェック
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("API からのレスポンスがエラーです: %s", body)
}
// レスポンスのデコード
var searchResponse struct {
Items []SearchItem `json:"items"`
}
if err := json.NewDecoder(resp.Body).Decode(&searchResponse); err != nil {
return nil, fmt.Errorf("デコードに失敗しました: %v", err)
}
// 検索結果を返す
return &SearchResult{
Items: searchResponse.Items,
}, nil
}
コード補足
今回のデモでは使用していませんが、検索するものをソート(日付順)や言語などを細かく設定できます。
以下のリンクにそれらのリファレンスがあるので参考にしてください。
https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list?hl=ja
プロジェクトの依存関係を初期化します。
-
go mod init demo
でGoモジュールを作成 -
go mod tidy
で必要な依存パッケージを自動的にダウンロードし、go.mod
ファイルを更新
go mod init demo
go mod tidy
環境変数ファイル(.env)では、セキュリティを考慮して以下の情報を設定します。
- GOOGLE_API_KEY: Google Custom Search APIにアクセスするための認証キー
- SEARCH_ENGINE_ID: 特定の検索エンジン(この場合はQiitaサイト)用の識別子
GOOGLE_API_KEY=api_key
SEARCH_ENGINE_ID=engin_id
動作確認
今回はPostmanで動作確認をします。
エンドポイント:POST
http://localhost:8080/search
リクエストボディー
{
"query": "きーたん"
}
こんな感じでqiita
内で「きーたん」が出てくる検索結果を取り出すことができます。
おわりに
Google Custom Search JSON APIは、検索したいドメインなどを絞ることによってwebサービスやスクレイピングなどに活用できるとても使い勝手がいいAPIです。是非皆さんも試してみてはいかがでしょうか?