turtlechanのブログ

無知の私がLinuxをいじりながら書いていくブログ

【Python】ラジコの番組を検索するスクリプト

ラジコの番組を検索するPythonスクリプト

はじめに

ラズパイでラジコをタイムフリーで聞きたいときに、放送日時なんて覚えてないよってなっていた。キーワード検索して日時を取得すればよくね?と思い今回スクリプトを書いた。もともと需要がないせいかgoogle先生に聞いても思ったものは見当たらなかった。

確かにシェルスクリプトで済むことをわざわざPythonでやる必要もないですよね。

下調べ

ブラウザでラジコにアクセスして動作を確認します。

適当に検索してみた

  • キーワード: 井口裕香
  • 日付: すべて
  • 地域: 東京
  • 状態: タイムフリー

以下の画像の状態で検索。

radikoで検索している画像

結果は以下。

radikoで検索した結果画像

検索結果は1件ですね。

動作

ブラウザのデベロッパーツールを眺めて必要そうなところだけピックアップしました。

URL

基本URLは次のものでGETメソッドで取得している。

http://radiko.jp/v3/api/program/search

?以降はクエリ。付加されていたのは以下。

  • action_id: 0
  • app_id: pc
  • area_id: JP13
  • cul_area_id: JP13
  • end_day:
  • filter: past
  • key: 井口裕香
  • page_idx: 0
  • region_id:
  • row_limit: 12
  • start_day:
  • uid: e3948e8de187bab420a2fb4487f35675

レスポンス

嬉しいことに返ってくるのはjson形式のテキスト。

レスポンスの形式
{
    "meta": {
        "searched_url": "",
        "area_id": [
            ""
        ], 
        "region_id": "",
        "page_idx": ,
        "row_limit": ,
        "start_day": "",
        "cur_area_id": ,
        "station_id": [],
        "kakuchou": [],
        "filter": "",
        "end_day": "",
        "key": [
            ""
        ], 
        "suisengo": "", 
        "result_count": 
    }, 
    "data": [
        {
            "status": "",
            "info": "",
            "start_time_s": "",
            "ts_in_ng": ,
            "description": "",
            "img": "",
            "end_time_s": "",
            "start_time": "",
            "title": "",
            "station_id": "",
            "performer": "",
            "metas": [
                {
                    "name": "",
                    "value": ""
                }, 
                {
                    "name": "",
                    "value": ""
                }, 
                {
                    "name": "",
                    "value": ""
                }
            ], 
            "end_time": "",
            "program_date": "",
            "ts_out_ng": ,
            "program_url": ""
        }
    ]
}

Pythonで書いてみる

処理のながれは以下。

  1. クエリを準備
  2. 'http://radiko.jp/v3/api/program/search'にクエリをつけてGET

クエリを準備

先程も書いたがクエリは以下のものがあった。すべて必要なのか確認していないが、確認が面倒なため全部用意します。

  • action_id: 0
  • app_id: pc
  • area_id: JP13
  • cul_area_id: JP13
  • end_day:
  • filter: past
  • key: 井口裕香
  • page_idx: 0
  • region_id:
  • row_limit: 12
  • start_day:
  • uid: e3948e8de187bab420a2fb4487f35675

'action_id','app_id',region_id','row_limit'は特に手を加える必要はなさそう。'page_idx'は、検索結果が複数ページになる場合に使用されるんだろうが、今回は0で固定。'area_id','cul_area_id'は、その名の通り地域の指定。'start_day','end_day'は、使用するつもりはないので今回はそのままにする。'filter'は、状態。放送済みを検索の場合'past'、まだ放送されていない場合'future'だった。'key'は検索ワードですね。

問題なのは'uid'。
'uid'は、cookieで用意されている'rdk_uid'の値が使われているようだ。common.jsに以下のコードが書かれていた。

common.jsの一部
generateUid: function () {
    var _exp = $.cookie("rdk_uid");
    if (_exp == null || _exp == "") {
        var rnd = Math.floor(Math.random() * 1000000000) + "" + (new Date()).getTime();
        _exp = MD5_hexhash(rnd);
        $.cookie('rdk_uid', _exp, {path: '/'});

pythonで再現すると以下の感じだと思う(関数にしておく)。

pythonで書くと
import datetime, random, hashlib

def generate_uid():
    '''
    rdk_uid生成関数
    '''
    rnd = random.random() * 1000000000
    ms = datetime.timedelta.total_seconds(datetime.datetime.now() - datetime.datetime(1970, 1, 1)) * 1000
    return hashlib.md5(str(rnd + ms)).hexdigest()

'key'と'filter','area_id','cul_area_id'は引数で受け取るとする。

とりあえず

形だけですが、こんな感じでクエリを用意する。

params = {
    'key': 検索ワード,
    'filter': 'future'か'past',
    'start_day': '',
    'end_day': '',
    'area_id': エリアID,
    'region_id': '',
    'cul_area_id': エリアID,
    'page_idx': '0',
    'uid': generate_uid(),
    'row_limit': '12',
    'app_id': 'pc',
    'action_id': '0',
}

'http://radiko.jp/v3/api/program/search'にクエリをつけてGET

あとは'requests'ライブラリを使用すれば簡単ですね。クエリの付加はライブラリに任せる。

import requests

response = requests.get('http://radiko.jp/v3/api/program/search', params=辞書型で用意したクエリ)

'response.content'でjson形式のテキストなのであとは煮るなり焼くなり。

まとめ

上記のものをまとめると大体こんな感じになった。

まとめ.py
#! /usr/bin/env python
# coding: utf-8
# ライブラリのインポート import datetime import random import hashlib import requests import json import codecs def search(keyword='', t='past', area_id='JP13'): ''' 番組検索関数 ''' # クエリの準備 params = { 'key': keyword, 'filter': t, 'start_day': '', 'end_day': '', 'area_id': area_id, 'region_id': '', 'cul_area_id': area_id, 'page_idx': '0', 'uid': generate_uid(), 'row_limit': '12', 'app_id': 'pc', 'action_id': '0', } # GET response = requests.get('http://radiko.jp/v3/api/program/search', params=params) # ファイルに出力して確認する # output(response.content) # json形式のテキストを整形して返す return json.loads(response.content) def generate_uid(): ''' rdk_uid生成関数 ''' rnd = random.random() * 1000000000 ms = datetime.timedelta.total_seconds(datetime.datetime.now() - datetime.datetime(1970, 1, 1)) * 1000 return hashlib.md5(str(rnd + ms)).hexdigest() def output(out): ''' ファイルに出力する関数 jsonの確認用 ''' out = json.loads(out) print out with codecs.open('./result01.json', 'w', 'utf-8') as f: json.dump(out, f, ensure_ascii=False, indent=4)

おわりに

長々書いたけど、何かの参考になれば幸いです。