15
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AWS FargateでSeleniumを使い定期的にチェックする環境を作ってみた

Last updated at Posted at 2020-01-07

TL;DR (5行)

  • 頻繁に手動で更新するようなWebページ(今回は例としてZOZOTOWNを使います)を自動チェックしたい
  • Fargateを使ってSeleniumの実行環境を作ります
  • ローカルのコンテナをECRにpushしてFargateにデプロイします
  • Seleniumによるブラウザ操作をスケジュール設定し,バッチ処理として動作させます
  • バッチ処理の結果は,CloudWatchにてチェック

注意

本記事はFargate+Selenium導入紹介を目的としています.
筆者は内定者で許可もとっているので,題材として自社サービスのZOZOTOWNを使ってます!
もし,記事内容を流用する場合はマナーや規約に違反しない範囲でお願いします!

使用するサービスの説明

Fargateとは

通常コンテナをEC2で運用する場合,インスタンス管理する必要がありますが,Fargateの場合,インスタンス管理はAmazon側に任せ,コンテナを登録するだけでサーバレスにコンテナを動作させることができるサービスです.

サーバレスで有名なサービスとしてLambdaがありますが,こちらはコンテナを使えなかったり,タイムアウトなどの制約から柔軟性に欠ける部分があります.

一方で,Fargateはローカルで実行しているコンテナをそのまま登録して使えるため,多様なサービスの提供が可能です.

Seleniumとは

Webアプリのテストを自動化するためのブラウザ駆動型テストツールです.

PythonやRuby,Javaなど多様な言語に対応しており,簡単にテストスクリプトを作成することができます.

アーキテクチャ

今回は,AWS上に以下のようなアーキテクチャを構築します.

スクリーンショット 2020-01-03 11.00.20.png

Dockerfileとメインコードの作成

Selenium + Pythonでテストスクリプトを作成します.

Dockerfileの作成

./Dockerfile
FROM joyzoursky/python-chromedriver:3.8-alpine3.10-selenium

WORKDIR /usr/src
ADD main.py /usr/src

CMD ["python", "main.py"]

今回,Selenium+Headless Chromeを使うにあたって,
ベースイメージはこちらを使っています.

joyzoursky/python-chromedriver:3.7-alpine3.8-selenium
https://hub.docker.com/r/joyzoursky/python-chromedriver/

メインコードの作成

./main.py
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.common.exceptions import TimeoutException, ElementClickInterceptedException, NoSuchElementException

def check_coupon(driver, my_favorite_brand):
    # ZOZOのクーポンページに遷移
    driver.get("https://zozo.jp/coupon/")
    i = 1
    while True:
      try:
          coupon_brand = driver.find_element_by_xpath(f'//*[@id="body"]/div[3]/ul/li[{i}]/a/figure/div[2]').text
          if coupon_brand == my_favorite_brand:
              return True
          i += 1
      except NoSuchElementException:
          return False

if __name__ == '__main__':
    try:
        # Headless Chromeの設定
        options = webdriver.ChromeOptions()
        options.add_argument('--no-sandbox')
        options.add_argument("--disable-setuid-sandbox")
        options.add_argument('--window-size=1420,1080')
        options.add_argument('--headless')
        options.add_argument('--disable-gpu')
        # Headless Chromeブラウザに接続
        driver = webdriver.Chrome(options=options)
        # seleniumの動作タイムアウトを15秒間に設定
        driver.implicitly_wait(15)

        # 好きなブランド
        my_favorite_brand = "Carlie e felice"
        # クーポンのチェック
        if check_coupon(driver, my_favorite_brand):
            print("見つけたよ! ", my_favorite_brand)
        else:
            print("今日は見つけられなかった・・・")

    # 例外処理
    except ElementClickInterceptedException as ecie:
        print(f"exception!\n{ecie}")
    except TimeoutException as te:
        print(f"timeout!\n{te}")
    finally:
        # 終了
        driver.close()
        driver.quit()

クーポンページにブランド:Carlie e feliceがあるかどうかチェックします.

Requests + Beautiful Soup 4でスクレピングしても良かったのですが,今回はSeleniumを使った環境を構築したかったので,まさかり投げないでください;;

ローカル環境でコンテナの実行

# コンテナの構築
$ docker build -t zozo_check_coupons .

# コンテナの実行
$ docker run -it --rm zozo_check_coupons
見つけたよ!  Carlie e felice

無事,ローカル環境で実行できたことを確認したら,次はこのコンテナをAmazon ECRにプッシュします.

ECRはAWS上のプライベートなDocker Hubみたいなイメージです.

AWSの必要環境の構築

ECRの環境を構築

ECRのリポジトリ作成

