オープンデータをどういう風に活用したらいいのか?

前回の記事で折角自治体のオープンデータを取得してみましたので、今回はオープンデータをリアルタイムに取得し、ユーザーに教えることをしてみようと思い、またまたLINEBotを作成してみました⭐️
今回もさっと作成してみたかったので、一番慣れているRailsと、Herokuを使って、WebAPIを作成してみました。
実際は、Railsで無くても十分な気がしますが、ご了承ください。
実際に出来上がったもの
こちらです。
福岡県オープンデータの「福岡県 感染症発生動向調査週報」を利用させていただきました。
こちらでは、データをCSVとして公開するだけでなく、APIを使って、JSON形式でリアルタイムにデータを取得することが出来るようになっているので、次のような機能を盛り込んでみました。
- リアルタイムにオープンデータを取得
- 最新のオープンデータを取得し、インフルエンザの流行状況をお知らせ
- 最新と最新から1個前のデータを取得し、インフルエンザの流行状況の増減をお知らせ
※正確に言えば、「福岡県に報告があった、該当する1週間で、1医療機関に何名辺りのインフルエンザの患者さんが確認されたか」というデータのようです。
イメージ
ユーザーが「先週比」と送ると、 最新のデータと、最新から1個前のデータを取得し、人数の差分を返却します。
ユーザーが「最新」と送ると、 最新のデータから、人数を返却します。
参考にさせていただいたサイト
【Rails】1時間ぐらいで簡単にLINEのBot開発をしよう-アンケート集計Bot基礎-【画像付き】
こちらで、LINEのユーザーからメッセージを飛ばされた時の取得方法、メッセージを返却する方法を参考にさせていただきました。
コード部分
コントローラー
class LinebotController < ApplicationController
require 'line/bot'
require 'net/http'
protect_from_forgery :except => [:shuhou]
def client
@client ||= Line::Bot::Client.new { |config|
config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
}
end
#上のLINE_CHANNEL_SECRETなどの設定は参考サイトをみてください。環境変数を設定する必要があります。
#api部分のメソッド(ユーザーからのメッセージの内容により返却する値を変更)
def shuhou
body = request.body.read
events = client.parse_events_from(body)
signature = request.env['HTTP_X_LINE_SIGNATURE']
unless client.validate_signature(body, signature)
head :bad_request
end
events.each do |event|
message = event.message['text']
#ユーザーから「最新」と送られた場合
if message.include?("最新")
resources = get_recent_id()
recent_updated_id = resources[resources.length - 1]["id"]
records = get_shuhou(recent_updated_id)
res_str = ["1医療機関でインフルエンザの感染が確認された人数は\n\n"]
#recordsをeachで回し発生地点毎のインフルエンザ倍率を配列に格納
records.each do |record|
if record["自治体名"] == record["地点名"]
timei = record["自治体名"]
else
timei = record["自治体名"] + record["地点名"]
end
res_str << "#{timei}:#{record["(インフルエンザ)"]}人\n"
end
res_str << "\n\nです。\n(例)\n◯◯市:1人(〇〇市の1医療機関で、1週間辺りに1人のインフルエンザの患者が確認された。)"
return_str = res_str.join("")
#ユーザーから「先週比」と送られた場合
elsif message.include?("先週比")
resources = get_recent_id()
recent_updated_id = resources[resources.length - 1]["id"]
second_updated_id = resources[resources.length - 2]["id"]
recent_records = get_shuhou(recent_updated_id)
next_records = get_shuhou(second_updated_id)
res_str = ["1医療機関でインフルエンザの感染が確認された人数の先週比は\n\n"]
#最新の週報と1個前の週報で人数を比較
recent_records.each do |recent|
next_records.each do |second|
if (recent["自治体名"] + recent["地点名"] ) == (second["自治体名"] + second["地点名"] )
num = (recent["(インフルエンザ)"].to_f - second["(インフルエンザ)"].to_f).round(1)
num = "+" + num.to_s if num >= 0
if recent["自治体名"] == recent["地点名"]
timei = recent["自治体名"]
else
timei = recent["自治体名"] + recent["地点名"]
end
res_str.push("#{timei}:#{num}人\n")
end
end
end
res_str << "\n\nです。\n(例)\n◯◯市:+1人(〇〇市の1医療機関で、先週と比較して1週間辺り、インフルエンザの患者数が1人増えた。)"
return_str = res_str.join("")
#それ以外は使い方を送信する。
else
return_str = return_str3 = "使い方\n\n福岡県が公開している「福岡県 感染症発生動向調査週報」のデータを元に、\n「1週間における、1医療機関当たりのインフルエンザの感染が確認された人数」\nをお知らせします。\n「最新」と送信すれば、最新の人数を、「先週比」と送信すれば、前回の報告と比較した人数の増減をお知らせします。"
end
case event
when Line::Bot::Event::Message
case event.type
when Line::Bot::Event::MessageType::Text
message = {
type: 'text',
text: return_str
}
client.reply_message(event['replyToken'], message)
end
end
head :ok
end
#感染症週報のオープンデータの公開状況を取得する。resources["result"]["resources"][添字]["id"]で添字番目のオープンデータリソースidを取得
def get_recent_id
uri = URI.parse("https://ckan.open-governmentdata.org/api/3/action/package_show?id=43dd36e0-fc93-40af-8215-c17cbf964cae")
response = Net::HTTP.get_response(uri)
json = JSON.parse(response.body)
resources = json["result"]["resources"]
return resources
end
#指定したリソースidの感染症週報のデータを取得する。
def get_shuhou(resource_id)
uri = URI.parse("http://data.bodik.jp/api/action/datastore_search?resource_id=" + resource_id)
response = Net::HTTP.get_response(uri)
json = JSON.parse(response.body)
records = json["result"]["records"]
return records
end
end
router
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
post '/shuhou' => 'linebot#shuhou'
end
これだけです。
やってることは超単純で
ユーザーからのメッセージを取得⇨メッセージの内容で、取ってくるオープンデータを変える⇨ 取ってきたオープンデータをちょっとだけ加工して、ユーザーに返す
としているだけです。
まとめ
- 自治体にもよるけど、オープンデータもWebAPIにより、データをリアルタイムで取得することが出来るようになっている
- データの取得は単なるHTTPのリクエストなので、Webの知識があって、少し触ればすぐにわかる
- LINEとのメッセージのやり方も先人の知恵があるので、簡単に出来る
- 実際このアプリは1日でできました
- ただし、Herokuの無料モードでやっているので、速度は・・・
というところです。
2019-11-10追記 視覚的に分かりやすいように、グラフ機能を追加しました。記事はこちら
