はじめに
筆者は粗品が好きで、単独ライブ「電池の切れかけた蟹」のチケットを毎回とっていますが、最近チケット販売の告知がなくなり、気付いたら販売終了してた....
となることが何度かありました。
そこで、チケットが販売されたら通知がくるものを作りたいと考え、
下記サービスについては初心者ですが、色々調べながら頑張って作ってみました。
環境・利用サービス
・Windows11
・Python 3.12
・AWS Lambda
・AWS ECR
・Docker
・LINE Notify
とりあえずPython書いてみる
チケット販売が開始しているかを確認するため、pythonでseleniumを使って
吉本のお笑いライブチケット販売サイトの「FANYチケット」へクローリングを行います。
FANYチケットサイトをデベロッパーツールで確認したところ、
「芸人/公演名/会場で探す!」という検索欄で「粗品」と検索し、「電池の切れかけた蟹」というボックスがあれば、チケット販売あり、なければチケット販売なし、という通知を送るようにすれば、目的通りの動作ができそうです。
また、通知方法は色々ありますが、毎日見ているLINEで通知が来ると都合が良いので、
今回はLINE Notifyを使います。
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の通知が届き、しっかりと動作しています。
あとはこのコードを定期実行すれば完成です。
AWS Lambdaの実装
上記のコードを定期実行するためには色々とやり方はあると思いますが、
今回はお金をかけずサーバレスで実行したかったので、
勉強中でもあるAWS Lambdaを使ってみようと思いました。
AWS Lambdaとは
AWS Lambdaは、Amazon Web Services(AWS)が提供するサーバーレスコンピューティングサービスの一つです。
AWS Lambdaを用いることでコードをサーバレスで実行することが可能です。
今回の場合は1日に1回しかコードを実行しないので、無料枠で利用することができます。
関数の作成
早速、関数を作成し、seleniumやrequestsなどの外部ライブラリもレイヤー追加してみました。
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は初心者だったため、作成にはこちらを参考に作成しました。
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にてイメージが作成されたことを確認できます。
Amazon ECRへプッシュ
Amazon ECRとは
Amazon ECR (Elastic Container Registry) は、AWS(Amazon Web Services)が提供する、Dockerコンテナイメージの保存、管理、デプロイを行うためのコンテナレジストリサービスです。ECRを利用することで、セキュアかつスケーラブルな方法でコンテナイメージを保存し、デプロイできます。
AWS CLIを使用しECRへプッシュ
AWS CLIにてコマンドを実行することで、先ほど作成したDockerイメージをECRへプッシュすることができます。
ECRにて下記のようなリポジトリにイメージが作成できていればプッシュが完了しています。
ECRにプッシュしたDockerイメージをLambdaへ
Lambda関数作成時に、コンテナイメージから作成を選択し、先ほどECRで作成した
コンテナイメージURIを入力し「イメージを参照」をクリックして、関数を作成します。
コンテナの大きさによって時間がかかる場合がありますが、無事関数の作成ができました。
ちなみに、デフォルトでは関数のタイムアウトが3秒になっていますが
seleniumには短すぎるため、1分に変更しました。
定期実行のためのトリガー作成
Lambdaのトリガー追加から、定期実行のためのトリガーを作成します。
トリガーのソースはEventBridgeを使用し、1日おきに実行するようにしました。
トリガー追加後の実行結果
トリガーを追加することで一日おきにチケット販売が開始されたかどうか、
自動でLINEに通知を送ることができました。
まとめ
Lambdaを使用し、電蟹のチケットが販売されているかどうかを
1日おきにLINEに通知することができるようになりました。
これでチケット購入を忘れることがなくなりました。
今回はseleniumについてあまり知識がなかったので、もう少し勉強をして
次は自動でチケットを買えるようにしたいです。