この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、ジョン・ヒョンジェです。
皆さんは新型コロナウイルスの発生状況を検索してみたりしませんか?私は毎朝、地域別にどのぐらい感染者が発生したか検索しますが、毎回検索するのはちょっと面倒だなと思いました。それで、感染者の発生状況を自動にSlackに告げてくれるアプリを作ってみました!!今回はその話をしていきたいと思います。
はじめに
構築するアーキテクチャです。作業の流れは以下のようになります。
- Incoming Webhooksアプリを作成する
- 新型コロナウイルス発生状況のデータを提供するOpen APIを用意する
- AWS Lambda作成(データの取得と加工、Incoming Webhooksにデータ送信)
- CloudWatch Events(time-based)でLambdaの実行を自動化させる
では、早速始めましょう!!
作ってみよう
Incoming Webhooksアプリを作成
Incoming Webhooksアプリは以下のリンクに接続してとても簡単に作成し、Slackのチャンネルに追加することができます。
アプリを追加するときに出るWebhook URLはアプリにデータを送信するとき使いますので、どこかへ記録しておいてください。
私は「COVID-19感染状況を告げるオールマイト」という名前のアプリを作成しました。(最近ハマっているキャラクターです)
Open APIを用意
私は韓国の政府が運営している公共データポータルサイトで新型コロナウイルス発生状況のOpen APIを使いました。Open APIの活用申請をすると、認証キーが提供され、使える各種のパラメーターの説明が見れます。
AWS Lambda作成
では、Incoming WebhooksとOpen APIが用意されましたので、以下のようにAWS Lambda関数を作成します。(Pythonで作成しました。)
import boto3
import json
import requests
import xmltodict
import urllib.parse
import datetime
def alert(event, context):
# 時間設定
today_time = datetime.date.today()
yesterday_time = today_time - datetime.timedelta(days = 1)
## parse_data関数を呼び出す
result_today_datas = parse_data(today_time.strftime("%Y%m%d"))
result_yesterday_datas = parse_data(yesterday_time.strftime("%Y%m%d"))
# S3にファイルをアップロード。(省略してもOK。ただのデータバックアップのため)
s3 = boto3.resource('s3')
bucket_name = "corona-log"
file_name = "%s.json" % (today_time.strftime("%Y%m%d"))
obj_name = s3.Object(bucket_name, file_name)
obj_name.put(Body=json.dumps(result_today_datas))
message_text = "" #Incoming Webhooksに送信するテキスト
for i in range(0, len(result_today_datas)): #データの加工
region = result_today_datas[i]["region"]
today_confirmed = result_today_datas[i]["confirmed"]
inc_confirmed = int(result_today_datas[i]["confirmed"]) - int(result_yesterday_datas[i]["confirmed"])
add_message = "*%s : %s名* (前日と比べ%s" % (region, today_confirmed, abs(inc_confirmed)) + ("名増加)" if inc_confirmed >=0 else "名減少)")
if region == "Total":
line = "========================================="
message_text = (line + "\n").join([message_text, add_message])
else:
message_text = "\n".join([message_text, add_message])
# Incoming Webhooksの設定
url = "<Incoming WebhooksのURL>"
payload = {
"attachments": [{
"pretext" : "私が韓国の新型コロナウイルス感染者発生状況を告げに来た!! (%s)" % str(today_time),
"color" : "#0099A6",
"text" : message_text
}]
}
headers = {
"Content-Type" : "application/json; charset=UTF-8"
}
# Incoming Webhooksにデータ送信
response = requests.post(url, data=json.dumps(payload), headers = headers)
return response
def parse_Data(time):
# Open APIのリクエストURL作成
api_url = "http://openapi.data.go.kr/openapi/service/rest/Covid19/getCovid19SidoInfStateJson"
queryParams = {
"ServiceKey" : "<Open APIの認証キー>",
"startCreateDt" : time,
"endCreateDt" : time
}
query_string = urllib.parse.urlencode(queryParams)
url = api_url + "?" + query_string
# 分析しやすくするため、JSON形式に変換
raw_data_result = requests.get(url).text
dict_data = xmltodict.parse(raw_data_result)
json_datas = json.loads(json.dumps(dict_data))
result_datas = []
for json_data in json_datas["response"]["body"]["items"]["item"]:
data = {}
data["region"] = json_data["gubunEn"] #地域
data["confirmed"] = json_data["incDec"] #感染者数
result_datas.append(data)
return result_datas
parse_Data
関数ではOpen APIからデータを取得して、alert
関数ではそのデータを加工し、Incoming Webhooksに送信します。(S3にファイルをアップロードしていますが、省略しても構いません)
実際にIncoming Webhooksにデータを送信する部分は以下のコードになります。
# Incoming Webhooksの設定
url = "<Incoming WebhooksのURL>"
payload = {
"attachments": [{
"pretext" : "私が韓国の新型コロナウイルス感染者発生状況を告げに来た!! (%s)" % str(today_time),
"color" : "#0099A6",
"text" : message_text
}]
}
headers = {
"Content-Type" : "application/json; charset=UTF-8"
}
# Incoming Webhooksにデータ送信
response = requests.post(url, data=json.dumps(payload), headers = headers)
Incoming Webhooksアプリにデータを送信する方法は二つがあります。
- POSTリクエストでJSONデータを
payload
パラメーターとして送信 - JSONデータをPOSTリクエストのbodyとして送信する
今回はpayloadパラメーターとして送信します。
payloadにtextプロパティだけ使ってデータを送信することもできますが、attachmentsプロパティを使うともっと多くの設定ができます。設定できるプロパティは以下のリンクを参考してください。
CloudWatch Events設定
韓国時間で毎日12時にLambdaを実行させるために、CloudWatch Eventsトリガを追加します。
cron
表現はUTC時間帯を使いますので、韓国時間から9時間差し引いて設定します。
確認
毎日12時Slackに新型コロナウイルスの発生状況を告げてくれるアプリが完成しました!
感想
補足ですが、payloadパラメーターにtextプロパティを使いましたが、fieldsプロパティを使って
fields = [{"title" : xxx, "desc" : xxx}, {"title" : xxx, "desc" : xxx}]
payload = {
"attachments" : [{
"fields" : fields
}]
}
このようにメッセージをJSONに設定することもできます。
では、今回の記事は以上です。Incoming Webhooksを使うととても簡単にアプリが作れますので試してみてください!