インターンシップ学生の高倉です。ここでは、HTMLとJavaScriptで番組表を取得し、表示するための方法について順を追って解説しようと思います。今回は、NHK番組表APIを使用し、フォームから開始時間と終了時間のデータを受け取っているという前提で解説します。
NHK番組表APIを使うための準備
NHK番組表APIからデータを取得するためには、ユーザ登録する必要があります。
1.まず、NHK番組表APIのホームページ(https://api-portal.nhk.or.jp/)にアクセスし、右上の新規登録をクリックします。
2.必要な情報を入力し、アカウントを作成します。
3.入力したメールアドレスにメールが届くので、認証します。
4.番組表APIの新規アプリ登録ページで必要事項を記入しAPIキーの発行を申請します。
5.ホームページの「登録済みアプリはこちら」のボタンをクリックすると、登録したアプリの情報が表示されます。それをクリックすると、APIの取得に必要なキーが表示されます。
URLからデータを取得する方法
ほかのサイトでも、フォームを入力した後に
・・・.html?○○=××&△△=××
といった表記を見たことはあるでしょうか?今回はこの機能を使っていきます。
function getparam(name){ url=window.location.href; name = name.replace(/[\[\]]/g, "\\$&"); var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"); var results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); }
HTMLで表の素体を作る方法
Tableを用いて、表を作ります。見出しは表の最初の行で設定します。
プログラム
<table id="table" class="table table-striped"> <caption>Powered by NHK番組表API</caption> <tr> <!--表の見出し--> <th>放送局</th> <th>番組名</th> <th>放送開始時間</th> <th>放送終了時間</th> <th>ジャンル</th> </tr> <tr> <!--APIから取得したデータを埋め込む。 serviceは放送局 nameは番組のメインタイトル timeは放送開始時間 endは放送終了時間 genreはジャンルの番号に対応している。 --> <td> <div id="service"> </div> </td> <td> <div id="name"> </div> </td> <td> <div id="time"> </div> </td> <td> <div id="end"> </div> </td> <td> <div id="genre"> </div> </td> </tr> </table>最初のtr要素では、表の見出しを表示できるようにしています。実際の表では、上に書いた要素から左に並んでいきます。二つ目のtr要素では、情報を表示するための箇所を確保しています。serviceは放送局名
nameは番組名
timeは放送開始時間
endは放送終了時間
genreはジャンル名に対応しています。APIからデータを取得する方法
NHK番組表APIでは、YYYY-MM-DDの形式で月日を指定します。月や日が一桁の時は頭に0をつけないと正常に取得できないため、その場合は条件分岐で頭に0をつける処理をします。
JavaScriptでは1個しか変数を返すことができないので、リストの形で返します。プログラム
function makeURLpart(iyear,imonth,iday){ var year var month var day year=String(iyear) if(imonth<10){ month="0"+String(imonth) }else{ month=String(imonth) } if(iday<10){ day="0"+String(iday) }else{ day=String(iday) } return [year,month,day] }このプログラムでは、APIから情報を取得するためにURLの一部分を作成しています。URLは文字列で指定するため、ここで文字列に変換します。YYYY-MM-DD形式で日時を指定するため、月や日が一桁となる場合には、前に0をつけることで対応します。最後に作成したyear,month,dayを返します。URLに必要なパラメータを作成できたら、次にURLを取得します。プログラムfunction getURL(ch,year,month,day){ request=new XMLHttpRequest() var url="https://api.nhk.or.jp/v2/pg/list/130/"+ch+"/"+year+"-"+month+"-"+day+".json?key=キーを入力" request.open("GET",url,true) request.responseType="json" return request }第一引数のchでは、取得するチャンネルを指定しています。対応表は以下の通りです
引数 チャンネル名
g1 NHK総合 e1 NHKEテレ e4 NHKワンセグ s1 NHKBS s3 BSプレミアム ほかの引数のyear,month,dayは、取得したい日にちを入力します。
最後に、取得したデータを返します。
入力された時間が日をまたぐ場合の対応方法
日にちを進める関数を利用して、1日分進めた後、もう一度APIからデータを取得します。うるう年や30日31日の月の日数の違いも考慮します。
プログラムは以下の通りです。
function progressDay(y,m,d){ var mday={ 1:31, 2:28, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30, 10:31, 11:30, 12:31 } if(y%4==0){ mday[2]=29 }else{ mday[2]=28 } if(d==mday[m]){ if(m==12){ d=1 m=1 y+=1 }else{ m+=1 d=1 } }else{ d+=1 } return [y,m,d] }
表に適した情報を反映させる方法
最後に、取得したデータから放送局・番組名・番組開始時間・番組終了時間・ジャンルを取り出します。
プログラム
function writeTable(req,ch){ var data=req; console.log(data); var len //要求されたチャンネルに応じて取り出す要素を変更する。 if(ch=="g1"){ len=Object.keys(data.list.g1).length; }else if(ch=="e1"){ len=Object.keys(data.list.e1).length; }else if(ch=="e4"){ len=Object.keys(data.list.e4).length; }else if(ch=="s1"){ len=Object.keys(data.list.s1).length; }else if(ch=="s3"){ len=Object.keys(data.list.s3).length; }else{ console.log("無効なチャンネルが指定されています"); } console.log(ch) var service var name var time var end var genre for(let i=0;i<len;i+=1){ if(ch=="g1"){ service=data.list.g1[i].service.name; name=data.list.g1[i].title; time=data.list.g1[i].start_time; end=data.list.g1[i].end_time; genre=data.list.g1[i].genres[0]; }else if(ch=="e1"){ service=data.list.e1[i].service.name; name=data.list.e1[i].title; time=data.list.e1[i].start_time; end=data.list.e1[i].end_time; genre=data.list.e1[i].genres[0]; }else if(ch=="e4"){ service=data.list.e4[i].service.name; name=data.list.e4[i].title; time=data.list.e4[i].start_time; end=data.list.e4[i].end_time; genre=data.list.e4[i].genres[0]; }else if(ch=="s1"){ service=data.list.s1[i].service.name; name=data.list.s1[i].title; time=data.list.s1[i].start_time; end=data.list.s1[i].end_time; genre=data.list.s1[i].genres[0]; }else if(ch=="s3"){ service=data.list.s3[i].service.name; name=data.list.s3[i].title; time=data.list.s3[i].start_time; end=data.list.s3[i].end_time; genre=data.list.s3[i].genres[0]; } if(time>starttime && end<endtime){ console.log("時間の範囲内") console.log("放送局:"+service); console.log("番組名:"+name); console.log("開始時間:"+time); console.log("終了時間:"+end); console.log("ジャンル:"+genre); //表を拡張 var add=table.insertRow(-1); var cell1=add.insertCell(-1); var cell2=add.insertCell(-1); var cell3=add.insertCell(-1); var cell4=add.insertCell(-1); var cell5=add.insertCell(-1); //時間などの要素を取り出す time=String(time); end=String(end); genre=String(genre); timeymd=time.substr(0,10); timehms=time.substr(11,5); eymd=end.substr(0,10); ehmd=end.substr(11,5); //ジャンルを大ジャンルと小ジャンルに分ける var big_genre=genre.substr(0,2); var small_genre=genre.substr(2,); //大ジャンルと小ジャンルをもとに、表示を完成させる if(big_genre=="00"){ genre="ニュース/報道" if(small_genre=="00"){ genre+="(定時・総合)" }else if(small_genre=="01"){ genre+="(天気)" }else if(small_genre=="02"){ genre+="(特集・ドキュメント)" }else if(small_genre=="03"){ genre+="(政治・国会)" }else if(small_genre=="04"){ genre+="(経済・市況)" }else if(small_genre=="05"){ genre+="(海外・国際)" }else if(small_genre=="06"){ genre+="(解説)" }else if(small_genre=="07"){ genre+="(討論・会談)" }else if(small_genre=="08"){ genre+="(報道特番)" }else if(small_genre=="09"){ genre+="(ローカル・地域)" }else if(small_genre=="10"){ genre+="(交通)" }else{ genre+="(その他)" } ...ジャンルを記入していく }else{ genre="その他" } cell1.innerHTML=service cell2.innerHTML=name cell3.innerHTML=timeymd+"\n"+timehms; cell4.innerHTML=eymd+"\n"+ehmd; cell5.innerHTML=genre }else{ console.log("時間の範囲外") } } }取得した時間の範囲内に収まる(最初から最後まで見れる)番組だけを表示します。
今回使用したNHKの番組表APIはジャンルの上二桁は大ジャンル、下二桁は小ジャンルに分かれている
ため、ジャンルの数字を二桁ずつに分割して、大ジャンルと小ジャンルに分け、それに応じたジャンル名を表示するようにしています。プログラム全体の流れ
ここまではすべてFunction機能を使用してきました。最後に、Function同士をつなげて、実行できるようにします。ここでは、NHK総合の番組表を取得する場合を示しています。
プログラム
nymd=[iyear,imonth,iday] for(j=0;j<2;j+=1){ var uymd uymd=makeURLpart(nymd[0],nymd[1],nymd[2]) req=getURL("g1",uymd[0],uymd[1],uymd[2]) req.addEventListener("load",function(){ writeTable(this.response,"g1") }) req.send() nymd=progressDay(nymd[0],nymd[1],nymd[2]) }まず日にちを取得し、その日にちからURLを作ります。その後、URLを取得し、取得出来たら表に書くという流れになっています。最後にsendを挟むことで表に反映し、次の日にちに設定します。それを2回繰り返す流れです。二重にFor文を設定すると、addEventListenerの仕様で正常に動作しないため、実際には5つのチャンネルを別々に動作させています。