お久しぶりです!
突然ですが、NHKの番組って気付かぬ間に時間変更されていたり、連続録画しててもタイトルが変わってていつの間にか連続録画がされていない…なんてことはありませんか?
そこでNHK番組表API(無料)を使って、番組検索と事前に通知してくれるアプリを作成しようと思います!
NHK番組表APIとは?
NHK番組表API公式サイトには以下のように記されています。
番組表APIは、全国のNHKの放送番組のタイトルや放送時間などの番組情報を提供します。
4種類のAPIがあって、ジャンルを指定できるものや、番組の詳細を取得できるものがあるので、気になった方は公式サイトを見てみてください!
APIキーの取得方法
こちらのブログを大参考にさせていただきました!
目次の「3.NHK番組表APIのAPIキーを取得」に手順の全てが書かれているのだ。
APIキーは機密情報なので、絶対に外部に漏洩しないよう細心の注意を払ってください!
間違ってもGitHubにpushしないように…リモートリポジトリを削除する羽目になります。
いよいよコードを書き書き
さて、今回もViteでプロジェクトを新規作成しました。
最初に初期の不要なコンポーネントやコード、イメージを削除しておきましょうね。
APIから指定したパラメータでデータをフェッチし、ブラウザに表示するまでのコードは以下です!
(一部試験的に書いているところもあるので、悪しからず)
import { useEffect, useState } from "react";
import axios from "axios";
export const FetchPrograms = () => {
const [loading, setLoading] = useState(true);
const [programs, setPrograms] = useState([]);
const API_KEY = import.meta.env.VITE_NHK_API_KEY;
const area: string = "130";
const service: string = "e1";
const genre: string = "0700";
const date: string = "2025-02-26";
const url = `https://api.nhk.or.jp/v2/pg/genre/${area}/${service}/${genre}/${date}.json?key=${API_KEY}`;
useEffect(() => {
const fetchData = async () => {
try {
const res = await axios.get(url);
setPrograms(res.data.list.e1);
} catch (error) {
console.error("データ取得エラー:", error);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
return (
<div>
<h1>NHK 番組一覧</h1>
{loading ? <p>ロード中・・・</p> : <p>ロード完了</p>}
{programs.map((program, index) => (
<div className="programCardContainer" key={index}>
<p>{program.title}</p>
<p>{program.start_time}</p>
<p>{program.end_time}</p>
<p>{program.subtitle}</p>
<p>{program.content}</p>
<p>{program.act}</p>
</div>
))}
</div>
);
};
さて、所管をまとめましょう。
- エンドポイントを変数に格納
- 取得したAPIキーを「.env」ファイルに記述し、環境変数としてimport
- パラメータを変数にして、一旦特定の値を代入
- 非同期処理でgetリクエスト、エラーハンドリング
- データ配列からmapで繰り返し取り出し、動的にブラウザに表示
APIキーを環境変数にして.gitignoreでGitHubに載せないようにしているのですが、結局この方法だとデプロイした時に第三者にAPIキーを知られてしまいます。
ゆくゆくは、Firebaseでバックエンド管理する方法を調べて実装する予定です!
こんな感じで理解しながら進めています!
もう少し詳しい内容については、これから解説しますね。
エンドポイントを変数に格納
NHK番組表API公式サイトに掲載されている「Resource URL」がエンドポイントです。
https://api.nhk.or.jp/v2/pg/genre/{area}/{service}/{genre}/{date}.json?key={apikey}
{area}などに特定の値を入れることで正しいURLとして機能します。
そこで以下のコードのように、テンプレートリテラルで${area}とし、後ほど特定の値を変数にして適宜置換するようにしました!
const url = `https://api.nhk.or.jp/v2/pg/genre/${area}/${service}/${genre}/${date}.json?key=${API_KEY}`;
取得したAPIキーを「.env」ファイルに記述し、環境変数としてimport
まずは.envをルートディレクトリ直下に作成します。そして以下のコードでAPIキーを格納します。
VITE_NHK_API_KEY = あなたのAPIキー
頭に付いているVITEですが、これはViteでプロジェクトを起こしているためです!
次にエンドポイントを書いているファイルで、import.metaを使って呼び出します。
const API_KEY = import.meta.env.VITE_NHK_API_KEY;
前述していますが、これはあくまでGitHubにpushしないための対策ですので、デプロイする方はバックエンドで管理しましょう。
ちなみに何も知らなかった私はAPIキーをベタ打ちしてpushしたら、Gitからメールが来ました。
GitGuardian has detected the following Generic High Entropy Secret exposed within your GitHub account.
翻訳:GitGuardian が、あなたの GitHub アカウント内に以下の「高エントロピーの一般的な秘密情報(機密情報)」が公開されていることを検出しました。
高エントロピーとは、予測が難しくランダム性の高いデータのこと。つまりここで言うAPIキーです。
こうなるとリモートリポジトリを削除するか、Gitの運営さんにお願いして履歴を削除してもらう他ないのです。
私は、リポジトリの削除・APIキーの再生成で対応済みです!
これ、個人開発でリポジトリ削除できる環境だからよかったものの、チーム開発でやっちまうと死ぬほど大変なことになるし、情報漏洩しちゃうので、絶対にやっちゃダメです!!!勉強になった。
パラメータを変数にして、一旦特定の値を代入
パラメータに値を入れてあげましょう!
const area: string = "130";//東京
const service: string = "e1";//NHK Eテレ1
const genre: string = "0700";//アニメ/特撮(国内アニメ)
const date: string = "2025-02-26";//2025年2月26日
書けるなら最初からuseStateで書けばいいのですが、一旦APIからデータ取得できるかどうかわかりやすくするために、特定のパラメータを代入することにしています。
(TypeScriptで書いてますが、まだ学習中なので書けるところだけ試験的に書いてます…)
API叩くのに一筋縄ではいかなかったのですが、そのうち1つの理由がdateパラメータでした。
ずっと過去の日付で指定していたけど、当日か先日付じゃないとデータがなくて、これに気づくのに時間かかりました。
エラーの原因は足元に落ちていることを痛感しました。
非同期処理でリクエスト、エラーハンドリング
useEffect(() => {
const fetchData = async () => {
try {
const res = await axios.get(url);
setPrograms(res.data.list.e1);
} catch (error) {
console.error("データ取得エラー:", error);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
可読性が高いのが好きで、fetchではなくaxiosを使っています。try…catchはセットで使います!
でもエンジニアになるとコードを書くこと以上に読むことが多いと聞くので、fetchでもスラスラ読めるようにしとかないとですな!
一つ気になるのが、setPrograms(res.data.list.e1)のところ…listが入ることでアクセスしにくい、というかなんか気持ち悪い気がしています…が、一旦次へ進みます。
ところで、then…catchとtry…catchってどう違うの?って思ったことありませんか?
気になって調べたのがこちらでした。ご参考に。(詳しすぎるくらい詳しい解説ですごいです)
データ配列からmapで繰り返し取り出し、動的にブラウザに表示
return (
<div>
<h1>NHK 番組一覧</h1>
{loading ? <p>ロード中・・・</p> : <p>ロード完了</p>}
{programs.map((program, index) => (
<div className="programCardContainer" key={index}>
<p>{program.title}</p>
<p>{program.start_time}</p>
<p>{program.end_time}</p>
<p>{program.subtitle}</p>
<p>{program.content}</p>
<p>{program.act}</p>
</div>
))}
</div>
);
};
とりあえず今のパラメータで取得できるデータ配列から、mapで順番に取り出し、ブラウザにpタグで表示させました。
この辺ではデータがない場合のオプション処理的なのも必要なのかな〜と何となく思いながら、そこはTypeScriptを頑張るフェーズで考える予定です!
最後に
ここまでご覧くださり、ありがとうございました!
まだまだ学習中で間違っているところや、解釈が甘いところもあるかと思いますが、ご容赦ください。
最後に言いたいことは一つ!
自分で調べながらコード書くの楽しいぃぃぃぃいいい!
コメント