以前、NHKが行っているインターネットラジオ「らじる★らじる」を録音するためのスクリプトを紹介した ことがあります。
かって「エア・チェック」が趣味だった人間としては、ノイズや混信の無いきれいな音でFMの音楽番組を聞けたり、MP3プレイヤーにコピーして暇な時間に語学番組を聞けるのはとても便利です。しかも、かってのようにテープ代や録り溜めたテープの整理場所を気にする必要もありませんし、聞きたい番組が重なっても問題ないのもうれしいところです。
そんなわけで、いい気になってあれもこれもと録音しているうちに、録音したデータがずいぶん増えてきて、今度はそれらをどう整理したものかと悩むようになりました。
かって「エア・チェック」が全盛だったころは、放送で提供される楽曲の一覧を紹介したFM専門誌が存在し、その放送予定リストを見ながらどの番組を録音するかを決めたものです。このリストは、番組選択の目安となるだけではなく、録音した番組の曲目リストとして利用することもできました。たとえば、手元に残っている当時のカセットテープには、番組表から切り抜いた曲目リストがインデックス代わりに入っています。
図1 カセットテープと曲目リストの例
こうしておけば、どのテープにどういう曲が入っているかがわかるので、聞きたい曲を簡単に選ぶことができます。一方、このような仕組みをインターネットラジオを録音したファイル で実現しようとすると結構面倒です。
ファイルの場合、外から見てすぐにわかるのはファイル名 です。そのため収録曲名をファイル名にいれることを考えてはみたものの、ファイル名は最長255文字程度 なので入力可能な曲数は限られますし、あまりにファイル名を長くすると、移動やコピーの際に不便です。仕方ないので最初の曲や主要な曲のみをファイル名に加えてみたりもしましたが、見た目もイマイチだし、ファイル名の曲以外に何が入っているかは聞いてみないとわかりません。
$ ls MP3/NHK/クラシック
...
「シンフォニア 変ホ長調 Wq。183 第2」-2012-01-31-14-00.mp3
「組曲“ヴィクトリアン・キッチン・ガーデン”-2012-01-31-07-20.mp3
アンダルシア幻想曲-2012-02-07-14-00.mp3
イタリア風序曲-2012-02-01-14-00.mp3
ウィリアムテル、ウィンナワルツ、ビゼー、チャイコフスキー.mp3
...
もう少し使いやすくするために、どこかに曲目リストを記録できないかな、と調べてみることにしました。
NHKの番組情報API
「らじる★らじる」のプレイヤーでは、現在放送中の番組情報を表示しています。
図2 「 らじる★らじる」の画面
この番組情報はどこから取ってくるのだろう、とGoogleで調べてみたら「らじる★らじる」のプレイヤーを解析した人がいて、config_pc.xml という設定ファイルを使っていることがわかりました。
この設定ファイルを眺めてみると、放送中の番組情報を入手するためのURL がありました。
<!-- ただいま放送中の番組を取得するAPIのURL -->
<url_program_noa>
http://www2.nhk.or.jp/hensei/api/noa.cgi?c=3&wide=1&mode=jsonp
</url_program_noa>
wgetを使ってこのURLにアクセスしてみると、確かに番組情報らしきデータが得られます。
$ wget 'http://www2.nhk.or.jp/hensei/api/noa.cgi?c=3&wide=1&mode=jsonp' -O sample.dat
$ cat sample.dat
nowonair({"title":"NHK\u30cd\u30c3\u30c8\u30e9\u30b8\u30aa\u305f\u3060\u3044\u307e
\u914d\u4fe1\u4e2d","language":"ja","pubDate":"Thu, 27 Mar 2014 00:14:59 +0900",
"curtime":"2014-03-27 00:14:59","netr10":{"ch":"netr1","index":0,"starttime":
"2014-03-27 00:10:00","endtime":"2014-03-27 01:00:00","title":"\u30e9\u30b8\u30aa\u6df1
\u591c\u4fbf \u5bae\u5ddd\u6cf0\u592b","subtitle":"\u25bd\u30ef\u30fc\u30eb\u30c9\u30cd
...
得られたデータはテキスト形式ではあるものの、そのままでは読めそうにありません。そこで、このデータを処理する方法を調べてみました。
番組情報データの解読
実のところ、前節のデータは、wgetでダウンロードする際にmode=jsonp と指定しているので、JSON と呼ばれる形式になっています。
JSON(JavaScript Object Notation)は、JavaScriptのオブジェクト情報を記述するために提案されたデータ記述用言語 で、JavaScriptの書式に準じて、キーと値のペアを{ }で括ったような形になっています。JSONは、元々はJavaScript用に考案されたものの、データをテキスト形式で簡単にやりとりできるので、現在ではJavaScript以外でもデータ交換用に広く利用されています。
最近よく使っているPythonにもJSON用のモジュール が用意されています。そこで、このJSONデータをPythonを使って解読してみることにしました。
$ python
Python 2.7.3 (default, May 24 2012, 17:48:47)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import json
>>> f=open('sample.dat','r')
>>> l=f.readline()
>>> data=json.loads(l)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.7/json/__init__.py", line 326, in loads
return _default_decoder.decode(s)
File "/usr/lib64/python2.7/json/decoder.py", line 366, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib64/python2.7/json/decoder.py", line 384, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
>>>
おっと「JSONオブジェクトが見つからない」というエラーになってしまいました。モジュールの使い方をまちがったのかな、と調べてみたところ、本来のJSON形式のデータは'{'で始まり、'}'で閉じる必要があるのに、url_progrom_noaからダウンロードしたデータには、先頭に'nowonair('という余計なタグが付いています。そこで、この部分と対応する最後の');'を取り除いてみます。
>>> data = json.loads(l.lstrip('nowonair(').rstrip(');'))
>>> print data
{u'language': u'ja', u'pubDate': u'Thu, 27 Mar 2014 09:18:44 +0900', u'title': u'NHK\u30cd\u30c3
...
こんどは正しく読み込めたようです。Pythonの場合、JSONモジュールで読み込んだデータは、キーと値がペアになった辞書型のデータ として展開されるので、まずどのようなキーがあるのかを調べてみました。
>>> print data.keys()
[u'001netr2B1', u'language', u'pubDate', u'title', u'001netfmF1', u'001netr20', u'001netr1B1', u'001netfm0', u'curtime', u'001netr1F1', u'001netfmB1', u'001netr10', u'001netr2F1']
>>> print data['language']
ja
>>> print data['title']
NHKネットラジオただいま配信中
>>> print data['001netfm0']
{u'index': 0, u'ch': u'netfm', u'subtitle': u'\u300c\u30b9\u30a6\u30a7\u30c3\u30c8\u300d (\u30c8\u30cb\u30fb\u30d6\u30e9\u30af\u30b9\u30c8\u30f3&\u30d9\u30a4\u30d3\u30fc\u30d5\u30a7\u30a
....
この結果を見ると、どうやら001netfm0 や001netr1F1 の中に番組情報が収納されているようです。これらもそれぞれが辞書型のデータとして入れ子状になっているので、もう一段階掘り下げてみます。
>>> print data['001netfm0'].keys()
[u'index', u'ch', u'subtitle', u'title', u'url_goods', u'hashtag', u'free', u'content', u'station', u'music', u'starttime', u'act', u'link', u'rebroad', u'endtime']
>>> print data['001netfm0']['title']
ザ・ソウルミュージック▽Blast From The Past 第2夜
>>> print data['001netfm0']['content']
「スウェット」 (トニ・ブラクストン&ベイビーフェイス) (4分25秒) <MOTOWNUICT-1071> 「イッツ・イン・ユー」 (ロウ・ソウル・エクスプレス) (3分26秒) <WARNERWPCR-27718> 「リッスン・トゥ・ミー」 (ベイビー・ヒューイ) (6分36秒) <WARNERWPCR-27720> 「カム・オン・アンド・ステイ・ウィズ・ミー」 (サウンズ・オブ・ザ・シティ
>>> print data['001netr20']['title']
カルチャーラジオ 芸術その魅力「楽器別・中南米音楽入門」(12)-終-
なるほど、だいたいの見当は付きました。でも、001netfm0 以外の001netfmF1 や001netfmB1 は何でしょう? その答えは 'starttime'にありました。
>>> print data['001netfm0']['starttime']
2014-03-27 10:00:00
>>> print data['001netfmB1']['starttime']
2014-03-27 09:20:00
>>> print data['001netfmF1']['starttime']
2014-03-27 11:00:00
>>> print data['001netfmF1']['title']
弾き語りフォーユー
どうやら、B1が1つ前の番組 、F1が次の番組 を示しているようです。これは他のチャンネルでも成立するのでしょうか?
>>> print data['001netr10']['title']
第86回選抜高校野球大会 第6日
>>> print data['001netr1F1']['title']
天気予報・交通情報
>>> print data['001netr1F1']['starttime']
2014-03-27 11:50:00
どうやらルールとして、どのチャンネルでも末尾の'0'が現在の番組、'B1'が1つ前、'F1'が次の番組を意味しているようです。
番組情報が変わるように、しばらく間を置いて何度かデータを入手して眺めてみたところ、url_program_noaから得られる番組情報データは以下のような構造になっているようです。
title 「NHKネットラジオただいま配信中」という文字列(多分固定)
language ja(日本語以外があるかは不明)
pubData このデータをダウンロードした時刻
curtime 現在時刻(多分pubDataと同じ)
001netfm0 NHK FMの現在の番組情報
001netfmB1 NHK FMの1つ前の番組情報
001netfmF1 NHK FMの次の番組情報
001netr10 NHKラジオ第一の現在の番組情報
001netr1B1 NHKラジオ第一の1つ前の番組情報
001netr1F1 NHKラジオ第一の次の番組情報
001netr20 NHKラジオ第二の現在の番組情報
001netr2B1 NHKラジオ第二の1つ前の番組情報
001netr2F1 NHKラジオ第二の次の番組情報
そして、それぞれの番組情報には以下のような内容のデータが含まれています。
index 0(現在の番組) 、-1(1つ前) 、1(次)
ch netfm(FM), netr1(ラジオ第一) 、netr2(ラジオ第二)
title 番組名
subtitle 番組内容の要約
hashtag Twitterに投稿する際のハッシュタグ
station 放送局の識別子。東京(001) 、仙台(600) 、名古屋(300) 、大阪(200)
starttime 番組の開始時刻。"2014-03-27 10:00:00"という形式
endtime 番組の終了時刻。形式はstarttimeと同じ
act 出演者
content 短めの番組内容紹介
link 各番組のホームページへのリンク
rebroad 1だと再放送(番組表に「再」という記号が付く)
url_goods 関連商品等へのリンク?
music BGM等の曲名?
free 曲目、演奏者、演奏時間、レコード番号等の詳細情報
これらのうちurl_goodsとmusicは使っている例が見つからなかったので推測です。また、subtitleとcontent、freeは同じデータを使っていて、freeが番組内容の全文、contentはその先頭300字程度、subtitleはさらにその前半100字程度という関係になっているようです。
このように、NHKが提供しているNow On AirのAPIからは、ずいぶん充実した番組情報を入手できるようです。この機能を使えば録音した番組の曲目リストを自動的に作ることも可能でしょうし、ファイル名や曲目リストをデータベース化すれば、聞きたい曲を探すのにも便利でしょう。そう考えて以前作った「らじる★らじる」の録音スクリプトに曲目リスト登録機能を実装してみることにしました。