ChromeとSeleniumをLambdaで動かすAWSに限らない話ですが、クラウドを基盤とするシステムに関わると、自然とAPIベースで必要な情報を取得する機会は多くなります。テキストをパースするよりGUIベースで情報を自動取得したい場合も依然とあり、そちらの方が適しているユースケースは依然と多い、と個人的には感じています。ChromeとSeleniumをLambda関数で動かし、webページのスクリーンショットを取得する方法をご紹介します。Layerで作成し、Lambda関数から使っています。Frameworkを使いました。全体の構成としては、次の通りです。Frameworkの紹介は割愛するため、既に導入済みの環境であることを前提とします。Chrome+WebdriverとSelenium、2つのLayerを作成するために、まずは準備です。Recommendationそれぞれ優れた技術ですが、本記事では説明を割愛します。ヘッドレスモードがリリースされたのは2017年6月。WebDriverは2018年にW3勧告されている仕様で、Seleniumを使う上では重要なコンポーネントです。本記事ではChromeを扱っていますが、Firefoxでもヘッドレスモードは提供されています。ヘッドレスブラウザを自動化する上で必要なものは、”ブラウザの実行バイナリ”と”WebDriver”です。Chromeバイナリは、chromiumのソースコードからあの手この手でビルドすると軽量になります。ビルド済みのものが下記Githubプロジェクトでリリースされていました。感謝しつつ、今回はこちらののリリースからchromiumバイナリをダウンロードして使用します。serverless-chromeChromeのWebdriverはchromedriverという名称ですが、ダウンロードはこちら。Chrome面倒なTipsとして、Chrome本体とChromeDriverの間に互換性の規則があることです。下記ページにある通り、Chromeバージョンのピリオド区切り数字(major,minor,buildの各番号)が一致するChromeDriverでなければ動きません。73.0.3683個人的経験としても、最初はローカルPCでchromedriverを使うスクリプトを動かしていたら、Chrome本体の自動アップデート機能によってchromedriverとの互換性エラーが勝手に発生し、沢山のエラーが出ました。そんなつまらないエラーを回避するためにも、サーバレス環境を一考することは重要だなーと再認識しました。ご参考ブログ:自動バージョンアップスクリプト「chromedriver_update_tool」を公開しましたなお、chromeとchromedriverのバージョンは上記の通りに守りましたが、seleniumはバージョン気にせず導入しても動作しました。PythonLambdaに標準外パッケージを含めたい場合、上記ドキュメント通りのディレクトリ構成にする必要があります。そのため、Seleniumをpipインストールする際は、次のようなコマンドが必要です。"python3.x"は使用するPythonバージョンChromeの実行バイナリ、ChromeDriver、Selenium、それぞれの準備を済ませ、次のようなディレクトリ構成ができました。Layerの作成データ一式の準備は完了したので、あとはデプロイするのみです。serverless.ymlの記述は次の通り。{プロジェクト名}でテンプレートを作成した都合上、Pythonバージョンは”3.6′′の指定で統一しています。Layerが2つ作成されます。Layer作成後に再実行した際です。同じ定義のserverless.ymlであれば、既存のAWSリソースをアップデートする挙動になります。Lambda関数の準備Lambda関数に関しては、準備はないのでコードを作成するだけです。...というわけには行きませんでした。日本人特有のフォント問題に対処する必要があります。いわゆる豆腐問題です。最終的に、”.fonts”ディレクトリをLambdaのパッケージに含めて一緒にデプロイすることで解決しました。フォントディレクトリについては、Linux一般のはなしで、下記ページが参考になりました。ダウンロードページ個人的にはNotoフォントを使用するつもりでしたが、一式のデータサイズがGB単位だったので断念しました。Tofu準備が完了すると、次のようなディレクトリ構成になりました。headless-chrome.pyLambda関数の作成Layerの際と同じく、ymlファイルにデプロイ内容を記述します。timeoutメモリサイズとタイムアウトの値は上積みした方が良いです。ヘッドレスとはいえブラウザを起動するため、オーバーヘッドかかります。packageこちらで”.fonts”ディレクトリを定義します。LayerのARNを指定します。Lambda関数のスクリプト本体は次の通りです。responseos.environ[‘HOME’]OS環境変数HOMEとLambdaの実行ディレクトリを一致させます。指定したほうが安全です。Layerとして作成したchromiumのパスを指定します。Layerとして作成したchromedriverのパスを指定します。url本記事では、は弊社グループウェアのログインページを指定しています。CSSセレクターパス自分のhtml知識が皆無のため、Firefoxの開発者モードに頼り切りました。save_screenshotSelenium仕様により、.pngフォーマットのみサポートされます。serverlessを導入していると、次のようにLambda関数を開発環境から実行することも可能です。Office"}TOFUも解消しました。最後にスクリーンショットを自動取得できるようになると、用途は色々考えられます。Webシステムのリグレッションテストはもとより、あるWebページの情報を通知したいだけでも、テキストより画面をみたほうが理解が早い場合は多いはずです。個人的に今回一番手こずったのは、日本語フォントの文字化け対処でした。普段、意識もしない分野だったので苦戦しましたが、目新しく面白かったです。hintingちなみに、今回使用したchromiumバイナリのように軽量ビルドしたい場合、下記ブログがとても参考になります。興味のある方はどうぞ。