LoginSignup
10

More than 3 years have passed since last update.

AWS Lambdaでselenium×chromeを動かす時の AWS Lambda Layers のつくり方

Last updated at Posted at 2020-09-29

この記事では

AWS Lambdaから、selenium×chromeでブラウザ操作したい時に、
Layer の作り方でハマったので投稿します。

やりたいこと

AWS Lambdaでselenium×chromeを動かしたい。

環境

windows 10 Pro
python 3.7
chromdriver 2.37
headless-chromium 64.0.3282.167

記載しないこと

-AWS lambda の関数作成、呼出方法
-selenium webdriverによるブラウザ操作ができるpythonプログラムの作り方。

つまづいたところ

1.AWS Lambda Layersを作る単位
2.AWS Lambda Layersへの搭載方法と呼び出し方

1.AWS Lambda Layersを作る単位

まず、AWS Lambda Layers とはlamda から共通的に使える共通関数のようなものです。
下記のようにLambda本体から参照される形で呼び出すことができます。
機能の1部を切り出すことで、lambda本体の軽くすることができます。
image.png
軽くすることで、例えば下記のような、モジュール一式の容量が大きすぎるためにコードが表示できないデメリットを回避することができます。
image.png

今回は、python からselenium でchromeDriverで実装したかったので、
以下2点のLayer を作ります。

1.seleniumのライブラリを格納するLayer
2.chromeDriverを格納するLayer

↓Layer の構成
image.png

以下に作り方を記載します。

1.seleniumのライブラリを格納するLayer

1.搭載するライブラリ一式の準備

任意のフォルダで下記コマンドを実行します。
既にpip install selenium をしていると思いますが、
搭載するライブラリを準備する作業なので、実行モジュールとは別の場所で行います。

seleniumモジュールの準備
   pip install -t ./python/lib/python3.7/site-packages selenium

2.以下の構成ができあがります。(windows環境で実施しています。)

image.png

3.zip 圧縮

python フォルダからzip圧縮します。
image.png

4.AWS Lambda Layers の作成

lambdaのコンソール画面から、Layers を新規作成します。
作成時に、3のzipファイルを指定して作成します。
image.png

5.Lambda関数へのLayer追加

Lambda関数から4で作ったLayers を参照設定します。
Layer の設定画面からカスタムレイヤーを選択すると、選択肢に表示されるようになります。
image.png

6.import で呼び出し

lambdaからimport で呼び出します。

import文
from selenium import webdriver

もし、上記構成を間違った場合、下記エラーとなります。

error文
[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'selenium'

2.chromeDriverを格納するLayer

1.driverの準備

公式配布されているdriver (2点)を準備します。
chromdriver 配布元:https://chromedriver.storage.googleapis.com/index.html?path=2.37/
headless-chromium 配布元:https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-37/stable-headless-chromium-amazonlinux-2017-03.zip

2.zip 圧縮

上記2点を同じフォルダに配置し、linux環境でzip 圧縮します。
image.png

もし、windows環境でzip圧縮した場合、lamdaを実行しても下記のエラーとなります。
linux 環境でも、各ファイルのパーミッションが777でないと、下記エラーとなります。

error文
[ERROR] WebDriverException: Message: 'chromedriver' executable may have wrong permissions. Please see https://sites.google.com/a/chromium.org/chromedriver/home

windowsPCの方で、linux 環境でzip圧縮するには、下記方法があります。どちらでもいけました。
1.WSL環境でのzip ※パーミッション777にしておく
2.Docker desktopで適当な環境を作る
(たまたま使っていた、こちらのphp環境を利用しました。 https://hub.docker.com/_/php

3.Lambda関数へのLayer追加

Lambda関数から4で作ったLayers を参照設定します。
※先ほどと同じ手順となります。

4.lambdaから呼出

lambdaから 以下パスを指定して呼びます。
AWS Lambda layersの仕様で、/opt に配置されるため、下記のように指定します。

import文
driver = webdriver.Chrome(executable_path ="/opt/chromedriver", chrome_options=options)

もし、optが無いなどパスを誤った場合、エラーとなります。

error文
[ERROR] WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home

もう一つ注意点

lamda もseleniumも処理が遅いので、lamdaのtimeout値を長めに設定してやります。
デフォルトは、3秒ですので、ほぼtimeoutし、下記のエラーとなります。

error文
Task timed out after XX.XX seconds

timeout値の設定
image.png

実装

lamdaのコードは、最終的に下記となります。

lamda_function.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def lambda_handler(event, context):
    LINE_NOTIFY_URL = "https://notify-api.line.me/api/notify"

    options = Options()
    options.binary_location = '/opt/headless-chromium'
    options.add_argument('--headless')
    options.add_argument('--no-sandbox')
    options.add_argument('--single-process')
    options.add_argument('--disable-dev-shm-usage')

    driver = webdriver.Chrome(executable_path ='/opt/chromedriver', chrome_options=options)
    driver.get("https://xxxxxxxxxxx")

まとめ

他の記事を見ていると、serverless.ymlやcloudFormationを使ったものが多かったのですが、
私はそのあたりの知識が弱かったため、上記方法をとりました。
初めてサーバレスでseleniumを組み込む方の参考になれば幸いです。

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
10