2
1
はじめての記事投稿
Qiita Engineer Festa20242024年7月17日まで開催中!

AWS Lambdaを使って粗品の「電池の切れかけた蟹」のチケット販売開始通知をLINEに送信してみた

Last updated at Posted at 2024-07-06

はじめに

筆者は粗品が好きで、単独ライブ「電池の切れかけた蟹」のチケットを毎回とっていますが、最近チケット販売の告知がなくなり、気付いたら販売終了してた....
となることが何度かありました。

そこで、チケットが販売されたら通知がくるものを作りたいと考え、
下記サービスについては初心者ですが、色々調べながら頑張って作ってみました。

環境・利用サービス

・Windows11
・Python 3.12
・AWS Lambda
・AWS ECR
・Docker
・LINE Notify

とりあえずPython書いてみる

チケット販売が開始しているかを確認するため、pythonでseleniumを使って
吉本のお笑いライブチケット販売サイトの「FANYチケット」へクローリングを行います。

FANYチケットサイトをデベロッパーツールで確認したところ、
「芸人/公演名/会場で探す!」という検索欄で「粗品」と検索し、「電池の切れかけた蟹」というボックスがあれば、チケット販売あり、なければチケット販売なし、という通知を送るようにすれば、目的通りの動作ができそうです。

また、通知方法は色々ありますが、毎日見ているLINEで通知が来ると都合が良いので、
今回はLINE Notifyを使います。

python
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import requests


# LINE Notifyの設定
LINE_NOTIFY_TOKEN = 'LINE notifyのトークン'
LINE_NOTIFY_API = 'LINE notifyのAPI'

def send_line_notify(message):
    headers = {
        'Authorization': f'Bearer {LINE_NOTIFY_TOKEN}',
    }
    data = {
        'message': message,
    }
    response = requests.post(LINE_NOTIFY_API, headers=headers, data=data)
    if response.status_code == 200:
        print("LINE Notify: メッセージが送信されました")
    else:
        print("LINE Notify: メッセージの送信に失敗しました")



# ChromeDriverのパスを指定
driver_path = 'chromeドライバーのパス'

# ChromeOptionsを使用してChromeDriverのパスを指定
options = webdriver.ChromeOptions()
options.add_argument(f"--binary={driver_path}")

# WebDriverをセットアップ
driver = webdriver.Chrome(options=options)

try:
    # 指定されたURLにアクセス
    driver.get('https://yoshimoto.funity.jp/')
    
    # 検索ボックスに「粗品」と入力し検索
    search_box = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.XPATH, '//*[@id="kw"]'))
    )
    search_box.send_keys('粗品')
    search_box.send_keys(Keys.RETURN)
    
    # 検索結果を待つ
    time.sleep(3)  # ページが読み込まれるまで待つ
    
    # 検索結果を確認
    try:
        # 「電池の切れかけた蟹」と書いているボックスを探す
        element = driver.find_element(By.XPATH, '//*[contains(text(),"電池の切れかけた蟹")]')
        if element:
            message = "チケットが販売されています"
            print(message)
        else:
            message = "チケットなし"
            print(message)
    except:
        message = "チケットなし"
        print(message)
    
    # LINE Notifyで結果を通知
    send_line_notify(message)
    
finally:
    # ブラウザを閉じる
    driver.quit()

実行結果

LINEの通知が届き、しっかりと動作しています。
あとはこのコードを定期実行すれば完成です。

IMG_9965.jpg

AWS Lambdaの実装

上記のコードを定期実行するためには色々とやり方はあると思いますが、
今回はお金をかけずサーバレスで実行したかったので、
勉強中でもあるAWS Lambdaを使ってみようと思いました。

AWS Lambdaとは

AWS Lambdaは、Amazon Web Services(AWS)が提供するサーバーレスコンピューティングサービスの一つです。
AWS Lambdaを用いることでコードをサーバレスで実行することが可能です。
今回の場合は1日に1回しかコードを実行しないので、無料枠で利用することができます。

関数の作成

早速、関数を作成し、seleniumやrequestsなどの外部ライブラリもレイヤー追加してみました。
image.png

Lambdaがエラーで動かず....

