RSSで取得した英語をAmazon Translateで日本語に翻訳してSlackに通知してみた
はじめに
どうも。英語苦手勢代表のnt1です。
みなさんは英語得意ですか。私は苦手です。
なのでRSSで取得した英語を日本語に翻訳するアプリケーションを作成することにしました。
本記事ではその作成方法・手順についてご紹介できればと思います。
構成概要
構成図については下記になります。
実装イメージとしてはLambda関数にてPython3.8を使用してWhat’s New with AWS?からRSSフィードを取得します。
feedparser
という外部ライブラリを使用してフィードのフォーマットの差異を吸収して扱いやすくしています。
試しにRSSフィードを取得してみると以下のような形式で出力されています。
{ "links": [ { "rel": "alternate", "type": "text/html", "href": "https://aws.amazon.com/about-aws/whats-new/2024/02/amazon-cloudfront-availability-embedded-pops/" } ], "link": "https://aws.amazon.com/about-aws/whats-new/2024/02/amazon-cloudfront-availability-embedded-pops/", "id": "5c68127f3511b9d7e5316e365e5195db62eaedde", "guidislink": false, "title": "Amazon CloudFront announces availability of Embedded Points of Presence", "title_detail": { "type": "text/plain", "language": null, "base": "https://aws.amazon.com/about-aws/whats-new/recent/feed/", "value": "Amazon CloudFront announces availability of Embedded Points of Presence" }, "summary": "<p>Amazon CloudFront embedded Points of Presence (POPs) are a new type of CloudFront infrastructure deployed closest to end viewers, within internet service provider (ISP) and mobile network operator (MNO) networks. Embedded POPs are custom built to deliver large scale live-stream video, video-on-demand (VOD), and game downloads. Today, CloudFront has 600+ embedded POPs deployed across 200+ cities globally.<br /> </p>", "summary_detail": { "type": "text/html", "language": null, "base": "https://aws.amazon.com/about-aws/whats-new/recent/feed/", "value": "<p>Amazon CloudFront embedded Points of Presence (POPs) are a new type of CloudFront infrastructure deployed closest to end viewers, within internet service provider (ISP) and mobile network operator (MNO) networks. Embedded POPs are custom built to deliver large scale live-stream video, video-on-demand (VOD), and game downloads. Today, CloudFront has 600+ embedded POPs deployed across 200+ cities globally.<br /> </p>" }, "published": "Mon, 26 Feb 2024 21:04:06 +0000", "published_parsed": { "tm_year": 2024, "tm_mon": 2, "tm_mday": 26, "tm_hour": 21, "tm_min": 4, "tm_sec": 6, "tm_wday": 0, "tm_yday": 57, "tm_isdst": 0 }, : : :
今回は概要が分かればよいのでこの中からtitle
とlink
とsummary
を取得します。
published
の時間と現在の時間を比較して1日前までに更新されたものだけ翻訳処理をかけるようにしています。
翻訳処理はtitle
とsummary
をAmazon Translateに渡して日本語訳にしてもらっています。
そのあとSlack APPを使用してSlackチャンネルに日本語に翻訳したタイトル(リンク)、概要を通知します。
イメージとしては以下のようなSlackメッセージが投稿されます。
後は日時で定期実行するEventBridgeを設定しており毎日特定の時間に通知されるように設定しています。
Amazon Translateについては、下記記事にてAmazon TranslateとAWS LambdaでAmazon S3にアップロードされたファイルの内容を翻訳するアプリケーションを作成する手順を解説していますので、興味がありましたらご確認ください。
作成手順
本手順では下記の流れで構築していきます。
- Slack APP作成
1.1 Slackチャンネル設定 - Lambdaレイヤー&関数作成
2.1 Lambda関数設定
2.2 Lambdaコード作成 - Lambda関数実行
- EventBridge作成
1. Slack APP作成
まず外部サービス連携でよく使われるIncoming Webhookは以下の説明文のとおり非推奨であり将来的に削除される可能性があるため、代替手段のSlack APPを使用しています。
Slack apiでAPPを作成して権限のあるSlackワークスペースにインストールすることが可能です。
本項ではSlack APPを作成してOAuth&権限設定を行いワークスペースにインストールする手順を解説していきます。
Slack apiより「Create New App」を選択します。
「From scratch」を選択します。
- App Nameは任意の値を選択(今回の場合はtranslate bot)
- Pick a workspace to develop your app inは任意のワークスペースを選択
左ペインの「OAuth & Permissions」を選択します。
Scopesという項目がありますので「Add an OAuth Scope」をクリックして下記権限を選択します。
- chat:write
- chat:write.customize
- chat:write.public ※APPが参加していないチャンネルに通知する場合
完了したら「Basic Information」に戻り、「Install to Workspce」を選択します。
APPの実行できる権限が表示されるので確認して「許可する」を選択します。
先ほどの「OAuth & Permissions」ペインでBot User OAuth Tokenが発行されていますのでこれをcopyしておいてください。
後の手順で使用します。
1.1 Slackチャンネル設定
Slackチャンネルに先ほど作成したAPPを追加します。
先ほどの権限設定でchat:write.public
を付与した場合はチャンネルに追加せずとも通知可能です。
通知したいSlackチャンネルの設定画面を開き「インテグレーション」から「アプリの追加」で作成したAPPを追加します。
同じ画面の「チャンネル情報」タブに記載されているチャンネルIDについても後の手順で使用しますのでcopyしておいてください。
2. Lambdaレイヤー&関数作成
AWS Lambdaはデフォルトでは外部ライブラリを利用することができません。
そのためライブラリと実行ファイルをひとまとめにしてzipファイル化してLambdaレイヤーにインポートすることでその外部ライブラリを利用することが可能になります。
今回はRSSフィード用のfeedparser
とSlack通知用のslack_sdk
を利用しているためLambdaレイヤーにそれぞれインポートしていきます。
Lambda関数1つにつき5つのレイヤーまでという制限があるため気になる方は複数のライブラリをひとまとめにしてアップロードしても問題ありません。
本項ではfeedparser
,slack_sdk
それぞれのLambdaレイヤーを作成し関数に紐づける手順を解説していきます。
「Lambda」コンソールに移動して「Lambdaレイヤーを作成」を選択します。
- 名前は任意の名前を選択(今回の場合はnt1-feedparserとnt1-slack_sdk)
- ライブラリをアップロードします。方法は割愛しますがpythonフォルダにpipなどを使用してライブラリをインストールしてzipファイル化すれば大丈夫です。
- 互換性のあるアーキテクチャ-オプションを「x86_64」を選択
- 互換性のあるランタイム-オプションを「Python3.8」を選択
作成が完了したら「関数」タブの「関数を作成」を選択します。
- 名前は任意の名前を選択(今回の場合はnt1-translate-rss)
- ランタイムは「Python3.8」を選択
- アーキテクチャは「x86_64」を選択
- 実行ロールは「基本的な Lambda アクセス権限で新しいロールを作成」を選択
※IAMロールは後から権限追加します。 - その他はデフォルトで問題ありません。
では先ほど作成したLambdaレイヤーをLambda関数に紐づけます。
下記画像の「Layers」を選択します。
「レイヤーの追加」を選択します。
- レイヤーソースは「カスタムレイヤー」を選択
- 先ほど作成したLambdaレイヤーを追加
レイヤーとして表示されていれば完了です。
2.1 Lambda関数設定
本項ではLambda関数のタイムアウト設定、アクセス権限を設定していきます。
タイムアウトの設定
今回の関数だとタイムアウト値がデフォルトの3秒では処理が終わらないため30秒くらいに設定しておきます。
この辺りはRSS URLの数やフィードの数に依存すると思いますので適宜変更してください。
Lambda関数の「一般設定」から「編集」を選択します。
- タイムアウトを30秒に設定
アクセス権限設定
Lambda関数の「アクセス権限」から「IAMロール名」を選択しIAMの画面に遷移します。
「許可を追加」⇒「ポリシーをアタッチ」からマネージドポリシーのTranslateFullAccessを選択します。
Lambda関数設定についてはこれで完了です。
2.2 Lambdaコード作成
Lambdaコードの全文は下記になります。
SLACK APPで使用するSLACK_ACCESS_TOKEN
とCHANNEL_ID
は1. Slack APP作成でcopyしたBot User OAuth TokenとチャンネルIDに置き換えてください。
import re import feedparser import boto3 import slack_sdk from datetime import datetime,timedelta from dateutil import tz from dateutil import parser from slack_sdk import WebClient # Amazon translate translate = boto3.client('translate') SRC_LANG = 'en' TRG_LANG = 'ja' # timezone timezone = tz.gettz('Asia/Tokyo') # RSS URL RSS_URL = 'https://aws.amazon.com/about-aws/whats-new/recent/feed/' def lambda_handler(event, context): # RSS取得 data = feedparser.parse(RSS_URL) # 1件ずつitemを取得 for entry in data.entries: print(entry.description) title = entry.title link = entry.link # summaryにはHTMLタグが含まれるので削除 description = remove_http_tag(entry.summary) # 現在の時刻と更新時刻を取得 published = parser.parse(entry.published).astimezone(timezone) current_time = datetime.now(timezone) # 1日前までに更新があったものだけ翻訳&Slack通知 if current_time < published + timedelta(days=1): # タイトルと要約はAmazon Translateで翻訳 ja_title = get_translate_text(title) ja_description = get_translate_text(description) # Slackに通知 SLACK_ACCESS_TOKEN = '<SLACK_ACCESS_TOKEN>' CHANNEL_ID = '<CHANNEL_ID>' # Slackクライアントを作成 client = WebClient(SLACK_ACCESS_TOKEN) # チャンネルにメッセージを投稿 msg = f"<{link}|{ja_title}>\n\n*概要:* {ja_description}" response = client.chat_postMessage(channel=CHANNEL_ID, text=msg, icon_emoji=':ghost:') def remove_http_tag(str): return re.sub(re.compile('<.*?>'), '', str) def get_translate_text(text): # 英語→日本語 翻訳 response = translate.translate_text( Text=text, SourceLanguageCode=SRC_LANG, TargetLanguageCode=TRG_LANG ) return response.get('TranslatedText')
Lambdaコード解説
ここからはコードの解説です。手順を先に進めたい方は3. Lambda関数実行まで読み飛ばしてください。
取得しているRSS
What’s New with AWS?からRSSフィードを取得しています。
日本語版のサイトもありますが英語版のほうが更新が速いので英語版で見たいです。
# timezone timezone = tz.gettz('Asia/Tokyo') # RSS URL RSS_URL = 'https://aws.amazon.com/about-aws/whats-new/recent/feed/' def lambda_handler(event, context): # RSS取得 data = feedparser.parse(RSS_URL) # 1件ずつitemを取得 for entry in data.entries:
RSSの取得方法
RSSフィードを一件ずつ処理していきます。
title
とlink
とsummary
を取得します。
summaryにはHTMLタグが含まれるため除外しています。
published
の時間と現在の時間を比較して1日前までに更新されたものだけ翻訳処理をかけるようにしています。
# 1件ずつitemを取得 for entry in data.entries: print(entry.description) title = entry.title link = entry.link # summaryにはHTMLタグが含まれるので削除 description = remove_http_tag(entry.summary) # 現在の時刻と更新時刻を取得 published = parser.parse(entry.published).astimezone(timezone) current_time = datetime.now(timezone) # 1日前までに更新があったものだけ翻訳&Slack通知 if current_time < published + timedelta(days=1): # タイトルと要約はAmazon Translateで翻訳 ja_title = get_translate_text(title) ja_description = get_translate_text(description) : [省略] : def remove_http_tag(str): return re.sub(re.compile('<.*?>'), '', str)
Amazon Translateによる翻訳
AWS SDK for Python (Boto3)を使用してAmazon Translateを呼び出し翻訳しています。
SRC_LANG
とTRG_LANG
で言語を選択してAPIをたたいて翻訳しています。
Amazon TranslateのAPIを利用するのに特段事前設定は必要なく非常にシンプルでわかりやすいです。
# Amazon translate translate = boto3.client('translate') SRC_LANG = 'en' TRG_LANG = 'ja' : [省略] : # 1日前までに更新があったものだけ翻訳&Slack通知 if current_time < published + timedelta(days=1): # タイトルと要約はAmazon Translateで翻訳 ja_title = get_translate_text(title) ja_description = get_translate_text(description) : [省略] : def get_translate_text(text): # 英語→日本語 翻訳 response = translate.translate_text( Text=text, SourceLanguageCode=SRC_LANG, TargetLanguageCode=TRG_LANG ) return response.get('TranslatedText')
Slackへの通知方法
Slack APPを使用しています。
通知フォーマットについては特にこだわる予定はなかったので最低限設定しています。
SLACK_ACCESS_TOKEN
とCHANNEL_ID
は1. Slack APP作成でcopyしたBot User OAuth TokenとチャンネルIDに置き換えてください。
# Slackに通知 SLACK_ACCESS_TOKEN = '<SLACK_ACCESS_TOKEN>' CHANNEL_ID = '<CHANNEL_ID>' # Slackクライアントを作成 client = WebClient(SLACK_ACCESS_TOKEN) # チャンネルにメッセージを投稿 msg = f"<{link}|{ja_title}>\n\n*概要:* {ja_description}" response = client.chat_postMessage(channel=CHANNEL_ID, text=msg, icon_emoji=':ghost:')
3. Lambda関数実行
では想定通り動くかどうかLambda関数を手動で実行してみましょう。
Lambdaのテスト画面から「テスト」を選択します。
うまくいった場合はSlackチャンネルに以下のようなメッセージが投稿されているかと思います。
4. EventBridge設定
最後に定期実行用のEventBridgeの設定を行います。
実行頻度はCron式もしくはrate式で設定することが可能です。
時間指定する際はUTC時間で設定が必要なので注意してください。
Lambda画面より「トリガーを追加」を選択します。
- ソースを選択で「EventBridge(Cloudwatch Events)」を選択
- Ruleで「Create a new rule」を選択
- Rule name、Rule descriptionは任意の値を選択
- Rule typeは「Schedule expression」を選択
- Schedule expressionはcron式もしくはrate式で入力できます。(私は朝7:00くらいに通知してほしいのでcron(0 22 * * ? *)と入力しました。)
最後に
以上がRSSリーダーで取得した英語を日本語に翻訳するアプリケーションを作成してSlackに通知する手順となります。
私と同じ英語苦手勢に刺さればいいなと思っています。
今のところAmazon Translateが翻訳した文章に違和感はありません。
これからもしばらく使ってみてAmazon Translateの翻訳精度についても確認していきたいですね。
最後まで読んでいただきありがとうございます!
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitterインフラエンジニアです。刹那的に生きてます。
Recommends
こちらもおすすめ
-
AWS Chatbotを使って、Slack通知をカスタマイズする
2024.2.15
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28
AWSの料金が 8 %割引になる!
『AWSの請求代行リセールサービス』
2023.01.15