この記事はリンク情報システムの2021新春アドベントカレンダー Tech Connect!のリレー記事です。
Tech Connect! は勝手に始めるアドベントカレンダーとして、engineer.hanzomon のグループメンバによってリレーされます。
この間のセールで買いそびれた人に向けた記事です。
スクレイピングした結果をSlackに連携するだけのよくあるやつですが、他の記事との差別化を図るためにGoogle Cloud Platform(以下GCP), Microsoft Azure(以下Azure), Amazon Web Services(以下AWS)にそれぞれデプロイしてみます。
つくるもの
1日1回 My Nintendo StoreのOnikenのページ を見に行ってセール中だったらSlackに連携する。
つくる
My Nintendo Storeのrobots.txtを確認
https://store-jp.nintendo.com/robots.txt を確認します。
「/list/software/」はDisallowされていなかったので問題なし。
Slackの設定
アプリの追加画面を開く
Incoming WebHooksを追加
通知先のチャンネルを指定
Webhook URLをメモ
スクリプトなどの準備
スクレイピングとSlackへの連携用のスクリプト
とりあえず動けばいいぐらいのやつ。
import json
import os
import requests
from bs4 import BeautifulSoup
res = requests.get(os.environ['TARGET_URL'])
soup = BeautifulSoup(res.text, 'html.parser')
div = soup.select_one('div.productDetail--detail__pricePrice')
if div is not None:
item = {
"text": div.text.strip()
}
json_data = json.dumps(item)
res = requests.post(os.environ['WEBHOOK_URL'], json_data)
スクレイピング
div = soup.select_one('div.productDetail--detail__pricePrice')
で以下の情報(値段)を取得します。
これが取得できなかった場合はセール中ではないためSlackへは連携しません。
Slackへの連携
res = requests.post(os.environ['WEBHOOK_URL'], json_data)
の部分。
Webhook URLへjsonのデータをpostするだけです。
今回は単純なメッセージですが、複雑なものを作ってみたい場合はBlock Kit Builderで色々試してみるのがいいかと思います。
requirements.txt
beautifulsoup4==4.9.1
requests==2.24.0
GCPへデプロイ
開く
Cloud Functions
スクレイピングしてSlackに連携する部分を担当。
Cloud Functionsを選択
関数を作成
各種設定
"基本"はお好きなように。
"トリガー"は画像の通りに設定して"保存"する。
URLは後で使うのでメモしておくこと
ランタイム環境変数の設定
名前 | 値 |
---|---|
TARGET_URL | OnikenのページのURL |
WEBHOOK_URL | 最初の方でメモしたSlackのWebhook URL |
Build APIの有効化
スクリプトを編集
requirements.txtを編集
デプロイ完了を確認
Cloud Scheduler
これを使って1日1回Cloud Functionsを実行します。
無料枠で3ジョブまで作成できる
Cloud Schedulerを選択
ジョブを作成
この画面のあとにリージョン選択画面がありますが、スクショを撮り忘れました。
好きな場所を選択してください。
各種設定
名前、説明などはお好きなように。
項目 | 値 |
---|---|
ターゲット | HTTP |
URL | 先ほど作成したCloud FunctionsのトリガーURL |
HTTPメソッド | GET |
設定が終わったら"作成"。
GCPへのデプロイ終わり
GCPへのデプロイはこれで終わりです。
Azureへデプロイ
開く
環境構築
今回の構成ではAzure Portal上でコードを書けないため、色々と準備が必要になります。
長くなりそうなので詳細は割愛します。
- Node.js
- Python(3.6, 3.7, 3.8のいずれか)
- Visual Studio Code
- Visual Studio CodeのPython拡張
- Visual Studio CodeのAzure Functions拡張
関数アプリ(Azure Functions)
リソースの作成
関数アプリを選択
各種設定
赤枠以外はお好きなように。
他はデフォルトで"確認および作成"。
作成
環境変数の設定
以下の2つを設定して"保存"。
名前 | 値 |
---|---|
TARGET_URL | OnikenのページのURL |
WEBHOOK_URL | 最初の方でメモしたSlackのWebhook URL |
関数を作成
Visual Studio Codeでの操作になります。
Azureにサインイン
プロジェクト作成
今回はDesktopに作ったazure_sampleフォルダで作業を行います。
言語を選択
関数のトリガーを選択
名前を付ける
スケジュールを指定
スクリプトを編集
しばらく待つと__init__.py
というファイルが開かれるので、事前に用意していた内容に書き換えます。
requirements.txtを編集
プロジェクトフォルダ(今回はazure_sample)にrequirements.txtがあるのでそれを編集します。
デプロイ
Azureへのデプロイ終わり
Azureへのデプロイはこれで終わりです。
Timer triggerのおかげで関数アプリ単独で実現できました。
AWSへデプロイ
開く
Lambda
関数作成の画面に行く
関数の作成
関数名はお好きなように。
オプションとランタイムの選択が終わったら"関数の作成"。
zipファイルをつくる
bs4~urllib3まではpythonのライブラリ。
lambda_function.py
は事前に用意したスクリプトをlambda用にしたもの。
oniken.zip
├ bs4
├ certifi
├ chardet
├ idna
├ requests
├ soupsieve
├ urllib3
└ lambda_function.py
import json
import os
import requests
from bs4 import BeautifulSoup
def lambda_handler(event, context):
res = requests.get(os.environ['TARGET_URL'])
soup = BeautifulSoup(res.text, 'html.parser')
div = soup.select_one('div.productDetail--detail__pricePrice')
if div is not None:
item = {
"text": div.text.strip()
}
json_data = json.dumps(item)
res = requests.post(os.environ['WEBHOOK_URL'], json_data)
return "success"
zipファイルのアップロード
環境変数の設定
以下の2つを設定して"保存"。
名前 | 値 |
---|---|
TARGET_URL | OnikenのページのURL |
WEBHOOK_URL | 最初の方でメモしたSlackのWebhook URL |
トリガー
トリガーを追加
EventBridgeの設定
AWSへのデプロイ終わり
AWSへのデプロイはこれで終わりです。
ライブラリも自分でアップロードしないといけないので面倒でした。(GCP, Azureはrequirements.txt書くだけ)
動作確認
00:00(GCP)、01:00(Azure)、02:00(AWS)にそれぞれ通知が来る予定でしたが、AzureとAWSが9時間ほどずれています。
GCPはCloud Schedulerでタイムゾーンを設定しましたが、そういえばAzureとAWSではそのような設定が無かったような気がします。
Azure
ログを見ると01:03(UTC)に動いていました。
3分のずれは一体?
AWS
ログを見るとこちらも02:00(UTC)に動いていました。
とはいえ
動きはしたのでこれは宿題とします。
まとめ
環境構築が出来ていればAzureが圧倒的に楽でした。
Timer triggerは偉大。
種類 | かんたん | ふつう | むずかしい |
---|---|---|---|
環境構築していない | GCP | AWS | Azure |
環境構築済み | Azure | GCP | AWS |
参考
- Visual Studio Code と Python を使用して Azure に関数を作成する
- Azure での関数アプリの設定の構成 | Microsoft Docs
- Python の AWS Lambda デプロイパッケージ - AWS Lambda
あんなこととは?
Microsoft StoreのOnikenのページより引用。
不吉な企業によって制御された目次録後の未来において、8ビットのアクション/プラットフォームの過酷なゲームプレイに触発されて、鬼剣は敵、罠、そして挑戦的なボスの籠手に対してあなたの敏捷性と刀剣を打ちつけます。
少し読んでもらえば分かる通り、日本語がおかしなことになっています。
翻訳元を探る
Microsoft StoreのOnikenのページ(英語)より引用。
パブリッシャーの製品ページも同じ文章。
In a post-apocalyptic future controlled by a sinister corporation, ninja mercenary Zaku is the last hope for humanity. Inspired by the demanding gameplay of 8-bit action/platformers, Oniken pits your agility and swordplay against a gauntlet of enemies, traps, and challenging bosses.
「目次録」とは「黙示録」のことでした。
翻訳してもらう
原文(日本語ページ)を見る限り何らかの翻訳をかませてそうなので、英語ページの文章をいくつかのサイトで翻訳してもらいます。
不吉な企業によって支配された終末後の未来において、忍者傭兵ザクは人類への最後の希望です。 8ビットアクション/プラットフォーマーの要求の厳しいゲームプレイに触発されたOnikenは、敵、罠、挑戦的なボスのガントレットに対して敏捷性と剣術を打ち負かします。
邪悪な企業に支配されたポスト黙示録的な未来では、忍者の傭兵ザクが人類の最後の希望となっていた。8ビットアクション/プラットフォーマーの厳しいゲーム性にインスパイアされた「鬼剣」は、敏捷性と剣術を駆使して、敵、トラップ、ボスなどの難関を突破していく。
不吉な企業が支配するポスト黙示録的な未来の中で、忍者傭兵ザクは人類の最後の希望です。8ビットアクション/プラットホームの厳しいゲームプレイに触発され、Onikenは敵、トラップ、そして挑戦的なボスのガントレットに対してあなたの敏捷性と剣遊びをピット。
不吉な企業によって支配された後の後進法において、忍者の傭兵のザクは人類にとって最後の希望である。 8 ビットアクション/小皿の厳しいゲームに触発され、鬼剣は敵、罠、そして挑戦的なボスに対して、機敏に剣術を注ぎ、その腹部に対して剣術を行う。
Google翻訳の結果が原文に近い
DeepL翻訳を除いた3つはほぼ似た結果になっており、中でもGoogle翻訳は忍者傭兵ザクの部分を除くとかなり原文に近い印象です。
原文とGoogle翻訳の結果を並べて違いを見てみます。
- 原文
不吉な企業によって制御された目次録後の未来において、8ビットのアクション/プラットフォームの過酷なゲームプレイに触発されて、鬼剣は敵、罠、そして挑戦的なボスの籠手に対してあなたの敏捷性と刀剣を打ちつけます。
- Google翻訳(から忍者傭兵ザクの部分を除外)
不吉な企業によって支配された終末後の未来において、8ビットアクション/プラットフォーマーの要求の厳しいゲームプレイに触発されたOnikenは、敵、罠、挑戦的なボスのガントレットに対して敏捷性と剣術を打ち負かします。
Google翻訳のアップデートで翻訳結果が変わってしまったようなレベルの違いしかないように見えます。
深まる謎
日本語ページの文章はおそらくGoogle翻訳の結果をベースにしていると思われる、というところまでは来ましたが理解できない謎が残っています。
-
目次録
何をどうやったら黙示録が目次録になってしまうのか検討もつきません。
英語 → (翻訳) → 日本語 → (音声読み上げ) → (Speech to Text) → 日本語 とすれば、Speech to Textの箇所で聞き間違いが発生する可能性もなくはないですが、わざわざこんなことする意味もないでしょう。 -
消えてしまった忍者傭兵ザク
ザクはOnikenの主人公です。
翻訳の際に
おわりに
答えに近づけた方がいましたらぜひ教えて下さい。