見出し画像

初心者がseleniumを使ってInstagramをエゴサするBotを作るお話(AWS Lambdaデプロイ編)

・はじめに

前回までに出来上がったアプリをLambda用にちょっと直してデプロイしていきます。rubyは最近対応したばかりみたいで、タイミングがいい。

・参考記事

基本的には開発者ガイドに全部あります。

わかりやすい手順も先人がいっぱい書いています。大変参考にしました。

・手順 - Lambda関数作成

AWS マネジメントコンソールにログインした後、リージョンをcloud9と同じものになっているか確認して、Lambdaにアクセスする。

関数の作成をクリックして、名前に好きな名前(ここではinstabot)を入れ、ランタイムをRuby2.5、ロールを"カスタムロールの作成"にする。

カスタムロールの作成を選ぶと新しいタブが立ち上がるので、許可を選ぶとCloudWatch Logsの書き込み権限が付与されたロールができる。

そして関数の作成をクリックすると、Lambda関数が作成されて細かい設定が出来るようになります。

ハンドラを(実行ファイル名).lambda_hundlerと入力します。ここではInstabot.lambda_hundlerとします、関数名と実行ファイル名で大文字小文字が揃ってないのはよくわかってなかったからです。

しばらく回したところ、メモリは1024MBもあれば大丈夫そうです。タイムアウトは1分ちょうどでも問題なさそうですが、なんとなく10秒長くしています。平均実行時間は40秒程度です。

・手順 - Lambda layersの作成

binやgemのサイズが大きすぎるせいでこのままではデプロイできません。Layersを使って分割することでデプロイすることができるようになります。

binフォルダをアップロードするためにzipに圧縮します。

ec2-user:~/environment/instabot $ zip bin -r bin

生成されたbin.zipをレイヤーにアップロードします。

ec2-user:~/environment/instabot $ aws lambda publish-layer-version 
--layer-name chrome 
--description "include binary of serverless-chrome and chromedriver" 
--zip-file fileb://bin.zip --compatible-runtimes ruby2.

(見やすいように余計な改行が入ってます)

・手順 - Botのデプロイ

Lambdaで動くように少しコードに手を加えます。

まずInstabot.rbの実行部分をlambda_handlerメソッドに変更します。

def lambda_handler(event:,context:)
    spreadsheet_id = SPREADSHEET_ID
    range_name = 'master!A1:G'
    username = INSTA_EMAIL
    password = INSTA_PASSWORD
    (略)
end 

次にselenium.rbのinitializeで指定しているbinのパスを変更し、オプションを追加します。(オプションに関しては参考記事からの丸コピで全部必要なのかよくわかっていません。変更しないで試したときにこんな感じのエラー

を吐きましたが、chromedriverとheadless-chromeのバージョンが違うのが悪かったのかオプション設定が悪かったのか検証してないのでわかりません、これで問題なく動いています。)

def initialize(username,password)
    Selenium::WebDriver::Chrome.driver_path="/opt/bin/chromedriver"
    options = Selenium::WebDriver::Chrome::Options.new(binary:"/opt/bin/headless-chromium")
    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 = Selenium::WebDriver.for(:chrome,options: options)
    @driver.get 'https://www.instagram.com/accounts/login/?source=auth_switcher'
    (略)
end

binをレイヤーとして切り分けましたので、それを除いてzipに圧縮します。

ec2-user:~/environment/instabot $ zip -r instabot * -x "bin*" 

gemの影響でこれでもかなりサイズが大きく、インラインコード編集をすることはできませんので、必要であればvendorもレイヤーに分けたほうがいいかもしれません。

できたzipをデプロイします。

ec2-user:~/environment/instabot $ aws lambda update-function-code 
--function-name instabot 
--zip-file fileb://instabot.zip

無事にデプロイできたら、Lambdaコンソールに戻り、レイヤーを追加、トリガーを設定して完了です!

CloudWatch Eventsを選択、新規ルールの作成からスケジュール式を選択して、cronかrate式を書いてあげればよいです。僕は、rate(1 hour)としています。

動いているかはコンソールからCloudWatch Logsを開くと確認できます。初めのうちは動作確認のためにトリガーの間隔を短くして様子を見ていました。うまい確認方法がありそうな気もしますがわからないので、知っていたら教えてください。

・感想

ド素人なのであちらこちらに躓いて苦戦しましたが、なんとか無事に動作するものが作れましたー!ものが出来ると嬉しいですね。嬉しいので頑張って記事も書きましたが、途中で飽きてAtCoderで遊んでばっかりいました。
レートも上がってきました。

おもしろいので今後も頑張ってプログラミングを学習していきたいと思います。

この記事が気に入ったらサポートをしてみませんか?