遅ればせながら新年明けましておめでとうございます。筆者の怠慢で休載が多くなっているこの連載ですが、
さて、筆者は
改めて確認したところ、
最近はNHKラジオもインターネット配信に力を入れているようで、放送した番組の多くが
見落していた番組をこの
「聴き逃し」サービスのプレイヤー
「聴き逃し」
何か手がかりは無いかとプレイヤーのHTMLのコードをあれこれ眺めていると、再生用のJavaScriptっぽい名前の"player_
見るだけで
そのために用いられる"JavaScript Obfuscator
Pythonのようなインデントに意味がある言語とは異なり、JavaScriptでは空白
jsbeatutifierはPythonで書かれたスクリプトで、PythonのパッケージデータベースPypiにも登録されているので、"pip"コマンドでインストールすることができます。
$ sudo pip install jsbeautifier [sudo] kojima のパスワード: xxxxxx Collecting jsbeautifier Downloading jsbeautifier-1.14.7.tar.gz (74 kB) |████████████████████████████████| 74 kB 137 kB/s Installing build dependencies ... done ... Successfully installed editorconfig-0.12.3 jsbeautifier-1.14.7
今回はpipを"sudo"経由で実行したので、ダウンロードしたパッケージはシステム領域にインストールされ、"/usr/
"js-beautifier"は整形したいファイルを引数に指定するだけではなく、標準入力から取りこんだファイルも処理できるので、"wget"で上記JavaScriptファイルを取り込み、"js-beatutifier"で整形してから保存してみます。
$ wget -O- 'https://www.nhk.or.jp/radio/js/player_ondemand.js?v202207' | js-beautify > player_ondemand.js $ cat -n player_ondemand.js 1 /////////らじる★らじる 聴き逃しプレーヤー///////// 2 var hostserver, ieVer, jsonpath = "nhk.or.jp/radioondemand/json/", 3 newspath = "nhk.or.jp/s-media/news/news-site/list/v1/all.json", 4 tophref = window == window.parent ? location.href : window.top.location.href, 5 nowDate = new Date, 6 $q = []; 7 $(function() { 8 if ($("#header h1 a").on("click", function() { 9 openerLink("/radio/") 10 }), setBodyClass(), getQuery("p")); 11 else { 12 $("#ODindex a").on("click", function() { 13 openerLink("/radio/ondemand/") 14 }), $("#bangumi").remove(), $("#ODindex a").html("<span>\u8074\u304D\u9003\u3057\u756A\u7D44\u4E00\u89A7\u3078</span>"); 15 return 16 } 17 $("#ODindex").slideUp("fast"), ("radionews" == ($q = getQuery("p").split("_"))[0] || "F261" == $q[0] || "F139" == $q[0]) && $("body").addClass("radionews"), "F139" == $q[0] ? (hostserver = "dev", jsonpath = "//dev-www." + jsonpath, newspath = "//dev-www." + newspath) : tophref.indexOf("//dev-") > -1 ? (hostserver = "dev", jsonpath = "//dev-www." + jsonpath, newspath = "//www." + newspath) : tophref.indexOf("//stg-") > -1 ? (hostserver = "stg", jsonpath = "//www." + jsonpath, newspath = "//www." + newspath) : tophref.indexOf("//www") > -1 ? (hostserver = "www", jsonpath = "//www." + jsonpath, newspath = "//www." + newspath) : tophref.indexOf("//nhk") > -1 && (hostserver = "ssf", jsonpath = "https://www." + jsonpath, newspath = "https://www." + newspath), $.getJSON($("body.radionews").length ? newspath : jsonpath + $q[0] + "/bangumi_" + $q[0] + "_" + $q[1] + ".json", function(a) { 18 callback(a.main) 19 }) ...
改行やインデントが無かった元のコードに比べてずいぶん見やすくはなったものの、JavaScriptの癖というか文法の特徴で、条件演算子
JavaScriptプレイヤーの解読
JavaScriptはきちんと勉強したことが無いので、Cなどの基本知識で読み解けるあたりから調べていったところ、どうやらこの"player_
さてそれではこの"player_
少し調べたところ、JavaScriptの場合、
if (condition1) { return value1; }
else if (condition2) { return value2; }
else if (condition3) { return value3; }
else { return value4; }
このように書くコードを、
return condition1 ? value1
: condition2 ? value2
: condition3 ? value3
: value4;
のように書けるそうです。また、
$("#ODindex").slideUp("fast"),
("radionews" == ($q = getQuery("p").split("_"))[0] || "F261" == $q[0] || "F139" == $q[0]) && $("body").addClass("radionews"),
"F139" == $q[0] ?
(hostserver = "dev", jsonpath = "//dev-www." + jsonpath, newspath = "//dev-www." + newspath)
: tophref.indexOf("//dev-") > -1 ?
(hostserver = "dev", jsonpath = "//dev-www." + jsonpath, newspath = "//www." + newspath)
: tophref.indexOf("//stg-") > -1 ?
(hostserver = "stg", jsonpath = "//www." + jsonpath, newspath = "//www." + newspath)
: tophref.indexOf("//www") > -1 ?
(hostserver = "www", jsonpath = "//www." + jsonpath, newspath = "//www." + newspath)
: tophref.indexOf("//nhk") > -1 &&
(hostserver = "ssf", jsonpath = "https://www." + jsonpath, newspath = "https://www." + newspath), $.getJSON($("body.radionews").length ?
newspath
: jsonpath + $q[0] + "/bangumi_" + $q[0] + "_" + $q[1] + ".json", function(a) {callback(a.main)}
)
うーん…… これでもロジックがよくわからないので、使っている変数の設定も追加してPython風に書き直してみましょう。
jsonpath = "nhk.or.jp/radioondemand/json/"
newspath = "nhk.or.jp/s-media/news/news-site/list/v1/all.json"
if window == window.parent :
tophref = location.href
else :
topref = window.top.location.href
$q = []
$q = getQuery("p").split("_")
if ( "radionews" == $q[0] || "F261" == $q[0] || "F139" == $q[0] ) :
$("body").addClass("radionews")
if ("F139" == $q[0]) :
hostserver = "dev"
jsonpath = "//dev-www." + jsonpath
newspath = "//dev-www." + newspath
elif (tophref.indexOf("//dev-") > -1) :
hostserver = "dev"
jsonpath = "//dev-www." + jsonpath
newspath = "//www." + newspath)
elif (tophref.indexOf("//stg-") > -1) :
hostserver = "stg"
jsonpath = "//www." + jsonpath
newspath = "//www." + newspath)
elif (tophref.indexOf("//www") > -1) :
hostserver = "www"
jsonpath = "//www." + jsonpath
newspath = "//www." + newspath)
elif (tophref.indexOf("//nhk") > -1 :
hostserver = "ssf"
jsonpath = "https://www." + jsonpath
newspath = "https://www." + newspath
if $.getJSON($("body.radionews").length ) :
newspath
else:
jsonpath + $q[0] + "/bangumi_" + $q[0] + "_" + $q[1] + ".json"
function(a) {callback(a.main)}
ロジックをきちんと理解できたわけではないものの、どうやらgetQuery()で"p=..."みたいなクエリを受けとり、それを"_"で分割し、最初の部分
さて、それではどこかに"p=..."を投げるところはあるのかな、と
どうやらこれっぽい、と予想して、$q[0]=0442、$q[1]=01を当てはめた"www.
$ curl https://www.nhk.or.jp/radioondemand/json/0442/bangumi_0442_01.json {"main":{"site_id":"0442","program_name":"音の風景","mode":0,"media_type":"radio", "media_code":"05,06,07","media_name":"NHKラジオ第1、NHKラジオ第2、NHK-FM", "site_detail":"5分のサウンドトリップへようこそ!\r\nリスナーのみなさんを音だけの世界にお連れします。\r\n 想像をかきたて、記憶を呼び覚まし、心を潤す音の数々。\r\n音響デザイナーがお届けする、5分間の音の旅をお楽しみ下さい。", "thumbnail_p":"https://www.nhk.or.jp/radioondemand/json/0442/img/g442.jpg", "thumbnail_c":null, "schedule":"【ラジオ第1】土11:50~日19:55~【ラジオ第2】月~金14:20~土12:10~ ....
この番組情報JSONデータには"filename:"としてストリーミングデータのURLも記載されており、VLC等でそのURLを開くとその番組の音声データが再生されました。もう少し関連するコードを解読したい気もするものの、とりあえず番組へのリンクから必要なJSONデータを入手できるようになったので、次はこれを使って録音するためのスクリプトを考えてみましょう。
今回紹介したNHKの聴き逃しサービスは、従来
というのも、JASRACの著作権使用料表によると、音声番組のダウンロード使用は
JASRAC管理楽曲も流す娯楽番組ではそのような縛りも妥当かな、と思う一方、