LoginSignup
0
0

EventBridgeScheduler+ECS+Docker+SeleniumでWebサイトのスクリーンショットを定期的に撮影する

Last updated at Posted at 2024-02-07

EventBridgeScheduler, ECS, Docker, Seleniumを使い1時間ごとに阿部寛のHPのスクリーンショットを撮影しS3に保存する方法についてまとめました。

スクレイピング用のDockerイメージを作成

以下の記事を参考にしながらスクレイピング用のDockerイメージを作成します。
環境変数からスクレイピング先のURLと保存先のバケットを読み取ります。

参考: Selenium×dockerでテスト自動化してみた

.
├── Dockerfile
└── app
    └── main.py
Dockerfile
FROM --platform=linux/x86_64 python:3.12.1-alpine3.19

ENV PYTHONIOENCODING utf-8
WORKDIR /app

RUN apk add --update \
        wget \
    # Add chromium and dependences
        udev \
        ttf-freefont \
        chromium \
        chromium-chromedriver \
    # Add Japanese font
    && mkdir noto \
    && wget -P /app/noto https://noto-website.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip \
    && unzip /app/noto/NotoSansCJKjp-hinted.zip -d /app/noto \
    && mkdir -p /usr/share/fonts/noto \
    && cp /app/noto/*.otf /usr/share/fonts/noto \
    && chmod 644 -R /usr/share/fonts/noto/ \
    && fc-cache -fv \
    && rm -rf /app/noto \
    # Add selenium
    && pip install selenium \
    && pip install boto3

COPY ./app .

CMD [ "python", "main.py" ]
main.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
import os
import shutil
import configparser
import datetime
import boto3


def save_screenshot(target_url: str, bucket_name: str):
    folder = '/opt/app'

    service = Service(executable_path=r'/usr/bin/chromedriver')
    options = webdriver.ChromeOptions()
    options.add_argument('--headless')
    options.add_argument('--no-sandbox')
    options.add_argument('--disable-dev-shm-usage')
    options.add_argument('--disable-gpu')
    options.add_argument('--window-size=1200x1800')
    prefs = {"download.default_directory" : folder}
    options.add_experimental_option("prefs",prefs)

    driver = webdriver.Chrome(service=service, options=options)

    driver.get(target_url)

    file_name = str(datetime.datetime.now()) + '.png'
    driver.save_screenshot(file_name)
    driver.quit()

    client = boto3.client('s3',region_name='ap-northeast-1')
    client.upload_file(file_name, bucket_name, file_name)


if __name__ == '__main__':
    target_url = os.environ['TARGET_URL']
    bucket_name = os.environ['BUCKET_NAME']
    save_screenshot(target_url, bucket_name)

ECRの作成、イメージのプッシュ

スクレイピング用のDockerイメージ保存するためのECRのプライベートリポジトリを作成します。

ECRの作成.png

Dockerイメージをビルドし、ECRリポジトリにプッシュします。

aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin {YOUR_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com
docker build -t web-crawler .
docker tag web-crawler:latest 397693451628.dkr.ecr.ap-northeast-1.amazonaws.com/web-crawler:latest
docker push {YOUR_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/web-crawler:latest

ECS,IAMロールの作成

スクレイピング用のDockerイメージを動かすためのECSクラスター、タスク定義、IAMロールを作成します。

ECSクラスターの作成

ECSクラスターを作成します。

クラスターの作成.png

タスクIAMロールの作成

スクレイピングするタスクを動かすためのIAMロール(タスクロール)を作成します。
スクリーンショットをS3に保存する必要があるのでS3へのファイルアップロードを許可する権限を付与します。(画像中ではFullAccess権限を与えていますが、サンドボックス環境以外では適切な権限を設定してください)
作成した web-crawer-task-role をタスク定義設定時に使用します。

タスクIAMロールの作成1.png

タスクIAMロールの作成2.png

タスクIAMロールの作成3.png

タスク定義の作成

スクレイピング用のタスク定義を作成します。
タスクロールの項に先ほど作成した web-crawer-task-role を設定し、コンテナの詳細欄にはECRのURIを設定します。
料金節約のためCPUとメモリサイズは調整しましたが他はデフォルトの設定を使用します。

タスク定義の作成.png

S3バケットの作成

スクリーンショットを保存するための S3バケットを作成します。
takoikatakotako-web-crawer-bucket という名前で作成しました。

EventBridgeSchedulerの作成

定期実行のためのEventBridgeSchedulerを作成します。
EventBridgeSchedulerを用いて定期的なタスクを実行し、オーバーライドオプションで環境変数の上書きを行います。

EventBridgeSchedulerの作成1.png

EventBridgeSchedulerの作成2.png

{
  "containerOverrides":[
    {
      "name":"ojichat",
      "environment":[
        {
          "name":"TARGET_URL",
          "value":"http://abehiroshi.la.coocan.jp/"
        },
        {
          "name":"BUCKET_NAME",
          "value":"takoikatakotako-web-crawer-bucket"
        }
      ]
    }
  ]
}

EventBridgeSchedulerの作成3.png

EventBridgeSchedulerの作成4.png

阿部寛のHPのスクリーンショットが保存されることを確認します。

詰まったところ

ECSタスクを変更する場合、新しいロールを作成する必要がある

EventBridgeSchedulerで生成されるIAMロールのポリシーにECSタスクのARNが含まれるため、コンソールからECSタスクを更新すると新しいロールを作成する必要があります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecs:RunTask"
            ],
            "Resource": [
                "arn:aws:ecs:ap-northeast-1:397693451628:task-definition/web-crawer-task-definition:*",
                "arn:aws:ecs:ap-northeast-1:397693451628:task-definition/web-crawer-task-definition"
            ],
            "Condition": {
                "ArnLike": {
                    "ecs:cluster": "arn:aws:ecs:ap-northeast-1:397693451628:cluster/web-crawler-cluster"
                }
            }
        }
    ]
    ...
}

デバッグにCloudTrailが必要な場合がある

上手く動かない場合、CloudTrailを使用してデバッグする必要があります。
CloudTrail イベント履歴から RunTask などを確認する必要があります。

CloudTrail.png

0
0
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
0
0