ECRに今回管理したいコンテナ専用のリポジトリを作成します.

  • サービスから,ECRを選択し,リポジトリの作成を選択
    2.png

  • リポジトリ名「zozo_check_coupons」を入力し,リポジトリを作成

スクリーンショット 2020-01-02 21.21.16.png
  • 無事,リポジトリを作成することができました
    4.png

このときの,リポジトリのURIはコンテナをプッシュするときに,使うのでメモしておきましょう.

ECRにログイン

$ aws ecr get-login --region ap-northeast-1 --no-include-email
docker login -u AWS -p ...
.
.
. .dkr.ecr.ap-northeast-1.amazonaws.com

# 返ってきたdocker login ~をコピペして打ち込む
$ docker login -u AWS -p ...
Login Succeeded

Login Succeededと表示されたらOKです

ECRにプッシュ

先程,メモしたリポジトリのURLをコピペし,作成したリポジトリにプッシュします

# リポジトリのURIでタグを付ける
$ docker build -t xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/zozo_check_coupons .
# タグをつけたコンテナをECRにプッシュする
$ docker push xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/zozo_check_coupons

コンテナを無事リポジトリにプッシュできました
1.png

イメージのURIは,タスク定義で使うので,メモしておきましょう

ECSでクラスター作成

コンテナを動作させる環境であるクラスターを作ります

  • サービスからECSを選択し,クラスターの作成を選択します.
    3.png

  • クラスターテンプレート「ネットワーキングのみ」を選択

スクリーンショット 2020-01-02 22.31.59.png
  • クラスター名を入力し,VPCの作成にチェックします.
スクリーンショット 2020-01-02 22.33.54.png
  • 最後に,作成ボタンを押せばクラスターが作成できます
    5.png

ECSでタスクの定義

次に,タスクの定義をします.

  • 新しいタスクの定義の作成を選択します
    6.png

  • 起動タイプの互換性の選択でFargateを選択

スクリーンショット 2020-01-02 22.56.44.png
  • 以下のようにタスクを定義します
スクリーンショット 2020-01-02 22.57.26.png

タスク実行ロールが何もない場合は,下の余談を参照し,作成してください

  • コンテナ追加を選択し,コンテナ名と先程プッシュしたコンテナイメージのURIをここでコピペします
スクリーンショット 2020-01-02 22.59.54.png
  • メモリとCPUを設定
スクリーンショット 2020-01-03 01.07.10.png
  • 最後に,作成を選択してタスク定義完了です
    7.png

余談 : CLIでタスク定義

  • タスク実行に必要なロールを定義
./task-execution-assume-role.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
  • 定義ファイルを用いて,ロールの作成
$ aws iam --region ap-northeast-1 create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://task-execution-assume-role.json
  • タスクの定義ファイルを作成
./task-config.json
{
  "family": "zozo-check-coupons-task",
  "networkMode": "awsvpc",
  "containerDefinitions": [
    {
      "name": "zozo-check-coupons-task",
      "image": "xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/zozo_check_coupons:latest",
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-region": "ap-northeast-1",
          "awslogs-group": "/ecs/zozo_check_coupons-task",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ],
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "256",
  "memory": "512",
  "executionRoleArn": "arn:aws:iam::xxxxxxxx:role/ecsTaskExecutionRole"
}
  • 定義ファイルをもとにタスクを作成
$ aws ecs register-task-definition --cli-input-json file://task-config.json

これで,打ち間違い,漏れなくタスクを定義することができます

詳しくは,こちらを参照ください
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-cli-tutorial-fargate.html

スケジュール実行の作成

次に,いよいよ定義したタスクをスケジュールで実行していきます.

  • 作成したクラスターを選択し,タスクのスケジューリングを選択,そして作成を押します

8.png

  • 以下のように設定しました.固定時間は,クーポン更新が24時間だったので24に設定しました
スクリーンショット 2020-01-02 23.05.25.png
  • クラスター作成時に,作成したVPCを選択します
    9.png

  • 最後に,作成を選択すると,タスクが実行されます
    10.png

CloudWatchでログをチェック

タスクが完了すると,CloudWatchの方にログが送られます

確認すると,以下のようなログがありました!

11.png

今日は無いみたいですね...

おわりに

Fargate + Seleniumの環境を作りました!
Fargateはコンテナを使って動かしたコンテナをそのまま登録できるので,かなり柔軟性はいいです.

ですが,クローリングをする場合,CPUやメモリにページの読み込みが遅くなり,プログラムによるブラウザ操作がうまく行かなかったり,タイムアウトが発生してしまう場合があるので,sleepを入れる等の対策は十分にしたほうが良さそうです.

最後に,本記事は導入目的で紹介しているので,流用する場合はマナーや規約をよく読んでからお願いします!

参考文献

15
10
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
15
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?