なぜかエラーが出てしまい実行できませんでした。
色々調べたところLambdaではpython3.7のランタイムでしかseleniumが動作しないようです。
しかし、python3.7のランタイムは2023年に終了しており、Lambda上でseleniumを動かすことは現状できないようです。

解決策

Lambda上で直接seleniumを使うことはできませんが、Dockerコンテナを作成し、
DockerコンテナをLambdaで実行すれば解決できそうです。

Dockerイメージの作成

Dockerとは

Docker は、ソフトウェアのコンテナ化を実現するオープンプラットフォームです。Dockerを使用することで、アプリケーションとその依存関係を一つのコンテナとしてパッケージ化し、どこでも一貫して動作するようにすることができます。

Dockerfile作成

Dockerfileとは、Dockerイメージを構築するためのファイルです。
今回はseleniumやchromedriverなどをインストールしていきます。

Dockerは初心者だったため、作成にはこちらを参考に作成しました。

Dockerfile
FROM public.ecr.aws/lambda/python:3.12 as build
RUN dnf install -y unzip && \
    curl -Lo "/tmp/chromedriver-linux64.zip" "https://storage.googleapis.com/chrome-for-testing-public/126.0.6478.126/linux64/chromedriver-linux64.zip" && \
    curl -Lo "/tmp/chrome-linux64.zip" "https://storage.googleapis.com/chrome-for-testing-public/126.0.6478.126/linux64/chrome-linux64.zip" && \
    unzip /tmp/chromedriver-linux64.zip -d /opt/ && \
    unzip /tmp/chrome-linux64.zip -d /opt/

FROM public.ecr.aws/lambda/python:3.12
RUN dnf install -y atk cups-libs gtk3 libXcomposite alsa-lib \
    libXcursor libXdamage libXext libXi libXrandr libXScrnSaver \
    libXtst pango at-spi2-atk libXt xorg-x11-server-Xvfb \
    xorg-x11-xauth dbus-glib dbus-glib-devel nss mesa-libgbm
RUN pip install selenium==4.22.0
RUN pip install requests
COPY --from=build /opt/chrome-linux64 /opt/chrome
COPY --from=build /opt/chromedriver-linux64 /opt/
COPY main.py ./
CMD [ "main.handler" ]

※ディレクトリ構造は以下になっており、main.pyは先ほどのコードです。

denkani/
├── Dockerfile
└── main.py

Dockerイメージのビルド

ターミナルにてDocker buildコマンドでDockerイメージを作成します。
Docker Desktopにてイメージが作成されたことを確認できます。
image.png

Amazon ECRへプッシュ

Amazon ECRとは

Amazon ECR (Elastic Container Registry) は、AWS(Amazon Web Services)が提供する、Dockerコンテナイメージの保存、管理、デプロイを行うためのコンテナレジストリサービスです。ECRを利用することで、セキュアかつスケーラブルな方法でコンテナイメージを保存し、デプロイできます。

AWS CLIを使用しECRへプッシュ

AWS CLIにてコマンドを実行することで、先ほど作成したDockerイメージをECRへプッシュすることができます。
ECRにて下記のようなリポジトリにイメージが作成できていればプッシュが完了しています。

image.png

ECRにプッシュしたDockerイメージをLambdaへ

Lambda関数作成時に、コンテナイメージから作成を選択し、先ほどECRで作成した
コンテナイメージURIを入力し「イメージを参照」をクリックして、関数を作成します。

image.png

コンテナの大きさによって時間がかかる場合がありますが、無事関数の作成ができました。
image.png

ちなみに、デフォルトでは関数のタイムアウトが3秒になっていますが
seleniumには短すぎるため、1分に変更しました。
image.png

定期実行のためのトリガー作成

Lambdaのトリガー追加から、定期実行のためのトリガーを作成します。
トリガーのソースはEventBridgeを使用し、1日おきに実行するようにしました。
image.png

トリガー追加後の実行結果

トリガーを追加することで一日おきにチケット販売が開始されたかどうか、
自動でLINEに通知を送ることができました。

IMG_9966.jpg

まとめ

Lambdaを使用し、電蟹のチケットが販売されているかどうかを
1日おきにLINEに通知することができるようになりました。
これでチケット購入を忘れることがなくなりました。

今回はseleniumについてあまり知識がなかったので、もう少し勉強をして
次は自動でチケットを買えるようにしたいです。

2
1
1

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
2
1