Last active
January 29, 2026 08:33
-
-
Save uru2/d1c24cd510e06ef92f0e62201b3826b8 to your computer and use it in GitHub Desktop.
放送局と日時からradikoの番組に関する情報を取得するサンプル
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # 放送局と日時からradikoの番組に関する情報を取得するサンプル | |
| # | |
| # ライセンスはUnlicense(https://unlicense.org/)にしますので | |
| # 必要な箇所をかいつまんでの利用や別の処理系で実装するなりご自由に | |
| # | |
| # usage: radiko_program_info.sh {station_id} {[%Y%m%d]%H%M[%S]} | |
| # 日時は以下の指定が可能 | |
| # %H%M (時分のみ、日付は実行日で補完) | |
| # %H%M%S (時分秒のみ、日付は実行日で補完) | |
| # %Y%m%d%H%M (年月日時分) | |
| # %Y%m%d%H%M%S (年月日時分秒) | |
| set -eu | |
| to_unixtime() { | |
| utime=$(echo "$1" \ | |
| | awk '{ | |
| date_str = $1; | |
| if (match(date_str, /[^0-9]/)) { | |
| # Invalid character | |
| print -1; | |
| exit; | |
| } | |
| if (length(date_str) != 12 && length(date_str) != 14) { | |
| # Invalid length | |
| print -1; | |
| exit; | |
| } | |
| # Split datetime parts | |
| year = substr(date_str, 1, 4) - 0; | |
| month = substr(date_str, 5, 2) - 0; | |
| day = substr(date_str, 7, 2) - 0; | |
| hour = substr(date_str, 9, 2) - 0; | |
| minute = substr(date_str, 11, 2) - 0; | |
| second = (length(date_str) == 14) ? substr(date_str, 13, 2) - 0 : 0; | |
| # Validation parts | |
| if ((year < 1970) || (month < 1) || (month > 12) || (hour < 0) || (hour > 23) \ | |
| || (minute < 0) || (minute > 59) || (second < 0) || (second > 59)) { | |
| print -1; | |
| exit; | |
| } | |
| split("31 0 31 30 31 30 31 31 30 31 30 31", days_of_month); | |
| days_of_month[2] = (year % 4 != 0) ? 28 : (year % 100 != 0) ? 29 : (year % 400 != 0) ? 28 : 29; | |
| if (day > days_of_month[month]) { | |
| print -1; | |
| exit; | |
| } | |
| # To UNIX time | |
| if (month < 3) { | |
| month+= 12; | |
| year--; | |
| } | |
| tz_offset = 32400; # JST(UTC+9) | |
| utime = (365 * year + int(year / 4) - int(year / 100) + int(year / 400) + int(306 * (month + 1) / 10) - 428 + day - 719163) \ | |
| * 86400 + (hour * 3600) + (minute * 60) + second - tz_offset; | |
| print utime; | |
| exit; | |
| }') | |
| if [ "${utime}" = '-1' ]; then | |
| return 1 | |
| fi | |
| echo "${utime}" | |
| return 0 | |
| } | |
| to_datetime() { | |
| datetime=$(echo "$1" \ | |
| | awk '{ | |
| ut = $0 + 32400; # JST(UTC+9) | |
| # hour, minute, second | |
| tm = ut; | |
| second = tm % 60; | |
| tm = int(tm / 60); | |
| minute = tm % 60; | |
| tm = int(tm / 60); | |
| hour = int(tm % 24); | |
| # year, month, day | |
| year = 1970; | |
| left_days = int(ut / 86400) + 1; | |
| while (left_days > 0) { | |
| is_leap = (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0)); | |
| year_days = (is_leap == 0) ? 365 : 366; | |
| if (left_days > year_days) { | |
| year++; | |
| left_days -= year_days; | |
| continue; | |
| } | |
| split("31 28 31 30 31 30 31 31 30 31 30 31", days_of_month); | |
| days_of_month[2] = (is_leap == 0) ? 28 : 29; | |
| month = 1; | |
| day = 0; | |
| for (i = 1; i <= 12; i++) { | |
| if (days_of_month[i] >= left_days) { | |
| day = left_days; | |
| left_days = 0; | |
| break; | |
| } | |
| left_days -= days_of_month[i]; | |
| month++; | |
| } | |
| } | |
| printf("%04d%02d%02d%02d%02d%02d", year, month, day, hour, minute, second); | |
| }') | |
| echo "${datetime}" | |
| return 0 | |
| } | |
| station_id=$1 | |
| program_datetime= | |
| # 番組開始日時 | |
| if [ "${#2}" = "14" ]; then | |
| # 年月日時分秒 | |
| program_datetime=$2 | |
| elif [ "${#2}" = "12" ]; then | |
| # 年月日時分 | |
| program_datetime="${2}00" | |
| elif [ "${#2}" = "6" ]; then | |
| # 時分秒 | |
| program_datetime="$(date +%Y%m%d)${2}" | |
| elif [ "${#2}" = "4" ]; then | |
| # 時分 | |
| program_datetime="$(date +%Y%m%d)${2}00" | |
| fi | |
| # 番組表の日付 | |
| # 00:00-04:59は前日扱いなので5時間分(=18000秒)引いて日付部だけ得る | |
| program_date=$(to_datetime "$(($(to_unixtime "${program_datetime}") - 18000))" | cut -c 1-8) | |
| # 放送局情報一覧の取得 | |
| stations_res=$(curl -s https://radiko.jp/v3/station/region/full.xml) | |
| # 放送局エリアID (番組情報一覧取得で使います) | |
| area_id=$(echo "${stations_res}" \ | |
| | xmllint --xpath "/region/stations/station[id='${station_id}']/area_id/text()" -) | |
| # 放送日および放送局がある都道府県の番組情報一覧の取得 | |
| programs_res=$(curl -s "https://api.radiko.jp/program/v3/date/${program_date}/area/${area_id}.xml") | |
| # ここからが抽出処理、エラーが出ても無視します | |
| # 指定日時に一番近い番組情報を参照 | |
| # 放送局名 | |
| station_name=$(echo "${stations_res}" \ | |
| | xmllint --xpath "/region/stations/station[id='${station_id}']/name/text()" - 2> /dev/null) \ | |
| || true | |
| echo "放送局名: ${station_name}" | |
| # 放送局URL | |
| station_url=$(echo "${stations_res}" \ | |
| | xmllint --xpath "/region/stations/station[id='${station_id}']/href/text()" - 2> /dev/null) \ | |
| || true | |
| echo "放送局URL: ${station_url}" | |
| # 番組開始日時 (radiko番組表上での日時) | |
| program_from_datetime=$(echo "${programs_res}" \ | |
| | xmllint --xpath "string((/radiko/stations/station[@id='${station_id}']/progs/prog[@ft<='${program_datetime}'])[last()]/@ft)" - 2> /dev/null) \ | |
| || true | |
| echo "番組開始日時: ${program_from_datetime}" | |
| # 番組終了日時 (radiko番組表上での日時) | |
| program_to_datetime=$(echo "${programs_res}" \ | |
| | xmllint --xpath "string((/radiko/stations/station[@id='${station_id}']/progs/prog[@ft<='${program_datetime}'])[last()]/@to)" - 2> /dev/null) \ | |
| || true | |
| echo "番組終了日時: ${program_to_datetime}" | |
| # 番組放送秒数 (radiko番組表上での秒数) | |
| program_seconds=$(echo "${programs_res}" \ | |
| | xmllint --xpath "string((/radiko/stations/station[@id='${station_id}']/progs/prog[@ft<='${program_datetime}'])[last()]/@dur)" - 2> /dev/null) \ | |
| || true | |
| echo "番組放送秒数: ${program_seconds}" | |
| # 番組名 | |
| program_name=$(echo "${programs_res}" \ | |
| | xmllint --xpath "(/radiko/stations/station[@id='${station_id}']/progs/prog[@ft<='${program_datetime}'])[last()]/title/text()" - 2> /dev/null) \ | |
| || true | |
| echo "番組名: ${program_name}" | |
| # URL | |
| program_url=$(echo "${programs_res}" \ | |
| | xmllint --xpath "(/radiko/stations/station[@id='${station_id}']/progs/prog[@ft<='${program_datetime}'])[last()]/url/text()" - 2> /dev/null) \ | |
| || true | |
| echo "URL: ${program_url}" | |
| # 出演者 | |
| program_performer=$(echo "${programs_res}" \ | |
| | xmllint --xpath "(/radiko/stations/station[@id='${station_id}']/progs/prog[@ft<='${program_datetime}'])[last()]/pfm/text()" - 2> /dev/null) \ | |
| || true | |
| echo "出演者: ${program_performer}" | |
| # 概要 | |
| program_description=$(echo "${programs_res}" \ | |
| | xmllint --xpath "(/radiko/stations/station[@id='${station_id}']/progs/prog[@ft<='${program_datetime}'])[last()]/desc/text()" - 2> /dev/null) \ | |
| || true | |
| echo "概要: ${program_description}" | |
| # 情報 (HTMLタグあり) | |
| program_information=$(echo "${programs_res}" \ | |
| | xmllint --xpath "(/radiko/stations/station[@id='${station_id}']/progs/prog[@ft<='${program_datetime}'])[last()]/info/text()" - 2> /dev/null) \ | |
| || true | |
| echo "情報: ${program_information}" | |
| # 画像URL | |
| program_image_url=$(echo "${programs_res}" \ | |
| | xmllint --xpath "(/radiko/stations/station[@id='${station_id}']/progs/prog[@ft<='${program_datetime}'])[last()]/img/text()" - 2> /dev/null) \ | |
| || true | |
| echo "画像URL: ${program_image_url}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment