🐍
[python,AWS]RSSをサーバーレスに自動取得してDiscordに送ってみる
はじめに
- 生まれながらにサーバーレスなRSSリーダーを自作したい欲求があったので、自作しました
- 以下を試しました
- Lambdaでスクレイピング、Discordにwebhookで投稿
- VSCode Remote Containerで開発
- EventbridgeによるLambdaの定期実行
- Lambdaをコンテナで動かす
- Systems ManagerパラメータストアとLambdaの連携
成果物
- 登録しておいたサイトのRSSが1時間おきに自動取得され、リンクとタイトルがDiscordに投稿されます
構成図
- LambdaがRSS情報を取得し、webhookを利用してDiscordに通知します
- LambdaはEventbridgeにより1時間おきに自動実行されます
- RSS取得先URLはSystems Managerパラメータストアに保存します
- URLの追加変更はデプロイを介さず可能です
- Lambdaはコンテナイメージを利用して動きます、言語はpythonです
- デプロイはGithub Actionsを利用して自動化しています
実装
- リポジトリ全体はこちら
RSSリーダー本体(Lambda)
- RSSの取得&解析はfeedparserというライブラリを利用して行います(参考)
- 最小構成は以下です、get_rssにRSSのURLを渡すと記事情報が得られます
import feedparser
import time
from dataclasses import dataclass
from typing import List
@dataclass
class RssContent():
title: str
url: str
def get_rss(endpoint: str) -> List[RssContent]:
feed = feedparser.parse(endpoint)
rss_list: List[RssContent] = []
for entry in feed.entries:
if not entry.get("link"):
continue
rss_content = RssContent(
title=entry.title,
url=entry.link
)
rss_list.append(rss_content)
return rss_list
- Lambdaはコンテナイメージで動かします
デプロイ(Github Actions)
- 参考
- 上記記事を参考に以下を行うことでデプロイの自動化が可能です
- ECRの作成
- IAMユーザーの作成
- Github Actionsのyamlファイル作成、.github/workflows/main.ymlに配置
- GitHubのSecretsにIAMログイン情報等を記載
- AWS_ECR_REPO_NAMEにはリポジトリ名を記載することに注意。URIではありません
(1敗)
- AWS_ECR_REPO_NAMEにはリポジトリ名を記載することに注意。URIではありません
webhookURL・RSS取得先URLの管理(Systems Manager)
- URL類はSystems Managerパラメータストアに保存します
- RSS取得先URLについては改行区切りで単一パラメータに保存してしまっています
- RSS取得先URLについては改行区切りで単一パラメータに保存してしまっています
- LambdaからSystems Managerを参照し、パラメータを改行で分割することでRSS取得先URLをLambdaに与えます
from typing import List
import boto3
ssm = boto3.client('ssm')
def get_target_url() -> List[str]:
"""
取得対象にするrssのURLを返却する
"""
url_param: str = ssm.get_parameter(
Name='RSSURLList'
)['Parameter']['Value']
# url_paramには改行区切りでURLが保存されているので、改行で分割して出力
url_list: List[str] = url_param.split("\n")
return url_list
-
DiscordのwebhookURLについても同様にSystems Managerに保存しています
- DiscordのwebhookURL自体の発行についてはこちら
-
ここまでで、Lambdaを手動実行すればRSSがDiscordに送られる状態が実現します
定期実行(Eventbridge)
-
EventbridgeをLambdaのトリガーに設定すると定期実行が可能です(参考)
-
今回は1時間おきに実行するので「rate(1 hour)」で設定しました
- rateは開始時間を設定できないようです。
試した限りではEventbridgeの設定完了直後〜数分後までに1回目が起動して、以降はrateの周期にしたがって動きます
- rateは開始時間を設定できないようです。
-
RSS情報が1時間おきにDiscordに送られれば完成です
改善点
- LambdaやECR、Eventbridgeは今回手動作成しましたが、SAMやterraform,serverless frameworkでデプロイした方が再利用性があって良さそうです
- pythonのDockerfileはalpineでない方がパフォーマンスが良いらしく、改善の余地があります(参考)
- AWS公式もalpineで紹介していたので今回は流用しましたが、次回はbuster系で試す予定です
- スクレイピング系の処理をLambdaで実行するのはコスパがあまりよくないそうです(参考)
- FargateのScheduled taskでも同様の挙動は実現できるはず
Discussion