NHK番組表APIを使ってキーワード監視と通知

Rubyでプログラムする人のための内容ですが、僕が勝手に作って使っているプログラムを公開します。NHKの番組表AIPを使って、興味のあるキーワードを含む番組情報を抽出して通知するプログラムです。

NHKの番組表AIPというのは、NHKが提供しているサービスで、そこで決められているプロトコルでNHKのサービスサーバーと通信して番組表のデータを取得できるもです。登録さえすれば無料で利用できます(但しアクセス回数に制限があるようです)。

この監視通知プログラムは僕のGitHUBのアカウントのGistsという場所で公開しているものですが、まずは下に貼り付けておきます。(Gists上で逐次修正しているので、貼り付けたものもそれに応じて更新されます。コードそのものについて何かあればGistsの方へコメントください)
> smallmake/nhkkw.rb
説明は後半へ。

#! /usr/bin/env ruby
require "faraday"
require "json"
require "time"
require "csv"
require "mail"
require "active_support/all"
NHK_API_KEY = ENV['NHK_API_KEY']
# メール送信用アカウントと送信先
GMAIL_APP_USERNAME = ENV['GMAIL_APP_USERNAME']
GMAIL_APP_PASSWORD = ENV['GMAIL_APP_PASSWORD']
GMAIL_ADDRESS = ENV['GMAIL_ADDRESS']
# 居住地(属するNHK地方局地域)
REGION_CODE = "260" #京都
# 興味対象のジャンルとキーワード "0000": "ニュース/報道(定時・総合)","0205": "情報/ワイドショー(グルメ・料理)","0800": "ドキュメンタリー/教養(社会・時事)" など
GENRE_CODES = %w(00 02 08)
# 検索キーワード(英数字も全角にすること)
KEYWORDS = %w(UFO 超能力 超常現象 光琳 若冲 宗達 応挙 其一 探幽 琳派 狩野派 アールヌーボー アール・ヌーボー)
# その他
LOG_FILE = "nhkkw.log" # 既に取得済みの番組は2回目以降除外するためのログファイルのファイル名です
NHK_CHANNELS = {"g1": "NHK総合", "e1": "NHK教育", "s1": "BS1", "s3": "BSプレミアム"}
# 値があるかチェック
REQUIREMENTS = %w(NHK_API_KEY REGION_CODE KEYWORDS LOG_FILE)
no_values = []
REQUIREMENTS.each do | requirement |
eval("no_values << %(#{requirement}) if #{requirement}.blank?")
end
unless no_values.empty?
puts "以下の変数に値がありません。\n" + no_values.join("\n")
exit
end
if !File.exist?(LOG_FILE)
File.write(LOG_FILE, '')
end
logs = CSV.read(LOG_FILE) # <id>,<start time>
# 1週間分の日付の配列をつくる
target_dates = []
target_date = Time.new()
7.times do
target_dates << target_date.strftime("%Y-%m-%d")
target_date = Time.new(target_date.year, target_date.month, target_date.day + 1, 0, 0, 0)
end
# コネクションを準備
conn = Faraday::Connection.new(:url => 'https://api.nhk.or.jp') do |builder|
builder.use Faraday::Request::UrlEncoded # リクエストパラメータを URL エンコードする
#builder.use Faraday::Response::Logger # デバグ用:リクエストを標準出力に出力する
builder.use Faraday::Adapter::NetHttp # Net/HTTP をアダプターに使う
end
# 指定チャンネルの番組情報を取得してキーワードを検索
result_message = ""
target_dates.each do |target_date|
NHK_CHANNELS.each do |channel_id, channel_name|
response = conn.get("/v2/pg/list/#{REGION_CODE}/#{channel_id}/#{target_date}.json?key=#{NHK_API_KEY}")
body = JSON.parse(response.body)
program_list = body["list"]["#{channel_id}"]
program_list.each do |program|
# 情報をバッファに取っておく
program_id = program["id"]
start_time = Time.parse(program["start_time"]).strftime("%Y/%m/%d %H:%M") if program["start_time"] != ''
end_time = Time.parse(program["end_time"]).strftime("%H:%M") if program["end_time"] != ''
title = program["title"]
subtitle = program["subtitle"]
content = program["content"]
act = program["act"]
genres = program["genres"]
# このうちtitle + subtitle + content + actにキーワードがあるか検査
words = title + subtitle + content + act
hit_flag = false
hit_words = []
KEYWORDS.each do |keyword|
if words.match(keyword)
hit_flag = true
hit_words << keyword
end
end
# 設定ジャンルに含まれているか検査(最初の2桁で検査します)
if GENRE_CODES.present?
genres.map! {|genre| genre[0,2] }
hit_flag &= !(genres & GENRE_CODES).empty?
end
# 既に送信しているかチェック
logs.each do |log|
log_program_id, log_start_time = log
hit_flag = false if log_program_id == program_id # 既にあれば除外
end
if hit_flag
result_message << "#{start_time}-#{end_time}:#{channel_name}:#{title}【#{hit_words.join(',')}】\n"
result_message << "#{subtitle}\n" if !"#{subtitle}".empty?
result_message << "#{content}\n" if !"#{content}".empty?
result_message << "----------\n"
logs << [program_id, program["start_time"]] # ログに追加
end
end
end
end
# メール送信せず表示するだけなら
puts result_message
# メールで送信
if !result_message.empty? && (GMAIL_APP_USERNAME || GMAIL_APP_USERNAME || GMAIL_APP_PASSWORD)
puts "-------- mail send --------"
mail = Mail.new do
from "#{GMAIL_ADDRESS}"
to "#{GMAIL_ADDRESS}"
subject "NKH番組キーワード監視通知"
end
mail.text_part do
body result_message
content_type 'text/plain; charset=UTF-8'
end
mail.delivery_method :smtp, { address: 'smtp.gmail.com',
port: 587,
domain: "#{GMAIL_ADDRESS}".split('@').last,
user_name: "#{GMAIL_APP_USERNAME}",
password: "#{GMAIL_APP_PASSWORD}" }
mail.deliver!
end
# logのクリーンアップ(終わったものは削除)
yesterday_date = Time.new().yesterday
CSV.open(LOG_FILE, "wb") do |csv|
logs.each do |log|
log_program_id, log_start_time = log
if Time.parse(log_start_time) > yesterday_date
csv << log
end
end
end
view raw nhkkw.rb hosted with ❤ by GitHub

