AWS Lambda上のheadless chromeをPythonで動かす

# はじめに
- この記事では、AWS Lambda上でheadless chromeをPythonで動かす方法を紹介します。
- [AWS Lambda](https://aws.amazon.com/jp/lambda/)と[docker](https://www.docker.com/)を使うので、導入してあることを前提とします。
- 今回書いたコードは[https://github.com/nabehide/lambda_headless_chrome_python](https://github.com/nabehide/lambda_headless_chrome_python)にあげました。
- Lambdaにデプロイするファイルの作成はMac OS上で行いました。
- 以下、適当なフォルダを作成して、その中で作業していきます。

```shell

$ mkdir lambda_headless_chrome_python
$ cd lambda_headless_chrome_python
```

* もしくは、githubからサンプルコードをクローンしてきてください。

```shell
$ git clone https://github.com/nabehide/lambda_headless_chrome_python.git
$ cd lambda_headless_chrome_python
```

# 手順
## lambda_function.py 作成
- googleにアクセスして、ページのタイトルを取ってくるだけの操作をやってみます。

```python:lambda_function.py

from selenium import webdriver


def lambda_handler(event, context):
    options = webdriver.ChromeOptions()

    # のちほどダウンロードするバイナリを指定
    options.binary_location = "./bin/headless-chromium"

    # headlessで動かすために必要なオプション
    options.add_argument("--headless")
    options.add_argument("--disable-gpu")
    options.add_argument("--window-size=1280x1696")
    options.add_argument("--disable-application-cache")
    options.add_argument("--disable-infobars")
    options.add_argument("--no-sandbox")
    options.add_argument("--hide-scrollbars")
    options.add_argument("--enable-logging")
    options.add_argument("--log-level=0")
    options.add_argument("--single-process")
    options.add_argument("--ignore-certificate-errors")
    options.add_argument("--homedir=/tmp")

    driver = webdriver.Chrome(
        "./bin/chromedriver",
        chrome_options=options)
    driver.get("https://www.google.co.jp")
    title = driver.title
    driver.close()
    return title
```

## serverless-chromiumのダウンロード
- [serverless-chrome](https://github.com/adieuadieu/serverless-chrome/releases) というLambda上で動くheadless-chromiumを使わせていただきます。
- 最新版はPythonで動かない（2018年4月27日現在 [[参照](https://github.com/adieuadieu/serverless-chrome/issues/133)]）ため、[v1.0.0-37](https://github.com/adieuadieu/serverless-chrome/releases/tag/v1.0.0-37)を入れます。

```shell

$ mkdir -p bin/
$ curl -SL https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-37/stable-headless-chromium-amazonlinux-2017-03.zip > headless-chromium.zip
$ unzip headless-chromium.zip -d bin/
$ rm headless-chromium.zip
```

## chromedriverのダウンロード
- 上でダウンロードしたChromiumのバージョンに対応したchromedriverのバージョン([2.37](https://chromedriver.storage.googleapis.com/index.html?path=2.37/))を選んでダウンロードします。

```
$ curl -SL https://chromedriver.storage.googleapis.com/2.37/chromedriver_linux64.zip > chromedriver.zip
$ unzip chromedriver.zip -d bin/
$ rm chromedriver.zip
```

## seleniumのダウンロード
- seleniumなど、pipでインストールするパッケージは、Lambdaにアップロードするファイルに含まれていないといけません。
- しかし、例えばMacの環境でpipを使うと、Mac環境で実行可能なファイルがダウンロードされることになります。
- そこで、Amazon Linux2で実行可能なものをダウンロードするために、dockerを使います。
- [lambda/lambci](https://hub.docker.com/r/lambci/lambda/~/dockerfile/) という、Lambdaの環境にPythonが入ったものを使わせていただきます。
- 下記のDockerfileを作成します。

``` Dockerfile:Dockerfile
FROM lambci/lambda:build-python3.6

ENV AWS_DEFAULT_REGION ap-northeast-1
ENV APP_DIR /var/task

ADD . .

CMD pip install -r requirements.txt -t $APP_DIR && \
  zip -9 deploy_package.zip lambda_function.py && \
  zip -r9 deploy_package.zip *
```

- docker image を作成して、パッケージングします。

```shell
$ docker build -t lambda_headless_chrome .
$ docker run -v "${PWD}":/var/task lambda_headless_chrome
```

- これでlambdaにアップロードするzipファイル deploy_package.zipができます。

## Lambdaで実行する
- AWSコマンドラインインターフェース(CLI)を導入していない場合は、下記コマンドで導入します。

```shell
$ pip install awscli
```

- 下記コマンドでapiキーなども設定しておきます。

```
$ aws configure
```

- AWSコンソールでS3のバケットとroleを作成します。roleのpolicyに AWSLambdaFullAccess をアタッチしておきます。
- deploy_pakcage.zipをLambdaにアップロードして、関数を作成します。（リージョンやロール、バケットの名前などは適宜変えて実行します。）

```shell
$ aws s3 cp deploy_package.zip s3://YOUR_BUCKET_NAME
$ aws lambda create-function --region ap-northeast-1 --function-name lambda_headless_chrome_python --runtime python3.6 --role YOUR_ROLE_NAME --code S3Bucket=YOUR_BUCKET_NAME,S3Key=deploy_package.zip --handler lambda_function.lambda_handler --memory-size 512 --timeout 300
```

- lambdaにアクセスすると、lambda_headless_chrome_python という関数ができているので、「テスト」ボタンで実行確認ができます。

# さいごに
AWS Lambda上でheadless chromeをPythonで動かす方法を書きました。
あとはlambda_function.pyを好きなように書いて、requirements.txtに必要なパッケージを追加して、実行するだけです！