記事内容
Google検索で表示される画像のデータを取得してNext.jsのアプリの画面に表示するまでの方法
GCP上でAPIと検索エンジンの準備をする
流れとしては自分用の検索エンジンを作って、その検索結果を使うことになる。
https://plus-pm.jp/blog/search-rank-check-use-google-custom-search-api/
この記事に従ってGoogle Custom Search APIのプロジェクトの作成、APIキーの取得、APIの有効化、Custom Search Engine(自分用の検索エンジン)を作成する。
Google API Client Librariesを使ってAPIを叩く
JavaScriptを選択すると、以下Githubのページに飛ぶ。
https://github.com/google/google-api-javascript-client
READMEの通りに進めていく。
TypeScriptの場合は@types/gapiを使えば良いとのことなので、そっちを使っていく。
npm install --save @types/gapi
https://developers.google.com/identity/oauth2/web/guides/migration-to-gis?hl=ja
上記のページの通りgoogle-api-javascript-clientは既に非推奨であった。
以前まではGoogleログインプラットフォームライブラリとGoogleAPIクライアントライブラリを使っていたが、これから Google Identity Services ライブラリに移行するらしい。
READMEのOption 2を試してみると、head
に以下のスクリプトタグを追加する必要があるので
Next.jsのHead
を使用して、layout.tsx
に追加。
<script src="https://apis.google.com/js/api.js"></script>
このスクリプトをそのまま使うと、Next.jsの非同期スクリプトエラーが出るため、async
属性を追加しました。
import Head from 'next/head';
const MyHead = () => {
return (
<Head>
<script src="https://apis.google.com/js/api.js" async />
</Head>
);
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<Providers>
<MyHead />
<div>{children}</div>
</Providers>
</body>
</html>
);
}
最後に、googleapisとaxiosをインストールし、custom searchのURLに各種情報を入れてAPIを叩く。
npm install googleapis axios
"use client";
import styles from "./page.module.css";
import { useState } from "react";
import { Input, IconButton, SearchIcon } from "@/plugins/chakra-ui-modules";
import axios from "axios";
import { customsearch_v1 } from "googleapis";
export default function Vocabulary() {
const [englishWord, setEnglishWord] = useState("");
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) =>
setEnglishWord(event.target.value);
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter") {
searchEnglishWord();
}
};
const searchEnglishWord = async () => {
searchImages();
};
const [images, setImages] = useState<string[]>([]);
const searchImages = async () => {
try {
const API_KEY = process.env.NEXT_PUBLIC_GOOGLE_SEARCH_API_KEY;
const CUSTOM_SEARCH_ENGINE_ID =
process.env.NEXT_PUBLIC_CUSTOM_SEARCH_ENGINE_ID;
const response = await axios.get(
`https://www.googleapis.com/customsearch/v1?q=${englishWord}&cx=${CUSTOM_SEARCH_ENGINE_ID}&key=${API_KEY}&searchType=image`
);
const items = response.data.items as customsearch_v1.Schema$Result[];
const imageUrls = items.map((item) => item.link || "");
setImages(imageUrls);
} catch (error) {
console.error("データの取得中にエラーが発生しました:", error);
}
};
return (
<div>
<div>
<Input
value={englishWord}
onChange={handleChange}
onKeyDown={handleKeyDown}
placeholder="英単語を入力してください。"
/>
<IconButton
aria-label="SearchIcon"
icon={<SearchIcon />}
onClick={searchEnglishWord}
/>
</div>
<div>
{images.map((imageUrl, index) => (
<img
key={index}
src={imageUrl}
alt={`image${index}`}
className={styles.image}
/>
))}
</div>
</div>
);
}