AWS Lambdaを使って、Yahooニュース!が更新されたらSlackに通知させる

はじめに


初めまして、SITCのTです。
昨今、新型コロナウイルスの影響でニュースを良く見るようになった私ですが、
新しいニュースの配信をSlackに通知してくれたら便利だなと思い、
SITCで学んだ知識と技術を活かして、RSSリーダーを作成してみたので紹介します。

※RSSリーダーはSlackのツールに既に存在してますので、あくまで自己満足です。

目次


・構成図
・作成手順
・結果
・まとめ

構成図


構成図を以下に示します。

出典:https://aws.amazon.com/jp/blogs/news/building-serverless-pipelines-with-amazon-cloudwatch-events/
出典:https://news.yahoo.co.jp/
出典:https://slack.com/intl/ja-jp/

作成手順


SlackにIncoming Webhookを登録

AWS LambdaからSlackに通知がいくようにする為に、Incoming Webhookというアプリを追加します。

Slack Incoming Webhook 追加

Slackに追加したら設定画面にてチャンネルを選択して、インテグレーションの追加ボタンを押します。
今回は新しく「yahooニュース」というチャンネルを作成しました。

Slack Incoming Webhook チャンネル作成

チャンネルを作成したらWebhook URLが作成されます。
これは後程使うのでメモしておきます。

Slack Incoming Webhook URL

RSSの取得

RSSの取得を行います。今回は Yahoo!ニュース 主要 のRSSを使います。
リンクを右クリックして、リンクのアドレスをコピーボタンを押します。

Yahoo News RSS

プログラム作成の準備

外部ライブラリを使用する場合はzipファイルに圧縮してアップロードする必要があるので、ソースコードやライブラリを含めたzipファイルの作成をします。

参考:AWS LambdaをPythonで使ってみた ライブラリの読み込みや環境変数の注意点について解説

作業用ディレクトリ作成


mkdir yahoodir
cd yahoodir

ライブラリインストール


pip install feedparser -t ./


pip install pytz -t ./

ファイルの作成


touch lambda_function.py

ソースコード

1時間毎にスケジュール実行を行う前提でソースコードを作成しました。

・RSS_URL = 取得したいRSSのURLを記載。今回はyahooニュースの「主要」RSSです。
・SLACK_CHANNEL = 通知先のチャンネルを記載。今回はIncoming Webhook登録時に作ったチャンネル「#yahooニュース」です
・SLACK_NAME = 通知するアプリ名を記載。
・SLACK_URL = 先ほどメモしておいたWebhook URLを記載。

参考:Python, feedparserでRSS, Atomフィードを解析/
参考:datetime — 基本的な日付型および時間型
参考:AWS Lambdaで作るSlack bot

import json
import datetime
import urllib.request
import feedparser
import pytz

RSS_URL = "https://news.yahoo.co.jp/pickup/rss.xml"
SLACK_CHANNEL = "#yahooニュース"
SLACK_NAME = "YahooNews_RSS"
SLACK_URL = "https://hooks.slack.com/services/XXXXXXXXX"

def post_slack(main_data):
    send_data = {
        "channel": SLACK_CHANNEL,
        "name": SLACK_NAME,
        "text": main_data
    }
    send_text = json.dumps(send_data)
    request = urllib.request.Request(
        SLACK_URL,
        data=send_text.encode("utf-8"),
        method="POST"
        )
    with urllib.request.urlopen(request) as response:
        response_body = response.read().decode('utf-8')

def lambda_handler(event, context):
        yahoo_news = feedparser.parse(RSS_URL)
        news_list = []

        for entry in yahoo_news.entries:
            jst = pytz.timezone('Asia/Tokyo')
            now_utc = datetime.datetime.now(tz=jst)
            entry_time = datetime.datetime.strptime(entry.updated, '%a, %d %b %Y %H:%M:%S %z')
            last_update = now_utc - datetime.timedelta(hours=1)

            if last_update <= entry_time < now_utc:
                entrys = entry.title + 'n' + entry.link
                news_list.append(entrys)
        if len(news_list) > 0:
            print('post slack')
            post_slack('n'.join(news_list))

zipファイルに圧縮

プログラムが完成したのでzipファイルに圧縮します。


zip -r upload.zip *

AWS Lambda 設定

zipファイル作成後、AWS Lambda関数の作成を行います。
まずは、AWS マネジメントコンソールでAWS Lmbdaを開きます。
開いたら関数の作成ボタンを押します。

AWS Lambda 関数 作成

情報入力画面に遷移するので、情報を入力します。
今回は関数名に「YahooNews_RSS」、ランタイムに「Python 3.8」を入力して関数の作成ボタンを押します。

AWS Lambda 関数 作成

以下のような画面に遷移するので、「コードエントリタイプ」を.zipファイルをアップデートに設定して、zipファイルをアップロードします。

AWS Lambda 関数 作成

アップロードが出来たら、画面上部の保存ボタンを押します。

AWS Lambda 関数 作成

保存が正常に完了したら、プログラムが正しく動作するかテストします。保存ボタンの左にあるテストボタンを押します。
イベント名を適当に設定して作成を押します。今回はイベント名に「test」を設定しました。

AWS Lambda 関数 作成

テスト作成が完了したら、再度テストボタンを押します。
実行結果:成功となったらテスト成功です。
1時間以内にYahooニュースが更新されていれば、この時点でSlackに通知が飛びます。

AWS Lambda テスト 結果

CloudWatch Events 設定

AWS Lambdaの設定は完了したので、次は関数をスケジュール実行実行するためのトリガーを追加します。
AWS Lambda画面にあるトリガーを追加ボタンを押します。

Cloud Watch Events トリガー 追加

トリガー追加画面に遷移するので、「CloudWatch Events」を選択します。
新規ルールの作成を選択し各項目を設定します。
今回はルール名に、「YahooNews_RSS_Trigger」、ルールタイプを「スケジュール式」で「rate(1 hour)」に設定しました。
設定出来たら追加ボタンを押します。

Cloud Watch Events トリガー 設定

追加出来たら全て完了です。
後は待っていれば通知が来るはずです。

結果


1時間待ってみましたら無事に通知が来ました!

Slack 通知 結果

まとめ


読んでいただきありがとうございます。
いかがだったでしょうか。
私としては、無事にプログラムが完成して安心していますし、
SITCで学んだものをこういった機会で紹介することができて良かったです。
今後はSITCを卒業して現場で業務を行うことになるので、
そこで学んだ技術をいつかまた紹介出来たらいいなと思います。

投稿者: エムシバ君

エムフィールドのイメージキャラクター えむしば君です。 気になったり、興味が湧いた記事があったら、なんでもコメントしてみてね。 コーポレートサイトの問い合わせ欄からでも大丈夫だよ。