5
3

More than 1 year has passed since last update.

AWS Lambda+seleniumでLineにpush通知やってみた

Posted at

この記事で言いたいこと

  • web 画面のpull型確認がめんどいのでLine通知にした
  • ハマったポイント

きっかけ

  • 子供が習い事をしていて、土日に練習会がある。

  • 練習場所が、毎週可変

  • 場所は昔ながらの掲示版でのみ知らされる。

  • あれ、今週末はどこだっけ? →わざわざ掲示版を見に行く
     ↑これが面倒 →プッシュ型の通知にしたかった。

  • 掲示版(sample)
    image.png

ひらめき

seleniumで掲示版での投稿内容を読み取って、
lamdaからプッシュ通知すればできるのでは?

image.png image.png

できたこと

image.png

作成にあたり

工夫点

  • まずは、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 へ搭載する方法

image.png

  1. ↑のフォルダ構成にseleniumライブラリ一式を準備
  pip install -t ./python/lib/python3.7/site-packages selenium
  1. python フォルダ直下をzip圧縮
     (この構成を間違うと認識してくれない)
  2. lambdaから importできる。(この時構成は無視)
 from selenium import webdriver

※他のライブラリも同様

ChromDriver を Layers に搭載する方法

image.png

  1. 公式配布されているchromdriver、headless-chromium の2点を準備、
    (linux環境で)zip圧縮 ※window環境でのzip ではダメ
  2. linux環境がないので、dockerイメージを呼び出し、zip 圧縮して、Layer にアップ
  3. lambdaから 以下パスを指定して呼ぶ(/opt に配置される)
driver = webdriver.Chrome(executable_path ="/opt/chromedriver", chrome_options=options)

lambda構成

image.png

layer の設定

image.png

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 メッセージ

image.png

やってみて

  • aws のクセにあわせるのが大変(自前でサーバ立てるよりは楽)
  • alexaスキルでの実装も考えたが、投稿内容をうまく絞るのが難しそうなのでやめた。
  • 掲示板に、更新通知機能があった(メール)(後でわかった)
  • 課金体系はまだ調べてない。
  • lambda 単体でも遅い、かつselenium も遅いので30秒くらいかかる。

まとめ

  • 身近な問題を個人で実装・解決できるのは良いこと
5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3