【自己紹介】
皆様はじめまして。なると申します。
私は、文系大学卒業後に銀行へ入社し、現在4年目で法人営業に従事しています。
私がエンジニアを目指す理由はここでは割愛しますが、学習のアウトプット等を載せて
いきたいと思います。機会があればエンジニアを目指す理由もお話したいと思います。
また、8月には 42Tokyo の入試試験 Piscine にチャレンジする予定ですので、
そちらのお話もできればと思います。
よろしくお願いします。
【今回開発するアプリについて】
今回は、Youtubeの動画をランダムに検索するアプリを制作していきます。
完成したアプリのURLはこちら:
RandomYoutube
作成した目的は フィルターバブルの解消 です。
「フィルターバブル」とは、アルゴリズムがネット利用者個人の検索履歴やクリック履歴を
分析し学習することで、個々のユーザーにとっては望むと望まざるとにかかわらず見たい
情報が優先的に表示され、利用者の観点に合わない情報からは隔離され、自身の考え方や
価値観の「バブル(泡)」の中に孤立するという情報環境を指す。
皆さんも感じることがあるでしょう。
Youtubeを見ていると似たような動画ばかりがオススメに上がってきて、なかなか他の
ジャンルの動画を見ることが無い。面白い動画が見たいがどのように検索をかけるべきか
わからない。
私自身そう感じることが多く、他にも同じように感じる人が多くいるのではと考え、制作を
始めました。
新しい世界と出会うことで、人生が豊かになるのは間違いないですからね。
【YoutubeAPI】
実装したい処理
検索キーワード、アップロード日、並び順 で動画を検索し、
動画ID、サムネイル、タイトル、概要、再生回数、アップロード日を取得する。
コード記述前の準備
Google Cloudの設定
(プロジェクト作成・YoutubeAPiの有効化・APIキーの取得)
コードの実装
1 .envファイル
取得したAPIキーを環境変数に格納します。
YOUTUBE_API_KEY = "******************"
2 .gitignoreファイル
.envファイルをGithubにpushしないよう.gitignoreファイルに格納します。
# .gitignore
.env
3 API用ファイル
下記のファイルはルートディレクトリに配置します。
import { NextApiRequest, NextApiResponse } from "next";
const YOUTUBE_SEARCH_URL = "https://www.googleapis.com/youtube/v3/search";
const YOUTUBE_VIDEO_DETAILS_URL =
"https://www.googleapis.com/youtube/v3/videos";
const API_KEY = process.env.YOUTUBE_API_KEY;
export default async function searchVideos(
req: NextApiRequest,
res: NextApiResponse
) {
const {
query,
publishedAfter,
maxResults = "5",
order = "relevance",
videoDuration = "medium",
} = req.query;
//サーチ内容の型を確認
const queryStr = typeof query === "string" ? query : "";
const publishedAfterStr =
typeof publishedAfter === "string" ? publishedAfter : "";
const maxResultsStr = typeof maxResults === "string" ? maxResults : "5";
const orderStr = typeof order === "string" ? order : "relevance";
const videoDurationStr =
typeof videoDuration === "string" ? videoDuration : "medium";
// queryStr が空の場合には400 エラーを返す
if (!queryStr) {
res.status(400).json({ error: "query parameters error" });
return;
}
//
try {
const searchParams = new URLSearchParams({
part: "snippet",
q: queryStr,
type: "video",
publishedAfter: publishedAfterStr,
maxResults: maxResultsStr,
order: orderStr,
videoDuration: videoDurationStr,
key: API_KEY as string,
});
// パラメータにより検索した動画を JSON 形式で取得
const response = await fetch(`${YOUTUBE_SEARCH_URL}?${searchParams}`);
const videoData = await response.json();
// 取得したデータから各 videoId を取得し文字列作成
const videoIds = videoData.items
.map((item: any) => item.id.videoId)
.join(",");
// リクエストにより取得したい詳細データを指定
const detailsParams = new URLSearchParams({
part: "snippet,statistics",
id: videoIds,
key: API_KEY as string,
});
// 動画の詳細データを取得
const detailsResponse = await fetch(
`${YOUTUBE_VIDEO_DETAILS_URL}?${detailsParams}`
);
const detailsData = await detailsResponse.json();
res.status(200).json(detailsData.items.slice(0, Number(maxResults)));
} catch (error) {
console.error("YouTube APIにてエラーが発生:", error);
res.status(500).json({ error: "Server Error" });
}
}
4 メイン画面の検索ボタン実装
const handleSearch = async () => {
//タブとキーワードのいずれかが選択されていない場合はモーダルを表示
if (!checkInputs()) {
setIsModalOpen(true);
return;
}
//ローディング表示
setLoading(true);
try {
const response = await fetch(
//クエリとオーダーはエンコードする必要あり
`/api/search?query=${encodeURIComponent(
keyword
)}&publishedAfter=${selectedDate}&maxResults=5&order=${encodeURIComponent(
selectedOrder
)}`
);
//APIから帰ってきたデータをJSON形式でVideosへ格納
const data: Video[] = await response.json();
setVideos(data);
setSearchClick(true);
} catch (error) {
console.error("動画取得時にエラー発生:", error);
}
setLoading(false);
あとは取得した情報を表示して完成です。
【感想】
APIの使用方法が理解出来てきました。Udemy等の動画講義は非常にわかりやすいですが、
実際に自分で0から実装することでより理解が進みますね。また、一見難しそうな公式
ドキュメントを読み込むことが意外と近道だと感じました。
最後まで読んで頂き、ありがとうございました!
【参考文献・記事】