AWS Lambda에서 스크린샷을 찍고 S3에 저장

소개



이 기사는 mohikanz Advent Calendar 2019의 11 일째 기사입니다.
작년은 마이크로 컴퓨터 자료 였습니다.
올해는 AWS에서 평소 편리하게 사용해 주는 기술 자료에 대해 씁니다.

한 프로젝트에서 웹 사이트를 정기적으로 캡처하고 S3에 저장해 두고 싶다고 말하는 것이 있고, 그렇다면 서버리스로 도전해 보려고 말하게 되고, 그것을 해 보았을 때의 기사가 됩니다.
Lambda는 편리합니다. 무엇보다 싸고.

필요한 지식


  • Python
  • AWS Lambda
  • Selenium

  • 사전 준비



    헤드리스 크롬을 사용하므로 몇 가지 사전 준비가 필요합니다.

    Lambda Layers



    Lambda의 파일 크기 한도에 걸리므로 Lambda Layers에 headless chrome을 준비합니다.
    GitHub에 놓아 두었으므로, 자유롭게 사용해 주세요.
    Lambda Layers는 관리 콘솔에서 업로드할 수 있습니다.

    일본어 글꼴



    IPAex 폰트가 있으면 문자화되지 않으므로, 미리 다운로드해 주세요../fonts 디렉토리에 저장하십시오.
    Lambda Layers에 포함시키면 50MB를 넘어 버리므로, Lambda쪽에 추가합니다.

  • 2 서체 팩 (IPAex 명조 (Ver.002.01), IPAex 고딕 (Ver.002.01))

  • Lambda 만들기



    Serverless Framework를 사용하여 빌드합니다.
    $ sls create --template aws-python3 --path headless-chrome
    

    serverless.yml
    service: headless-chrome
    
    provider:
      name: aws
      runtime: python3.6
      memorySize: 1600
      timeout: 120
      stage: ${opt:stage, 'dev'}
      region: ap-northeast-1
      # 権限設定
      iamRoleStatements:
        - Effect: "Allow"
          Action:
            - "s3:GetObject"
            - "s3:PutObject"
          Resource: "arn:aws:s3:::headless-chrome-${self:provider.stage}/*"
    functions:
     chrome: 
        handler: chrome.lambda_handler
        description: Headless Chrome
        environment:
          TZ: Asia/Tokyo
          STAGE: ${self:provider.stage}
          S3BUCKET: headless-chrome-${self:provider.stage}
        package:
          # フォントを追加する
          include: 
            - '.fonts/**' 
        layers: 
          - arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:layer:headless_chrome_python360:1
    

    Lambda 소스 코드

    chrome.py
    from selenium import webdriver
    import boto3
    import json
    import os
    import time
    
    
    os.environ['HOME'] = '/var/task'
    
    
    def lambda_handler(event, context):
        options = webdriver.ChromeOptions()
        options.add_argument("--headless")
        options.add_argument("--disable-gpu")
        # options.add_argument("--window-size=3408x2156")
        options.add_argument("--window-size=1704x1078")
        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("--v=99")
        options.add_argument("--single-process")
        options.add_argument("--ignore-certificate-errors")
        options.add_argument("--homedir=/tmp")
    
        options.binary_location = "/opt/bin/headless-chromium"
    
        bucket = os.environ.get("S3BUCKET", "")
        s3 = boto3.client('s3')
        driver = webdriver.Chrome(
            "/opt/bin/chromedriver", chrome_options=options)
        driver.get("https://www.google.co.jp")
    
        time.sleep(5)
        driver.save_screenshot("/tmp/shot.png")
        driver.close()
    
        s3.upload_file(Filename="/tmp/shot.png",
                       Bucket=bucket,
                       Key="hoge.png")
        return "ok"
    

    실행해 보았습니다.


    $ sls deploy -v
    $ sls invoke -f chrome
    

    이런 느낌이 들었습니다.



    사이고에게



    Selenium을 잘 다룰 수 있는 사람은 CI/CD에 짜넣거나 해 보면, 릴리스의 동작 확인까지 할 수 버리므로, 꿈이 퍼지네요.
    chrome은 file 프로토콜도 사용할 수 있으므로, 로컬에 둔 파일(Lambda가 움직이고 있는 실행 환경)을 사용할 수도 있습니다.

    좋은 웹페이지 즐겨찾기