この記事で言いたいこと
- web 画面のpull型確認がめんどいのでLine通知にした
- ハマったポイント
きっかけ
-
子供が習い事をしていて、土日に練習会がある。
-
練習場所が、毎週可変
-
場所は昔ながらの掲示版でのみ知らされる。
-
あれ、今週末はどこだっけ? →わざわざ掲示版を見に行く
↑これが面倒 →プッシュ型の通知にしたかった。
ひらめき
seleniumで掲示版での投稿内容を読み取って、
lamdaからプッシュ通知すればできるのでは?
できたこと
作成にあたり
工夫点
- まずは、PCローカルからselenium~line通知ができるか確認する。
- 掲示版のどの要素を読み取るかは、chrome の開発者ツールでXPathを確認
仕様
- 週に2回程度の更新なので、最新の2件のみ取得。
- 週末だけ必要なので、水~金の18時に通知させる。
- lambdaの課金体系がわからないが、とりあえずやってみる。
すんなりできた点
■掲示版の最新の2件のみ取得 (python)
for num in range(1,3):
title=driver.find_element_by_xpath("/html/body/div[6]/div/div[" + str(num) + "]/h3/a")
toukou=driver.find_element_by_xpath("/html/body/div[6]/div/div[" + str(num) + "]/p")
- lambda 関数の作成(経験あり)
- 定期実行させるためのCloud watch の設定
簡単なcron 式と、lamdaを指定するだけ。(英国時間になるので注意) - Line通知(経験あり)
ハマった点
- python のライブラリ(=selenium)は aws Layers に搭載させる。
lamdaにごちゃごちゃ置いても良いが、依存関係がわからなくなる。 - chrom Driver は aws Layers に搭載する必要がある。
- aws Layers がわからない・・
→lamda から共通的に使える共通関数のようなもの。 - aws Layers への搭載の仕方や、呼び方がわからない。
→ここのクセが強い。
python ライブラリ(selenium)を Layers へ搭載する方法
- ↑のフォルダ構成にseleniumライブラリ一式を準備
pip install -t ./python/lib/python3.7/site-packages selenium
- python フォルダ直下をzip圧縮
(この構成を間違うと認識してくれない) - lambdaから importできる。(この時構成は無視)
from selenium import webdriver
※他のライブラリも同様
ChromDriver を Layers に搭載する方法
- 公式配布されているchromdriver、headless-chromium の2点を準備、
(linux環境で)zip圧縮 ※window環境でのzip ではダメ - linux環境がないので、dockerイメージを呼び出し、zip 圧縮して、Layer にアップ
- lambdaから 以下パスを指定して呼ぶ(/opt に配置される)
driver = webdriver.Chrome(executable_path ="/opt/chromedriver", chrome_options=options)
lambda構成
layer の設定
python コード
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import urllib.parse
import urllib.request
def lambda_handler(event, context):
LINE_NOTIFY_URL = "https://notify-api.line.me/api/notify"
options = Options()
options.binary_location = '/opt/headless-chromium'
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--single-process')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(executable_path ='/opt/chromedriver', chrome_options=options)
driver.get("掲示板のURL")
for num in range(1,3):
title=driver.find_element_by_xpath("/html/body/div[6]/div/div[" + str(num) + "]/h3/a")
toukou=driver.find_element_by_xpath("/html/body/div[6]/div/div[" + str(num) + "]/p")
msg="\n■title:" + title.text + "\n■本文:" + toukou.text
#line 通知
method = "POST"
headers = {"Authorization": "Bearer %s" % "Line認証キー"}
payload = {"message": msg}
payload = urllib.parse.urlencode(payload).encode("utf-8")
req = urllib.request.Request(url=LINE_NOTIFY_URL, data=payload, method=method, headers=headers)
urllib.request.urlopen(req)
line メッセージ
やってみて
- aws のクセにあわせるのが大変(自前でサーバ立てるよりは楽)
- alexaスキルでの実装も考えたが、投稿内容をうまく絞るのが難しそうなのでやめた。
- 掲示板に、更新通知機能があった(メール)(後でわかった)
- 課金体系はまだ調べてない。
- lambda 単体でも遅い、かつselenium も遅いので30秒くらいかかる。
まとめ
- 身近な問題を個人で実装・解決できるのは良いこと