以前に記事にしたradiko.jpのタイムフリーを一括ダウンロードバッチのラジコプレミアムのログイン仕様が変更されたので対応版を作りました。
しかしまだ不明点があって後日修正するかもしれません。
今はこのブログでの活動時間があまりなく更新も時間差があります。
よく調査してないので不十分な点があります。
それでも良ければお付き合いください
利用にあたって
wget.exe
https://eternallybored.org/misc/wget/
ffmpeg.exe
https://ffmpeg.org/
新たにXMLの検証の為xmllintを使います
Windows版xmllintは、
このサイトの
https://www.zlatkovic.com/libxml.en.html
の
Win32 binaries (HTTP)
から、libxml2 バイナリをダウンロードしてください。
iconv-1.9.2.win32.zip
libxml2-2.7.8.win32.zip
zlib-1.2.5.win32.zip
をダウンロードして(将来ファイル名のバージョンは変わるかも)
iconv.dll
libxml2.dll
zlib1.dll
xmllint.exe
を置いてください
各種実行ファイルを集めて一つのフォルダに置いてください
ここでの例としてD:\RadikoRecに置いてます
以下のテキストソースも集めて一つのフォルダに置いてください
AYTHKeyGet.vbs
Option Explicit
Dim argStation,argDebug,argSilent,cookiefile,mail,pass,checkfile,loginfile
'radiko premium
mail = ""
pass = ""
argStation = "TBS" '引数1(i):radiko.jp内の放送局のid
argDebug = "no" '"yes"なら、動作の途中経過を逐次表示する
argSilent = "yes" '"yes"なら、外部コマンドであるwgetの実行プロンプトを表示しない
Dim i
Dim strCmd
Dim objFSO
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Dim aUnnamed
Set aUnnamed = WScript.Arguments.Unnamed
If aUnnamed.Count > 0 Then
For i = 0 To aUnnamed.Count - 1
Select Case i
Case 0
argStation = aUnnamed.Item(i)
End Select
Next
End If
'シェル起動オブジェクトを生成
Dim WSHShell,gShellStyle
Set WSHShell = WScript.CreateObject("WScript.Shell")
If argSilent = "yes" Then
gShellStyle = 7
Else
gShellStyle = 10
End IF
'ファイルシステム用オブジェクトを生成(ラジコ独自認証でファイルを利用)
Dim WSHFS
Set WSHFS = CreateObject("Scripting.FileSystemObject")
strCmd = GetRadikoCmd()
WScript.Quit(0)
'Radiko.jpの独自認証を行う
Function GetRadikoCmd()
Dim pSwfPlayer,pKeyFile,RtnCD,auth1_fms,auth2_fms
Dim pTmpName
pTmpName = WSHFS.GetTempName()
pSwfPlayer = "player_" & argStation & pTmpName & ".swf"
pKeyFile = "authkey_" & argStation & pTmpName & ".png"
auth1_fms = "auth1_fms_" & argStation & pTmpName
auth2_fms = "auth2_fms_" & argStation & pTmpName
loginfile = "login_" & argStation & pTmpName & ".txt"
cookiefile = "cookie_" & argStation & pTmpName & ".txt"
checkfile = "pre_check_" & argStation & pTmpName & ".txt"
'radiko premium
if not (mail = "") then
RtnCD = WSHShell.run("wget.exe -q --save-cookie=" & cookiefile _
& " --keep-session-cookies" _
& " --post-data=""mail=" & mail & "&pass=" & pass & """" _
& " -O " & loginfile _
& " https://radiko.jp/v4/api/member/login",gShellStyle,True)
If RtnCD <> 0 Then
GetRadikoCmd = "error 認証ステップ0:radiko premiumの取得失敗!"
premiumLogoutCmd()
Exit Function
Else
If argDebug = "yes" Then WScript.Echo "認証ステップ0"
End If
WScript.Sleep 2000
if not objFso.FileExists(cookiefile) then
WScript.Echo "failed login1"
premiumLogoutCmd()
Exit Function
End IF
End IF
Dim pFile
Dim pLine
Dim pLine1
Dim radiko_session,areafree
Dim aryStrings
Dim s
Set pFile = WSHFS.OpenTextFile(loginfile,1)
Do While pFile.AtEndOfStream = False
pLine1 = pFile.ReadLine
aryStrings = Split(pLine1, ",")
For Each s In aryStrings
pLine = s
pLine =Replace(pLine,"}","")
pLine =Replace(pLine,Chr(34),"")
If InStr(LCase(pLine),"radiko_session") <> 0 Then
radiko_session = mid(pLine,InStr(pLine,":")+1,len(pLine)-InStr(pLine,":"))
ElseIf InStr(LCase(pLine),"areafree") <> 0 Then
areafree = mid(pLine,InStr(pLine,":")+1)
End If
Next
Loop
pFile.Close
'認証ステップ1:Radikoのauth1をダウンロード
RtnCD = WSHShell.run("wget.exe -q --timeout=60 --tries=10" _
& " --header ""X-Radiko-App: pc_html5""" _
& " --header ""X-Radiko-App-Version: 0.0.1""" _
& " --header ""X-Radiko-Device: pc""" _
& " --header ""X-Radiko-User: dummy_user""" _
& " --save-headers " _
& " -O " & checkfile _
& " https://radiko.jp/v2/api/auth1",gShellStyle,True)
If RtnCD <> 0 Then
GetRadikoCmd = "error 認証ステップ1:auth1の取得失敗!"
premiumLogoutCmd()
Exit Function
Else
If argDebug = "yes" Then WScript.Echo "認証ステップ1"
End If
'認証ステップ2:RadikoのplayerCommon.jsをダウンロード
RtnCD = WSHShell.run("wget.exe -q --timeout=60 --tries=10" _
& " -O """ & auth1_fms & """" _
& " http://radiko.jp/apps/js/playerCommon.js",gShellStyle,True)
If RtnCD <> 0 Then
GetRadikoCmd = "error 認証ステップ2:playerCommon.jsの取得失敗!"
premiumLogoutCmd()
Exit Function
Else
If argDebug = "yes" Then WScript.Echo "認証ステップ2"
End If
'認証ステップ3:checkfileから、・X-Radiko-AuthToken・X-Radiko-KeyLength・X-Radiko-KeyOffset を読み取る
Dim pAuthtoken,pLength,pOffset
Set pFile = WSHFS.OpenTextFile(checkfile,1)
Do While pFile.AtEndOfStream = False
pLine = pFile.ReadLine
If InStr(LCase(pLine),"x-radiko-authtoken:") <> 0 Then
pAuthtoken = mid(pLine,InStr(pLine,":")+2,len(pLine)-InStr(pLine,":"))
ElseIf InStr(LCase(pLine),"x-radiko-keylength:") <> 0 Then
pLength = mid(pLine,InStr(pLine,":")+2,len(pLine)-InStr(pLine,":"))
ElseIf InStr(LCase(pLine),"x-radiko-keyoffset:") <> 0 Then
pOffset = mid(pLine,InStr(pLine,":")+2,len(pLine)-InStr(pLine,":"))
End If
Loop
pFile.Close
'認証ステップ4:playerCommon.jsから文字列取得
Dim radikojsplayer
Set pFile = WSHFS.OpenTextFile(auth1_fms,1)
Do While pFile.AtEndOfStream = False
pLine = pFile.ReadLine
If InStr(LCase(pLine),"new radikojsplayer") <> 0 Then
radikojsplayer = mid(pLine,65,40)
End If
Loop
pFile.Close
Dim fso
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Dim outputFile
Set outputFile = fso.OpenTextFile(pKeyFile, 2, True)
outputFile.WriteLine radikojsplayer
outputFile.Close
'認証ステップ5:playerCommon.jsの内容から、base64の値であるpartialkeyを求める
Dim pXmldom,pB64,pStream,partialkey
Set pXmldom = CreateObject("Microsoft.XMLDOM")
Set pB64 = pXmldom.CreateElement("work")
pB64.DataType = "bin.base64"
Set pStream = CreateObject("ADODB.Stream")
pStream.Type = 1
pStream.Open
pStream.LoadFromFile pKeyFile
pStream.position = pOffset
pB64.NodeTypedValue = pStream.Read(pLength)
partialkey = pB64.Text
pStream.Close
Set pStream = Nothing
'認証ステップ6:上記で求めたキーからauthtokenとpartialkeyをradikoに送り認証を成立させる
Dim auth2_url_param
auth2_url_param = "?radiko_session=" & radiko_session
RtnCD = WSHShell.run("wget.exe -q --timeout=60 --tries=10" _
& " --header ""X-Radiko-Device: pc""" _
& " --header=""X-Radiko-Authtoken: " & pAuthtoken & """" _
& " --header=""X-Radiko-Partialkey: " & partialkey & """" _
& " --header ""X-Radiko-User: dummy_user"""_
& " https://radiko.jp/v2/api/auth2" & auth2_url_param _
& " -O """ & auth2_fms & """" ,gShellStyle,True)
If RtnCD <> 0 Then
GetRadikoCmd = "error 認証ステップ6:authtokenとpartialkeyの失敗!"
premiumLogoutCmd()
Exit Function
Else
If argDebug = "yes" Then WScript.Echo "認証ステップ6"
End If
'テンポラリファイルを消す
If argDebug <> "yes" Then
WSHFS.DeleteFile pKeyFile, True
WSHFS.DeleteFile auth1_fms, True
WSHFS.DeleteFile auth2_fms, True
if not (mail = "") then
WSHFS.DeleteFile loginfile, True
WSHFS.DeleteFile checkfile, True
WSHFS.DeleteFile cookiefile, True
End If
End If
WScript.Echo(pAuthtoken)
End Function
Function premiumLogoutCmd()
Dim RtnCD
'radiko premium Logout
if not (mail = "") then
RtnCD = WSHShell.run("wget -q" _
& " --header=""pragma: no-cache""" _
& " --header=""Cache-Control: no-cache""" _
& " --header=""Expires: Thu, 01 Jan 1970 00:00:00 GMT""" _
& " --header=""Accept-Language: ja-jp""" _
& " --header=""Accept-Encoding: gzip, deflate""" _
& " --header=""Accept: application/json, text/javascript, */*; q=0.01""" _
& " --header=""X-Requested-With: XMLHttpRequest""" _
& " --no-check-certificate "_
& " --load-cookies cookiefile "_
& " --save-headers "_
& " -O logoutfile" _
& " https://radiko.jp/ap/member/webapi/member/logout",gShellStyle,True)
If RtnCD <> 0 Then
GetRadikoCmd = "error radiko premiumのLogout失敗!"
Exit Function
Else
If argDebug = "yes" Then WScript.Echo "radiko premiumのLogout取得成功"
End If
if objFso.FileExists(cookiefile) then
WSHFS.DeleteFile cookiefile, True
End IF
End IF
End Function
date.vbs
' CScript date.vbs w
' CScript date.vbs /d:-6
Option Explicit
dim argDay
Dim aNamed
Set aNamed = WScript.Arguments.Named
argDay = WScript.Arguments. Named.Item("d")
Dim strFormattedDate
Dim argC
Dim i
Dim strCmd
Dim objFSO
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Dim aUnnamed
Set aUnnamed = WScript.Arguments.Unnamed
argC = ""
If aUnnamed.Count > 0 Then
For i = 0 To aUnnamed.Count - 1
Select Case i
Case 0
argC = aUnnamed.Item(i)
End Select
Next
End If
if not (argDay = "") Then
dim strNow
strNow = Now()
strFormattedDate = DateAdd("d",argDay,strNow)
strFormattedDate = Left(strFormattedDate, 10)
strFormattedDate = Replace(strFormattedDate, "/", "")
WScript.Echo strFormattedDate
End If
if (argC = "w") Then
WScript.Quit(WeekDay(Date))
End If
日付計算のためのスプリクトです。
timeshift_get.bat
D:
cd \RadikoRec
set F=./rec/
REM TBS,QRR,LFR,RN1,RN2,INT,FMT,FMJ,JORF,BAYFM78,NACK5,YFM,HOUSOU-DAIGAKU
goto DAY
:MON
for /f %%i in ('CScript date.vbs /d:%dayC%') do SET D=%%i
call :get_ts BAYFM78 %D%130000 %D%160000 %F%%D%1300_it
exit /b
:TUE
for /f %%i in ('CScript date.vbs /d:%dayC%') do SET D=%%i
call :get_ts BAYFM78 %D%130000 %D%160000 %F%%D%1300_it
exit /b
:WED
for /f %%i in ('CScript date.vbs /d:%dayC%') do SET D=%%i
call :get_ts BAYFM78 %D%130000 %D%160000 %F%%D%1300_it
exit /b
:THU
for /f %%i in ('CScript date.vbs /d:%dayC%') do SET D=%%i
call :get_ts BAYFM78 %D%130000 %D%160000 %F%%D%1300_it
exit /b
:FRI
for /f %%i in ('CScript date.vbs /d:%dayC%') do SET D=%%i
call :get_ts BAYFM78 %D%130000 %D%160000 %F%%D%1300_KISS&SMILE
exit /b
:SAT
for /f %%i in ('CScript date.vbs /d:%dayC%') do SET D=%%i
call :get_ts TBS %D%010000 %D%030000 %F%%D%0100_JUNK_バナナマンのバナナムーンGOLD
exit /b
:SUN
for /f %%i in ('CScript date.vbs /d:%dayC%') do SET D=%%i
call :get_ts TBS %D%130000 %D%170000 %F%%D%1300_爆笑問題の日曜サンデー
exit /b
REM ここから処理部分
:DAY
cscript /b date.vbs w
if %errorlevel%==7 set WDAY=SAT
if %errorlevel%==6 set WDAY=FRI
if %errorlevel%==5 set WDAY=THU
if %errorlevel%==4 set WDAY=WED
if %errorlevel%==3 set WDAY=TUE
if %errorlevel%==2 set WDAY=MON
if %errorlevel%==1 set WDAY=SUN
if "%WDAY%" == "MON" (
set /a dayC=-6
call :TUE
set /a dayC=-5
call :WED
set /a dayC=-4
call :THU
set /a dayC=-3
call :FRI
set /a dayC=-2
call :SAT
set /a dayC=-1
call :SUN
set /a dayC=0
call :MON
goto end
)
if "%WDAY%" == "TUE" (
set /a dayC=-6
call :WED
set /a dayC=-5
call :THU
set /a dayC=-4
call :FRI
set /a dayC=-3
call :SAT
set /a dayC=-2
call :SUN
set /a dayC=-1
call :MON
set /a dayC=0
call :TUE
goto end
)
if "%WDAY%" == "WED" (
set /a dayC=-6
call :THU
set /a dayC=-5
call :FRI
set /a dayC=-4
call :SAT
set /a dayC=-3
call :SUN
set /a dayC=-2
call :MON
set /a dayC=-1
call :TUE
set /a dayC=0
call :WED
goto end
)
if "%WDAY%" == "THU" (
set /a dayC=-6
call :FRI
set /a dayC=-5
call :SAT
set /a dayC=-4
call :SUN
set /a dayC=-3
call :MON
set /a dayC=-2
call :TUE
set /a dayC=-1
call :WED
set /a dayC=0
call :THU
goto end
)
if "%WDAY%" == "FRI" (
set /a dayC=-6
call :SAT
set /a dayC=-5
call :SUN
set /a dayC=-4
call :MON
set /a dayC=-3
call :TUE
set /a dayC=-2
call :WED
set /a dayC=-1
call :THU
set /a dayC=0
call :FRI
goto end
)
if "%WDAY%" == "SAT" (
set /a dayC=-6
call :SUN
set /a dayC=-5
call :MON
set /a dayC=-4
call :TUE
set /a dayC=-3
call :WED
set /a dayC=-2
call :THU
set /a dayC=-1
call :FRI
set /a dayC=0
call :SAT
goto end
)
if "%WDAY%" == "SUN" (
set /a dayC=-6
call :MON
set /a dayC=-5
call :TUE
set /a dayC=-4
call :WED
set /a dayC=-3
call :THU
set /a dayC=-2
call :FRI
set /a dayC=-1
call :SAT
set /a dayC=0
call :SUN
goto end
)
echo date.vbs処理エラー
pause
:get_ts
set ch=%1
set ft=%2
set to=%3
set AYTHKeyGet=AYTHKeyGet.vbs
del timeshift.m3u8
for /f %%i in ('CScript %AYTHKeyGet% %ch%') do SET AUTHTOKEN=%%i
wget "https://radiko.jp/v3/station/stream/pc_html5/%ch%.xml"
for /f %%i in ('xmllint --xpath "/urls/url[@areafree=1][@timefree=1][1]/playlist_create_url/text()" %ch%.xml') do SET PLAYLIST_URL=%%i
DEL %ch%.xml
DEL %ch%.xml.?
ffmpeg -headers "X-Radiko-AuthToken: %AUTHTOKEN%" -i "%PLAYLIST_URL%?station_id=%ch%&start_at=%ft%&ft=%ft%&end_at=%to%&to=%to%&l=15&lsid=99999999999999999999999999999999&type=c" "%4.ts"
exit /b
:end
注意点
ffmpegの行の
lsid=99999999999999999999999999999999
は何のためのIDか不明です。9の文字はダミーです。
しかしこのIDを付加しないと400 Bad Requestになります。
将来の個人特定のIDかもしれませんが
今の所モニターしている限り固定値です
基本的にブラウザーのネットワークモニターで
m3u8ファイルを監視して
lsid=をコピペしたほうが無難です
xmllintでURLを抽出するターゲットとして
[@areafree=1][@timefree=1]
を指定してますエリアフリーなら1を
タイムフリーなら1を指定してください
XMLファイルからURLを抽出して
ダウンロードするように変更しましたが
このURLでダウンロードすると1倍速でダウンロードされて
時間がかかるようになりました
かなり不便になりました
不明な点が多いですがもし指摘点がございましたらコメントください
注意点終わり
毎日いつ実行してもいい状況を想定して書いてあります。
F=./rec/は録音ファイルのフォルダー名です。
MON(月)TUE(火)WED(水)THU(木)FRI(金)SAT(土)SUN(日)
なと曜日でダウンロードしたい日に番組を指定していきます。
get_ts 局名 開始時間 終了時間 録音ファイル名 です
EXITでバッチが終了します。
タイムフリーは一週間分しかダウンロードできません。
ラジコプレミアムに加入してればどの地域の人でも
ダウンロードできます。




1 Comment
い~ゆ~
2025年1月28日hanpen様
情報公開、ありがとうございます。
とても参考になりました。
私はラズベリーPIでここ20年くらい、仕様変更の度に少しづつ修正を加えながらシェルスクリプトでradikoを聞いていましたが、
先週の月曜日から急に再生できなくなり、1週間かけて仕様変更箇所の調査など行っておりました。
ここのページの情報が非常に役に立ちました。
お陰で今朝からまたjwaveで目覚めることができるようになりました。
しかし、実は今の仕様は2年前からされていて、私は旧仕様が切られるまで知らずに使い続けていたということだったというのは、このページで初めて分かりました(笑)。
非常にお世話になりました。
ありがとうございます。