背景
この記事の処理内容を、スクレイピングからAPIでの情報取得へ変更したことを紹介します。
👇
1.環境
- Python 3.9.x
- AWS Lambda
- Amazon EventBridge ...定期的に実行するため
- Amazon Simple Notification Service (SNS) ...終了通知をCloudWatchへ渡すため
- Amazon CloudWatch ...ロギング
- Amazon Simple Storage Service (S3) ...Lambda関数のアップロード先
- LINE公式アカウント
2.開発
2.1.Pythonコード
- スクレイピングの処理を、公共交通オープンデータセンター 開発者サイトから登録すると利用可能なAPIへ変更しました。
※ユーザー登録申請から承認までは、2営業日ほど。
- 主な利用ライブラリは以下の2つ。
- pytz
UTC(協定世界時)→JST(日本標準時)へ変換する際に利用
※Linuxの時間はUTCで管理されているため、通知前にJSTへ変換する必要あり
→APIで取得時間がJSTで返ってくるため、そちらを利用しても可。 - line-bot-sdk
- pytz
lambda_function.py
"""
lambda_function.py
"""
# postリクエストをline bot APIに送るためにrequestsのimport
import os
import time
from datetime import datetime, timezone
import pytz
import urllib.request, urllib.error
from linebot import LineBotApi
from linebot.models import TextSendMessage
import json
CONSUMER_KEY = os.getenv("CONSUMER_KEY")
# line messaging APIのトークン
LINE_ACCESS_TOKEN = os.getenv("LINE_ACCESS_TOKEN")
line_name_dict = {
"odpt.Railway:TokyoMetro.Ginza": "銀座線",
"odpt.Railway:TokyoMetro.Marunouchi": "丸ノ内線",
"odpt.Railway:TokyoMetro.Chiyoda": "千代田線",
"odpt.Railway:TokyoMetro.Tozai": "東西線",
"odpt.Railway:TokyoMetro.Yurakucho": "有楽町線",
"odpt.Railway:TokyoMetro.Fukutoshin": "副都心線",
"odpt.Railway:TokyoMetro.Hanzomon": "半蔵門線",
"odpt.Railway:TokyoMetro.Hibiya": "日比谷線",
"odpt.Railway:TokyoMetro.Namboku": "南北線",
}
def lambda_handler(event, context):
"""
lambda_handler
"""
print('event: {}'.format(event))
print('context: {}'.format(context))
URL = os.getenv("URL")
response_body = urllib.request.urlopen(url=URL).read()
data_dict = json.loads(response_body)
# 現在時刻
now = datetime.now(tz=timezone.utc)
tokyo = pytz.timezone('Asia/Tokyo')
# 東京のローカル時間に変換
jst_now = tokyo.normalize(now.astimezone(tokyo))
content0 = jst_now.strftime("%m月%d日 %H:%M現在")
info_list = []
for t in range(9):
line_name = data_dict[t]["odpt:railway"]
train_info_text = data_dict[t]["odpt:trainInformationText"]["ja"]
content = []
# 路線名
content1 = line_name_dict[line_name]
# 運行状況(詳細)
content3 = train_info_text
# lineに通知するメッセージを組み立て
content.append("●" + content1)
content.append(content3)
info_list.append(content)
content_text = []
for i in range(9):
content_text.append('\n'.join(info_list[i]))
notification_message = content0 +'\n' + '\n\n'.join(content_text)
line_bot_api = LineBotApi(LINE_ACCESS_TOKEN)
line_bot_api.broadcast(TextSendMessage(text=notification_message))
return {
'status_code': 200
}
if __name__ == "__main__":
print(lambda_handler(event=None, context=None))
requirememts.txt
pytz
line-bot-sdk
2.1.1.APIの呼び出し
- 該当箇所は以下の通りです。URLは環境変数として設定しています。
APIを使うことでコードも大変スッキリとしました。
import urllib.request, urllib.error
URL = os.getenv("URL")
response_body = urllib.request.urlopen(url=URL).read()
data_dict = json.loads(response_body)
2.1.2.LINEへの通知
- 事前にLINE公式アカンウントにて トークンと、API key の取得が必要です。
発行されたトークンとAPI keyは大切に保管してください。- 応答設定:Bot
- Webhook:On ...LINE Messaging APIを利用します
- ソースの該当箇所は以下の通りです。
こちらもコードはAPIの利用方法に倣うだけです。
from linebot import LineBotApi
from linebot.models import TextSendMessage
CONSUMER_KEY = os.getenv("CONSUMER_KEY")
# line messaging APIのトークン
LINE_ACCESS_TOKEN = os.getenv("LINE_ACCESS_TOKEN")
line_bot_api = LineBotApi(LINE_ACCESS_TOKEN)
line_bot_api.broadcast(TextSendMessage(text=notification_message))
3.Lambdaへアップロードするためのzipファイルを作成する
- zipファイルを作成するスクリプトは以下の通りです。
make_upload.sh
rm upload.zip
rm -r upload/
rm -r download/
mkdir -p download/bin
mkdir upload
cp -r download/bin upload/bin
cp app/lambda_function.py upload/
pip install -r app/requirements.txt -t upload/
cd upload/
zip -r ../upload.zip --exclude=__pycache__/* .
cd ../
rm -r upload/
rm -r download/
4.Lambda関数の環境変数を設定する
- Lambda関数の環境変数セクションを表示して、下記設定を行ないます。
キー | 値 | 備考 |
---|---|---|
CONSUMER_KEY | (64文字) | |
LINE_ACCESS_TOKEN | (173文字) | |
URL | https://api.odpt.org/api/v4/odpt:TrainInformation?odpt:operator=odpt.Operator:TokyoMetro&acl:consumerKey={CUSTOMERKEY} | 列車運行情報を取得します。customerKeyの設定が必須。 |
5.実行結果
(編集後記)
(お願い)APIを利用できる情報提供者からは、必ずAPIを使いましょう。
この記事ではいろいろと端折っている部分がありますので、細かい手順などは元の記事を参考にして頂ければ幸いです。
天気予報、株価の設定値到達アラート、服薬の飲み忘れ防止通知、等々に応用が利くことですので、みなさんのアイディアで様々に利用してみてください。
現在は定期実行していますが、LINE公式アカウントではLIFFアプリをつくることで、情報が欲しいタイミングでLINEの画面上からボタンひとつでAPIを呼び出すことも可能となります。こちらの機能もぜひ試してみてください。