NHK番組表APIのユーザー登録


NHK番組表APIを使うには、専用サイトでユーザー登録してログインし、自分のプログラムをアプリケーションとして登録して、専用のAPIキーを取得しなければなりません。

NHK番組表APIサイト

NHK番組表APIのサイト

登録方法などは僕は下記のQiitaの記事を参考にさせていただきました。本当に助かります。

 NHK番組表API(5さい)- Qiita @kazuchika

ここにも書かれているように取得できるのは当日から1週間先までの番組情報です。




プログラムの説明(使い方)


gem は faraday, json, time, csv, mail, active_support を使いますので、それぞれインストールしておいてください。

以下、プログラムの中身に説明です。
基本的にはプログラムの冒頭部分の各変数の設定さえちゃんと書いてもらえば、使えるはずです。

NHK_API_KEY 

NHK番組表APIのサイトで、自分のアプリ用にAPIキー(Program List API)を生成して入手してください。APIキーは "doksoHhdwh8shPsd6dsJshdjsjhsmrhdw"(テキトー) みたいな感じの文字列です。
プログラムではNHK_API_KEY の設定に ENV を使っています。つまり環境変数から取得するようにしていますが、プログラムファイルにじかに書いても結構です。(通常、サーバーなどに設置する場合はセキュリティの観点から環境変数から読み込むようにします。)

GMAIL_APP_USERNAME, GMAIL_APP_PASSWORD, GMAIL_ADDRESS

通知をgmailに送れるようにしています。
後で説明しますが、僕の場合、このプログラムをサーバーに置いて crontab で毎朝1回起動するようにしています。キーワードに引っかかる番組があると自動でメール通知してくれるわけです。

メール通知が不要な場合、つまり、例えばその都度手元で起動して表示される抽出結果を見るだけでよいなら、これらの変数は設定不要です。設定しなければメール送信しません。(これらも環境変数を参照するようにしているので、この場合、これらの環境変数を設定しなければメールは送信されません。なおgmailを二段階認証にしている場合、Googleからアプリ用パスワードの取得が必要です。)

REGION_CODE

住んでいる地域を示すコードを指定しなければなりません。NHKは地域毎に番組表が違う場合があるので、これは重要です。
地域コードは下記URLのページの「area」欄を参照してください。


GENRE_CODES

これは番組のジャンル(バラエティ、情報番組、ドラマなど)を絞り込むためのパラメータなのですが、実はジャンルのコードがどのようになっているのかはNHKのAPIサイト自体には詳しい説明がなく、僕は下記のブログで簡潔に知ることができました。助かります。


分類が多いので、大分類を示す最初の2桁だけで絞り込むようにしています(ニュース/報道は1, スポーツは2 ですが、それぞれ 01, 02 と記述します)


KEYWORDS

自分の興味を示すキーワードを並べてください。番組情報に半角英数字は使っていないようなので「UFO」も全角で「UFO」でなければなりません。


LOG_FILE

これは特に変更していただく必要はないと思います。ただし、このような名前のファイルが同じディレクトリ(フォルダ)に作られることを知っておいてください。また、プログラムに書き込みの権限が必要となりますのでご注意ください。

このファイルは、取得済み(通知済み)の番組を記憶しておくために使っています。そうしないと、プログラムが動くたびに通知済みの番組をその番組が終わるまでは何度も通知してしまうからです。

この記録は、プログラムの最後で、当日の前の日以前のから消去していますので、容量が増え続けるということはありません。


NHK_CHANNELS

抽出するTVチャンネルのコードと表示用の名前を設定します。NHK番組表APIはテレビだけでなくワンセグやラジオ放送も取得できます。コードと名前の対応一覧はNHK番組表APIサイトの下記のURLに「service」欄を参照してください。Rubyのhashで記述してください。


プログラム上などで各自が設定すべきことは以上です。

上にも書きましたが、取得できるのは1週間先までの番組表データです。それより先のものは取得できません。
ですので、できれば毎日1回自動起動して、プログラムにあるようにメールで通知させるのがいいと思います。

僕の場合は、これを自分のサーバーに設置してcrontabを設定して、毎朝8時5分に起動させています。以下のような設定ですね。

まず、シェル起動できるように

% chmod 755 nhkkw.rb

して、crontabでRuby環境を読み込んで起動するシェルスクリプトを nhkkw.sh を用意して
--------
#!/bin/sh

cd /home/eijin
source ./.bash_profile
./nhkkw.rb > /dev/null 2>&1
--------
で、

% chmod 755 nhkkw.sh

して、そして

% ctontab -e



5 8 * * * /home/eijin/nhkkw.sh

ですね。

以上です。

なお、コードに関しての質問については基本はノーサポートといたしますのでご了承ください。

【重要】また、コードを実行したことによって万が一に も発生した事故や損害などについては免責とさせていただきます。全て自己責任でお願いいたします。










コメント

このブログの人気の投稿

「このコンピュータ上の rapportd にアクセスしようとしています」のメッセージ

WinSCPをタスクで自動起動 — SSH鍵とパスフレーズの問題(ただしWindows2000の話し)