LoginSignup
4
3

More than 1 year has passed since last update.

AWS Lambdaで列車運行情報をLINEへ通知【Python】

Posted at

背景

この記事の処理内容を、スクレイピングから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
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.実行結果

IMG_1791.PNG


(編集後記)

(お願い)APIを利用できる情報提供者からは、必ずAPIを使いましょう。

この記事ではいろいろと端折っている部分がありますので、細かい手順などは元の記事を参考にして頂ければ幸いです。

天気予報、株価の設定値到達アラート、服薬の飲み忘れ防止通知、等々に応用が利くことですので、みなさんのアイディアで様々に利用してみてください。
現在は定期実行していますが、LINE公式アカウントではLIFFアプリをつくることで、情報が欲しいタイミングでLINEの画面上からボタンひとつでAPIを呼び出すことも可能となります。こちらの機能もぜひ試してみてください。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3