Lambda」タグアーカイブ

AWS Lambda 入門~おすすめ本5冊の紹介~

概要〜サーバレス基礎からAmplifyを使った本格開発までのおすすめ書籍〜

最近、AWS Lambdaの本増えてきましたよね。ということで今回はLambdaのおすすめ本の紹介です。

基礎編から本格的な専門書、アーキテクト、実際にAmplifyを使った開発と徐々にレベルアップする内容になっているのでLambdaを学びたい人は一つずつ読んでいってみてください。

Lambdaおすすめ本 5冊

今回紹介するAWS Lambdaのおすすめ本の一覧です。
忙しい方はここだけ確認してください。

基礎から学ぶ サーバーレス開発

基礎から学ぶ サーバーレス開発

まずは基本編です。Lambdaというかサーバレスとは?という導入編です。サーバレスとはどういうものか丁寧に書かれています。まずはサーバでの開発と比較してサーバレスにはどういったメリットデメリットがあるのかこの本で学びましょう。

目次

  • CHAPTER 01 サーバーレスとは
    • 1 サーバーレスの概要
    • 2 サーバーレスが注目された要因と新たなる課題
    • 3 サーバーレスのメリット・デメリット
  • CHAPTER 02 サーバーレス開発でよく使うサービス
    • 4 AWS Lambda
    • 5 Amazon API Gateway
    • 6 Amazon Aurora Serverless
    • 7 Amazon CloudWatch
    • 8 Amazon Simple Queue Service (Amazon SQS)
    • 9 AWS CodeCommit
    • 10 AWS CodePipeline
    • 11 AWS CodeBuild
    • 12 AWS CodeDeploy
    • 13 Amazon Simple Storage Service (Amazon S3)
    • 14 AWS Step Functions
    • 15 Amazon DynamoDB
    • 16 AWS Cloud9
    • 17 AWS X-Ray
  • CHAPTER 03 サーバーレスアプリケーションの構築
    • 18 フレームワーク
    • 19 CI/CD
    • 20 AWSにおけるCI/CD
    • 21 デプロイ手法
    • 22 トラフィックシフト
    • 23 昇格
  • CHAPTER 04 サーバーレスの運用監視
    • 24 サーバーレスのコスト
    • 25 サーバーレスにおける監視
  • CHAPTER 05 サーバーレス開発におけるセキュリティ
    • 26 サーバーレス開発におけるセキュリティの考え方
    • 27 Lambda@Edgeの利用
  • CHAPTER 06 サーバーレスの構築例
    • 28 完全サーバーレスでのWebページ構築事案
    • 29 完全サーバーレスでのWebページのバッチ部分
    • 30 APIバックエンドにAmazon RDSを用いた事例および2019年のアップデートについて
    • 31 サーバーレスで作る在宅勤務中の勤務時間登録システム
    • 32 AWS LambdaをAlexaのエンドポイントとして使う事例
  • CHAPTER 07 サーバーレスの失敗談と問題解決
    • 33 失敗談①~Amazon RDSを起動させ続けた
    • 34 失敗談②~AWS Lambda でスロットリングが発生してしまった
    • 35 SPA+サーバーレスで再読み込みをするとAccessDeniedになってしまう問題の解決方法

AWSではじめる クラウド開発入門

AWSではじめる クラウド開発入門

東大の人気授業が書籍化された内容です。Lambdaに限らずクラウド開発入門という位置付けなのでいろんな開発内容が書かれていて、クラウドでこうやって開発するんだとわかる内容になってます。最後の方は、かなり実践的で勉強になります。

目次

  • Chapter 1 はじめに
    • 1-1 本書の目的内容
    • 1-2 本書のフィロソフィー
    • 1-3 AWS アカウント
    • 1-4 環境構築
    • 1-5 前提知識
    • 1-6 本書で使用する表記について
  • Chapter 2 クラウド概論
    • 2-1 クラウドとは?
    • 2-2 なぜクラウドを使うのか?
  • Chapter 3 AWS入門
    • 3-1 AWSとは?
    • 3-2 AWSの機能・サービス
    • 3-3 Region と Availability Zone
    • 3-4 AWSでのクラウド開発
    • 3-5 CloudFormationとAWS CDK
  • Chapter 4 Hands-on #1:初めてのEC2インスタンスを起動する
    • 4-1 準備
    • 4-2 SSH
    • 4-3 アプリケーションの説明
    • 4-4 プログラムを実行する
    • 4-5 小括
  • Chapter 5 Hands-on #2: AWS でディープラーニングを実践
    • 5-1 なぜ機械学習をクラウドで行うのか?
    • 5-2 GPU による深層学習の高速化
    • 5-3 準備
    • 5-4 アプリケーションの説明
    • 5-5 スタックのデプロイ
    • 5-6 ログイン
    • 5-7 Jupyter Notebook の起動
    • 5-8 PyTorch はじめの一歩
    • 5-9 実践ディープラーニング! MNIST手書き数字認識タスク
    • 5-10 スタックの削除
  • Chapter 6 Docker 入門
    • 6-1 クラウドシステムの構築に向けて
    • 6-2 機械学習の大規模化
    • 6-3 Docker とは
    • 6-4 Docker チュートリアル
    • 6-5 Elastic Container Service (ECS)
  • Chapter 7 Hands-on #3 : AWS で自動質問回答ボットを走らせる
    • 7-1 Fargate
    • 7-2 準備
    • 7-3 Transformer を用いた question-answering プログラム
    • 7-4 アプリケーションの説明
    • 7-5 スタックのデプロイ
    • 7-6 タスクの実行
    • 7-7 タスクの同時実行
    • 7-8 スタックの削除
  • Chapter 8 Hands-on #4: AWS Batch を使って機械学習のハイパーパラメータサーチを並列化する
    • 8-1 クラウドを用いた機械学習モデルの最適化
    • 8-2 AWS Batch
    • 8-3 準備
    • 8-4 MNIST 手書き文字認識(再訪)
    • 8-5 アプリケーションの説明
    • 8-6 スタックのデプロイ
    • 8-7 Docker image を ECR に配置する
    • 8-8 単一のジョブを実行する
    • 8-9 並列に複数の Job を実行する
    • 8-10 スタックの削除
    • 8-11 クラウドを用いた機械学習アプリケーションの開発とデバッグ
    • 8-12 小括
  • Chapter 9 ウェブサービスの作り方
    • 9-1 個人のためのクラウドからみんなのためのクラウドへ
    • 9-2 ウェブサービスの仕組み Twitter を例に
    • 9-3 REST API
    • 9-4 Twitter API
  • Chapter 10 Serverless architecture
    • 10-1 Serverful クラウド (従来型)
    • 10-2 Serverless クラウドへ
    • 10-3 サーバーレスクラウドを構成するコンポーネント
  • Chapter 11 Hands-on #5: サーバーレス入門
    • 11-1 Lambda ハンズオン
    • 11-2 DynamoDB ハンズオン
    • 11-3 S3 ハンズオン
  • Chapter 12 Hands-on #6: Bashoutter
    • 12-1 準備
    • 12-2 アプリケーションの説明
    • 12-3 アプリケーションのデプロイ
    • 12-4 API リクエストを送信する
    • 12-5 大量のAPIリクエストをシミュレートする
    • 12-6 Bashoutter GUI を動かしてみる
    • 12-7 アプリケーションの削除
    • 12-8 小括
  • Chapter 13 Hands-on #7: boto3 道場
    • 13-1 boto3 の基本
    • 13-2 S3 道場
    • 13-3 DynamoDB 道場
    • 13-4 小括
  • Chapter 14 Hands-on #8: シン・Bashoutter
    • 14-1 シン・Bashoutter プロジェクトの概要
    • 14-2 STEP1:ドメインの設定とCloudFront の配置
    • 14-3 STEP2:Cognito によるユーザー認証の追加
  • Chapter 15 Hands-on #9: 深層学習を用いたアート自動生成アプリケーション
    • 15-1 Neural Art Canvas プロジェクト
    • 15-2 Neural style transfer
    • 15-3 ローカルで Neural style transfer を実行
    • 15-4 Step Functions
    • 15-5 Lambda layers
    • 15-6 アプリケーションの説明
    • 15-7 アプリケーションのデプロイ
    • 15-8 画像の生成 (コマンドラインから)
    • 15-9 画像の生成 (GUIから)
    • 15-10 アプリケーションの削除
  • Appendix 環境構築
    • A-1 本書で必要な計算機環境
    • A-2 AWS アカウントの取得
    • A-3 AWS のシークレットキーの作成
    • A-4 AWS CLI のインストール
    • A-5 AWS CDKのインストール
    • A-6 WSL のインストール
    • A-7 Docker のインストール
    • A-8 Python venv クイックガイド
    • A-9 ハンズオン実行用の Docker image の使い方

AWS Lambda実践ガイド 第2版 impress top gearシリーズ

AWS Lambda実践ガイド 第2版

ここからがLambdaの本格化書籍です。まずはLambdaの専門書といったらこれという一冊です。人気本で第二版も発売されてます。Lambdaの基礎からSAMを使った本格化開発まで記載されている良書です。Lambdaの専門書としてまずはこの本をおさえた方が良い内容になってます。

基本を抑えつつ現場で役に立つバージョン管理やエイリアスといった運用面の記載や、コールドスタートやコネクションなど現場で知っておかなければならない制限事項についても書かれており、本当にLambdaと言ったらこれという良書だと思います。

目次

  • 第1章 Lambda で実現するサーバーレスシステム
  • 第2章 Lambda 事始め
  • 第3章 Lambda の実行環境とイベント
  • 第4章 Lambda の開発環境と SAM
  • 第5章 S3 のイベント処理
  • 第6章 API Gateway、DynamoDB、SES との連携
  • 第7章 SQS やSNS を使った連携

AWSによるサーバーレスアーキテクチャ

AWSによるサーバーレスアーキテクチャ

アーキテクト部分からの一冊です。サーバレスアーキテクチャの本ということですが、Lambdaの解説書になっているのでLambdaの専門書という一面もあります。基礎からアーキテクトまで書かれていて参考になります。

目次

  • 第1部 導入
    • 第1章 サーバーレスの世界へ
      • 1.1 ここに至るまでの流れ
      • 1.2 サーバーレスアーキテクチャの原則
      • 1.3 サーバーからサーバーレスへの乗り換え
      • 1.4 サーバーレスの長所と短所
      • 1.5 まとめ
    • 第2章 アーキテクチャとパターン
      • 2.1 ユースケース
      • 2.2 アーキテクチャ
      • 2.3 パターン
      • 2.4 まとめ
    • 第3章 サーバーレスアプリケーションの構築
      • 3.1 24-Hour Video
      • 3.2 Amazon SNS の設定
      • 3.3 動画ファイルのアクセス権限の設定
      • 3.4 メタデータの生成
      • 3.5 仕上げ
      • 3.6 演習問題
      • 3.7 まとめ
    • 第4章 クラウドの設定
      • 4.1 セキュリティモデルとID管理
      • 4.2 ログとアラート
      • 4.3 料金
      • 4.4 演習問題
      • 4.5 まとめ
  • 第2部 コア機能
    • 第5章 認証と認可
      • 5.1 サーバーレス環境における認証
      • 5.2 24-Hour Videoへの認証の追加
      • 5.3 AWS との統合
      • 5.4 委任 トークン
      • 5.5 演習問題
      • 5.6 まとめ
    • 第6章 オーケストレーターとしての AWS Lambda
      • 6.1 AWS Lambdaの内部
      • 6.2 プログラミングモデル
      • 6.3 バージョニング、エイリアス、環境変数
      • 6.4 CLI の使い方
      • 6.5 AWS Lambdaのパターン
      • 6.6 Lambda関数のテスト
      • 6.7 演習問題
      • 6.8 まとめ
    • 第7章 Amazon API Gateway
      • 7.1 インターフェイスとしてのAmazon API Gateway
      • 7.2 Amazon API Gateway の操作
      • 7.3 ゲートウェイの最適化
      • 7.4 ステージとバージョン
      • 7.5 演習問題
      • 7.6 まとめ
  • 第3部 アーキテクチャの拡張
    • 第8章 ストレージ
      • 8.1 賢いストレージ
      • 8.2 セキュアなアップロード
      • 8.3 ファイルへのアクセス制限
      • 8.4 演習問題
      • 8.5 まとめ
    • 第9章 データベース
      • 9.1 Firebase 入門
      • 9.2 24-Hour VideoへのFirebase の追加
      • 9.3 ファイルへのアクセスの保護
      • 9.4 演習問題
      • 9.5 まとめ
    • 第10章 仕上げの学習
      • 10.1 デプロイとフレームワーク
      • 10.2 よりよいマイクロサービスのために
      • 10.3 AWS Step Functions
      • 10.4 AWS Marketplaceが開くビジネスチャンス
      • 10.5 これからの展開のために
  • 付録A サーバーレスアーキテクチャのためのサービス
    • A.1 Amazon API Gateway
    • A.2 Amazon SNS (Simple Notification Service)
    • A.3 Amazon 53 (Simple Storage Service)
    • A.4 Amazon SQS (Simple Queue Service)
    • A.5 Amazon SES (Simple Email Service)
    • A.6 Amazon RDS (Relational Database Service) & Amazon DynamoDB
    • A.7 Amazon CloudSearch
    • A.8 Amazon Elastic Transcoder
    • A.9 Amazon Kinesis Data Streams
    • A.10 Amazon Cognito
    • A.11 Auth0
    • A.12 Firebase
    • A.13 その他のサービス
  • 付録B インストールとセットアップ
    • B.1 システムの準備
    • B.2 IAM ユーザーとCLI のセットアップ
    • B.3 ユーザーアクセス権限の設定
    • B.4 新しいS3バケットの作成
    • B.5 IAMロールの作成
    • B.6 Lambda関数のための準備
    • B.7 Amazon Elastic Transcoder の設定
    • B.8 npm のセットアップ
  • 付録C 認証と認可について
    • C.1 認証と認可の基本
    • C.2 JWT
  • 付録D AWS Lambdaの内部
    • D.1 実行環境
    • D.2 制限
    • D.3 古いランタイムの扱い方
  • 付録 E モデルとマッピング
    • E.1 動画リストの取得
  • 付録 F Amazon S3のイベントメッセージ構造
    • F.1 S3 イベントメッセージの構造
    • F.2 覚えておくべきこと
  • 付録 G Serverless Framework & AWS SAM
    • G.1 Serverless Framework
    • G.2 AWS SAM
    • G.3 まとめ

AWS Amplify Studioではじめるフロントエンド+バックエンド統合開発

AWS Amplify Studioではじめるフロントエンド+バックエンド統合開発

最後はより実践編という位置付けでAmplifyを使った開発の内容の本にしました。Lambdaの基礎ではないため、これまでの本で基礎をおさえつつ再度のAmplifyでアプリ開発の本格入門という位置付けの本のしています。Amplify自体いろんな機能があって覚えることがたくさんなのですが、それら丁寧に解説してくれる内容になってます。

Lambdaの真価が問われるのはバックエンドとしてフロントエンドから連携されたアプリだと思っており、それを簡単に実現してくれるAmplifyには個人的には非常に期待しています。本の内容としては、Amplifyの一機能としてLambdaの使用方法を説明した内容になるのでLambdaに特化した内容ではないのですが、実業務でのLambdaで完結することはあまりないと思うで、一番実践に近い本だと思っています。

目次

  • Chapter1 AWS Amplifyを使おう
    • 1.1. AWS Amplifyを準備する
    • 1.2. サンプルアプリを作成する
  • Chapter2 Amplify Studioでバックエンドを設計する
    • 2.1. Reactアプリケーションの作成
    • 2.2. Amplify Studioとユーザー認証
    • 2.3. データモデルの設計
  • Chapter3 FigmaによるUI設計
    • 3.1. Figmaの基本操作
    • 3.2. Figmaでデザインする
    • 3.3. グラフィックの作成
    • 3.4. データモデル用のコンポーネントの利用
  • Chapter4 Reactによるフロントエンド開発
    • 4.1. Reactアプリケーションの基本
    • 4.2. Reactコンポーネントの設計
    • 4.3. ステートフックと副作用フック
    • 4.4. Reactコンポーネントを活用する
  • Chapter5 DataStoreによるデータベースアクセス
    • 5.1. コレクションコンポーネントの利用
    • 5.2. ReactとDataStoreの利用
    • 5.3. モデルデータの操作
  • Chapter6 GraphQLによるデータの利用
    • 6.1. Amplify MockとGraphQL
    • 6.2. コードからGraphQLを利用する
    • 6.3. GraphQLによるデータの書き換え
  • Chapter7 S3ストレージとLambda関数
    • 7.1. Amazon S3の利用
    • 7.2. ファイルの基本操作
    • 7.3. Lambda関数の利用
    • 7.4. LambdaからAWSの機能を使う
  • Chapter8 JavaScriptベースによるフロントエンド開発
    • 8.1. JavaScriptベースのアプリケーション作成
    • 8.2. Amplifyの機能を利用する

LINE Messaging API を使ってAWS Lambdaに連携する

概要

最近、LINE Messaging API x AWS Lambda x Google スプレッドシート を連携してサクッと便利ツールを作っている日々です♪
個人的にサクッと作れる便利ツールとして、UILINE Messaging APIにして、ロジックAWS Lambdaに、DBGoogle スプレッドシートで作るという構成が簡単に出来て気に入っています。

そこで今回はLINE Messaging API x AWS Lambda の連携編になります。
LINE Messaging API と AWS Lambda をWebhookを使ってHTTPSで連携します。
LINE Developersアカウントがあれば誰でも簡単・無料で出来るので、気になった人はやってみてください。

Lambdaの良書が増えてきたので、おすすめ本5冊を以下で紹介しています。Lambdaについて本格的に勉強したい方はぜひ読んでみてください。

AWS Lambdaおすすめ書籍5冊の紹介

前提条件

  • LINE Developersアカウント(LINE Business ID)取得
    • 無料で作成できるのでアカウントがない人は取得しましょう。
  • AWS Lambda関数の HTTP(S) エンドポイント割り当て
    • LINEからLambdaに連携するために、Lambda関数にHTTP(S) エンドポイントが必要になります。Lambdaを作成する際に、関数 URL を有効化する方法が簡単ですが、アクセス制御はしっかり行ってHTTP(S) エンドポイントを公開しましょう。

公式ページ

Messaging APIを始めよう
https://developers.line.biz/ja/docs/messaging-api/getting-started/

LINE Developersにログイン

まずは、LINEにログインします。
LINE Developersアカウント(LINE Business ID)を作成していない人はアカウントを作成から作成します。

https://account.line.biz/login

プロバイダー/チャネル作成 

ログイン後、LINE DevelopersコンソールというLINEの画面でプロバイダーチャネルを作成します。

  • プロバイダー:サービスを提供し、ユーザーの情報を取得する開発者個人、企業、または団体等のことです。個人で運用する場合は自由に登録すれば良いと思います。
  • チャネル:LINEが提供する機能を、サービス提供者が利用するための通信路です。今回の場合は、AWS Lambdaと LINE Messaging API を使って連携するLINEアプリのことです。

参考ページ
https://developers.line.biz/ja/docs/line-developers-console/overview/

プロバイダー作成

それではプロバイダーから作成していきます。
LINE Developersコンソールの画面操作だけで作成できるので簡単です。

LINE Developersコンソールにログイン後、表示される左メニューのプロバイダーを選択しし、プロバイダーの作成を選択します。

作成画面が表示されるため、任意のプロバイダー名を入力し、作成ボタンで作成されます。
簡単ですね。

チャネル作成

続いてチャネルの作成に移ります。
こちらもLINE Developersコンソールの画面操作だけで作成できます。

プロバイダーを選択する(今回は、AWS Lambdaとの連携が目的なのでLambdaProviderというプロバイダーを作成しています)と、チャネルの設定画面が表示されるため、AWS Lambdaと連携する Messaging API をクリックします。

チャネルの種類Messaging API になっていること、プロバイダー作成したプロバイダーになっていることを確認しましょう。あとは、必須項目を自身の情報で入力すれば大丈夫です。
利用規約を確認して、作成ボタンを押しましょう。

チャネル設定

無事にチャネルが作成されたらチャネルの設定に移ります。
この設定作業でAWS Lambdaとの連携情報認証情報LINEアプリの応答メッセージの設定などを行います。

作成したチャネルを選択します。(今回は、MessagingLambdaというチャネル名で作成しています)

Messaging API設定をクリックします。

ページ中央にあるWebhook URLに連携するAWS Lambdaの公開されたURLを編集ボタンを押して設定します。

URLを設定すると、検証ボタンやWebhookの利用Webhookの再送エラーの統計情報の設定ができるようになるので、必要な設定を行います。
Webhookの利用は必ず必要になるので、必ずONにします。

ページ下部にあるチャネルアクセストークンを設定します。
LambdaからこのLINEアプリに連携する際に指定するキーになる情報なので外部に漏れないないように管理しましょう。

応答/あいさつメッセージのカスタマイズ

ページ中央部にある応答メッセージあいさつメッセージ編集ボタンからこのLINEアプリにメッセージを送った時の応答メッセージLINEアプリを友だち追加した時のあいさつメッセージを編集できます。必要であれば編集しましょう。

編集ボタンをクリックすると以下の応答設定用の専用画面が表示されるため、専用画面で設定を変更します。

今回、AWS Lambdaから応答メッセージを自動作成して送信予定のため、応答メッセージオフに設定します。

AWS Lambdaの実装

いよいよここからはAWS Lambda側の実装になります。
前提条件のところに書きましたが、LINEと連携するためHTTP(S) エンドポイントが公開されているLambda関数の使用が前提になります。
今回は、最も基本的なLINEからLambdaにメッセージを送った時にLambdaからLINEへの応答メッセージを送る方法と、LambdaからLINEへプッシュメッセージを送る方法を記載します。

応答メッセージを送る

LINEからLambdaにメッセージを送った時に送られたメッセージをもとにして応答メッセージを送信するAPIは以下になります。

https://developers.line.biz/ja/reference/messaging-api/#send-reply-message

具体的には以下のhttpsリクエストを応答メッセージとして送信する必要があります。

curl -v -X POST https://api.line.me/v2/bot/message/reply \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {channel access token}' \
-d '{
    "replyToken":"{Reply token}",
    "messages":[
        {
            "type":"text",
            "text":"Hello, user"
        },
        {
            "type":"text",
            "text":"May I help you?"
        }
    ]
}'

  • channel access token:LINE Developersコンソールで発行したチャネルアクセストークンを設定します。
  • Reply token:メッセージのやり時の度にLINEからLambdaに送られたリクエストメッセージの中からReply tokenを取得して設定します。

LINEから送られてくるリクエストメッセージのReply tokenの具体例は以下になります。replyToken部から取得しましょう。
text部にLINEから送られてくるメッセージが格納されており、userId部がLINEの送信者を特定するIDになります。(userIdは次の「プッシュメッセージを送る」で使用します)

{
  "destination": "xxxxxxxxxx",
  "events": [
    {
      "type": "message",
      "message": {
        "type": "text",
        "id": "14353798921116",
        "text": "Hello, world"
      },
      "timestamp": 1625665242211,
      "source": {
        "type": "user",
        "userId": "U80696558e1aa831..."
      },
      "replyToken": "{Reply token}",
      "mode": "active",
      "webhookEventId": "01FZ74A0TDDPYRVKNK77XKC3ZR",
      "deliveryContext": {
        "isRedelivery": false
      }
    }
  ]
}

実際にLambdaで replyToken を取得して、応答メッセージを送信するサンプルは以下になります。

import json
import requests
from pprint import pprint

def lambda_handler(event, context):
    #=========================
    # LINEからのリクエスト解析
    #=========================
    bodyjson = json.loads(event['body'])
    messagetext = bodyjson['events'][0]['message']['text']
    print("messagetext: " + messagetext)
    replyToken = bodyjson['events'][0]['replyToken']
    print("replyToken: " + replyToken)

    #=========================
    # LINEへのレスポンス作成
    #=========================
    resmessage = [
        {'type':'text','text':messagetext}
    ]
    payload = {'replyToken': replyToken, 'messages': resmessage}
    # カスタムヘッダーの生成(dict形式)
    headers = {'content-type': 'application/json', 'Authorization': 'Bearer XXX'}
    # headersにカスタムヘッダーを指定
    r = requests.post("https://api.line.me/v2/bot/message/reply", headers=headers, data=json.dumps(payload))
    print("LINEレスポンス:" + r.text)
    return

LINEから送られてきたメッセージをそのまま送り返すサンプルになっています。
LINEからのメッセージと replyToken を取得して、応答メッセージ用のhttpsリクエストに設定して送信すればOKです。簡単ですね。

プッシュメッセージを送る

次はLambdaからLINEにプッシュメッセージを送るAPIは以下になります。

https://developers.line.biz/ja/reference/messaging-api/#send-push-message

具体的には以下のhttpsリクエストを送信することでプッシュメッセージを送ることができます。

curl -v -X POST https://api.line.me/v2/bot/message/push \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {channel access token}' \
-d '{
    "to": "{user id}",
    "messages":[
        {
            "type":"text",
            "text":"Hello, world1"
        },
        {
            "type":"text",
            "text":"Hello, world2"
        }
    ]
}'

  • channel access token:LINE Developersコンソールで発行したチャネルアクセストークンを設定します。
  • user id:プッシュメッセージを送りたい相手の userId を設定します。(userId は「応答メッセージを送る」で確認したLINEからメッセージが送られてきた時のリクエスト内容から確認できます)

実際にLambdaでプッシュメッセージを送信するサンプルは以下になります。

import json
import requests
from pprint import pprint

def lambda_handler(event, context):
    #===========================
    # LINEへのPUSHメッセージ作成
    #===========================
    resmessage = [
        {'type':'text','text':'メッセージ1'},
        {'type':'text','text':'メッセージ2'}
    ]
    payload = {'to': 'XXX', 'messages': resmessage}
    # カスタムヘッダーの生成(dict形式)
    headers = {'content-type': 'application/json', 'Authorization': 'Bearer XXX'}
    # headersにカスタムヘッダーを指定
    r = requests.post("https://api.line.me/v2/bot/message/push", headers=headers, data=json.dumps(payload))
    print("LINEレスポンス:" + r.text)
    return
  • ['to': 'XXX']:プッシュメッセージを送りたい相手の userId を設定します。
  • [Bearer XXX]:LINE Developersコンソールで発行したチャネルアクセストークンを設定します。

送信先のuserIdとチャネルアクセストークンを設定するだけになります。こちらも簡単ですね。

まとめ

今回は、LINE Messaging API x AWS Lambda の連携編を説明しました。
基本的にはLINE Developersコンソール上の設定作業がメインで、Lambda上の実装はMessaging API のリファレンス通りやるだけなので比較的簡単にできたのではないでしょうか。
これで何かあったらLINEにメッセージを送るとツールを動かせたり、定期的にLambdaを起動してLINEにメッセージを送ったりできるので簡単なツールだったら自分でサクッと作ってしまおうかなと思って個人的には気に入っている方法になります。
興味がある方がいたらぜひやってみてください。

AWS Lambda で Python プログラミング~Boto3 サンプル集S3編~

概要~個人的によく使うLambda(Python Boto3)のサンプル集~

Lambdaプログラミングしていて良く使うコードサンプルをまとめていきます。
随時更新予定です(^^)

公式APIリファレンス

AWS公式のAPIリファレンスは以下のURLで何かあったら参照して正しく使いましょう。

https://boto3.amazonaws.com/v1/documentation/api/latest/index.html

S3サンプル

S3ファイルダウンロード

ダウンロードするS3のバケット名、オブジェクト名、Lambdaのローカル環境に保存するファイル名を指定します。
ローカル環境上に同名のファイルがあった場合は上書きされます。

import boto3
s3 = boto3.client('s3')

# バケット名、ダウンロードオブジェクト名、ダウンロードファイル名
S3_BUCKET_NAME = 'sample-bucket'
S3_OBJECT_DOWNLOAD_FILE_NAME = 'sample.jpg'
LOCAL_SAVE_FILE_NAME = '/tmp/sample.jpg'

def lambda_handler(event, context):

    # S3ダウンロード
    s3.download_file(S3_BUCKET_NAME, S3_OBJECT_DOWNLOAD_FILE_NAME, LOCAL_SAVE_FILE_NAME)

    return

S3ファイルアップロード

アップロード先のS3のバケット名、オブジェクト名、Lambdaのローカル環境にあるアップロード対象のファイル名を指定します。
Lambdaのローカル環境にアップロードファイルがある前提のため、事前にアップロードファイルは作成しておく必要があります。
S3上に同名のオブジェクトがあった場合は上書きされます。

import boto3
s3 = boto3.client('s3')

# バケット名、オブジェクト名、アップロード対象ファイル名
S3_BUCKET_NAME = 'sample-bucket'
S3_OBJECT_UPLOAD_FILE_NAME = 'S3sample.jpg'
LOCAL_UPLOAD_FILE_NAME = '/tmp/sample.jpg'

def lambda_handler(event, context):

    # TODOアップロード対象ファイル作成処理

    # S3アップロード
    s3.upload_file(LOCAL_UPLOAD_FILE_NAME, S3_BUCKET_NAME, S3_OBJECT_UPLOAD_FILE_NAME)

    return

S3ファイルダウンロード(メモリ上で扱う場合)

ローカル環境に保存せず、そのままメモリ上でバイトデータとして扱う場合は以下になります。

import boto3

s3 = boto3.resource('s3')

# バケット名、ダウンロードオブジェクト名
S3_BUCKET_NAME = 'sample-bucket'
S3_OBJECT_DOWNLOAD_FILE_NAME = 'sample.jpg'

def lambda_handler(event, context):
    # S3ダウンロード
    bucket = s3.Bucket(S3_BUCKET_NAME)
    obj = bucket.Object(S3_OBJECT_DOWNLOAD_FILE_NAME)
    response = obj.get()
    body = response['Body'].read()

    # 別のBotoクライアントにバイトのまま渡す場合
    # response = client.xxxxxx(Image={'Bytes': body})
    # ダウンロードファイルが画像ではなくJSONファイルの場合
    # print(json.loads(body.decode('utf-8')))

S3ファイルのリスト表示

ファイルのリスト表示するS3のバケット名を指定します。

import boto3

s3 = boto3.client('s3')

# バケット名
S3_BUCKET_NAME = 'sample-bucket'

def lambda_handler(event, context):

    # オブジェクトのリスト表示
    response = s3.list_objects_v2(Bucket=S3_BUCKET_NAME)

    for obj in response['Contents']:
        print(obj['Key'])

    return

S3事前署名付きURL発行

S3に保存してあるファイルを一時的に公開するときに使用する事前署名付きURLを発行するサンプルです。
事前署名付きURLを発行するS3のバケット名、オブジェクト名、URLの有効期限(秒)を指定します。

import boto3
s3 = boto3.client('s3')

# バケット名、事前署名URL発行オブジェクト名、有効期限(秒)
S3_BUCKET_NAME = 'ai-sample-bucket'
S3_OBJECT_PRESIGNES_FILE_NAME = 'sample.jpg'
EXPIRATION = 3600

def lambda_handler(event, context):

    # 事前署名URL発行
    response = s3.generate_presigned_url('get_object',
        Params={'Bucket': S3_BUCKET_NAME,
        'Key': S3_OBJECT_PRESIGNES_FILE_NAME},
        ExpiresIn=EXPIRATION)

    print(response)

    return

参考

Boto3ライブラリは、boto3.clientとboto3.resourceの2つの主要なクラスがあります。

boto3.clientは、AWSサービスのAPIアクションを呼び出すためのクライアントを提供します。例えば、s3クライアントを作成して、S3バケットを作成したり、オブジェクトを取得したり、削除したりすることができます。これは低レベルのAPIであり、AWSリソースとのやり取りがJSONデータで行われます。

一方、boto3.resourceは、AWSリソースを表すPythonオブジェクトを提供します。これは、より高レベルのAPIであり、AWSリソースとPythonオブジェクトのやり取りが可能です。例えば、s3リソースを使用して、バケットを作成したり、オブジェクトを取得したり、削除したりすることができます。また、オブジェクトにはファイルの内容にアクセスするためのread()メソッドがあり、オブジェクトに対してPythonオブジェクトと同じように操作できます。

それぞれで出来ること、やりたいことを理解して使い分けましょう。

Pythonのseleniumを使ってWeb画面操作を自動化する~サンプルを使ってWebスクライピンングのチャレンジ~

概要~Pythonのseleniumを使って値取得/値入力/クリック/スクリーンショット等、画面操作を自動化する~

少しずつ毎日のWeb生活を快適にするために最近は Python selenium 使ったWeb画面自動化処理を行っています。
今回の投稿は、その自動化処理をする上で繰り返し使える基本コードのまとめから、ちょっとした便利ノウハウをまとめた内容になっています。
これを実行すれば誰でも簡単にWeb画面の自動化処理ができ、日々単調なルーチンワークから脱却できるので、ぜひ試してみてください。

対象読者

  • Pythonを触ったことがある人
  • ブラウザの自動化で楽したい人

出来るようになること

  • Web画面を自動操作する
    • 画面を開く
    • 特定のHTML要素から値を取得する
    • 特定のHTML要素に値を入力する
    • ボタンをクリックする
  • Web画面のスクリーンショットを取得する

事前準備

今回は selenium を使って自動化します。その為に2つの事前準備が必要なのでその準備をします。

事前準備1~ブラウザのドライバをダウンロード~

Web画面の自動化はブラウザの専用ドライバーを使って画面操作を行います。そのためにドライバーをダウンロードします。ドライバーはブラウザ別に用意されているのでお好みのブラウザのドライバーをダウンロードしましょう。(どのドライバーでも自動化のソースコードは同じです)

chromeドライバー

https://chromedriver.chromium.org/downloads

Edge ドライバー

https://developer.microsoft.com/ja-jp/microsoft-edge/tools/webdriver/

事前準備2~seleniumのインストール~

これはpipを使うだけで簡単です。以下のコマンド実行します。

pip install selenium

事前準備は以上です!では、さっそくWeb画面の自動化にチャレンジしていきましょう!!

補足~Google Colaboratoryでのselenium実行~

seleniumu は Google Colaboratory でも実行できるので、サクッと試してみたい時はこちらがおすすめです。
その場合、ドライバー、selenium のインストールは以下のコマンドを実行しておくことになります。

!apt-get update
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
!pip install selenium
!pip freeze

Google Colaboratory では、日本語フォントがインストールされていないので文字化けが発生する場合は、以下のコマンドで日本語フォントをダウンロードします。

# 日本語フォントをダウンロードする。
!apt-get -y install fonts-ipafont-gothic

それでは、本編に戻ります!

ページを開く

最初は最も基本的な特定のページを開く操作です。
getメソッドに開きたいページのURLを指定します。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By

# ドライバーの設定
CHROME_DRIVER = "{ドライバーの格納フォルダ}\\chromedriver"

driver = webdriver.Chrome(CHROME_DRIVER,options=Options())

# 指定したURLの画面を開く
driver.get("http://www.google.com")

# ブラウザを閉じる
driver.quit()

【参考ドキュメント】
https://www.selenium.dev/ja/documentation/webdriver/drivers/options/#normal-default

サンプルソースの{ドライバー格納フォルダ}を自身でドライバーを保存したフォルダに変更して実行してみてください。(サンプルはChromeドライバーを使った例になります)

簡単にブラウザの特定のページが開けたと思います。すぐに閉じてしまっているので一瞬だったかもしれませんが、ここから自動化処理のスタートです!

要素を探す

seleniumで実現したいことはWeb画面の自動操作だと思います。
その中で最も基本的なことは操作したい要素を探す(指定する)ことであり、慣れるまでここが最も大変と思うのでこの部分を重点的に説明します。

要素の選択(指定)

要素の選択(指定)方法には以下の8種類があります。
(ロケータと呼びます)

ロケータ詳細コード例
idid属性が一致する要素を探すdriver.find_element(By.ID,"abc")
class nameclass名に値を含む要素を探す(複合クラス名は使えない)driver.find_elements(By.CLASS_NAME,"abc")
css selectorCSSセレクタが一致する要素を探すdriver.find_elements(By.CSS_SELECTOR,"abc")
xpathXPathと一致する要素を探すdriver.find_elements(By.XPATH,"abc")
link texta要素のテキストが一致する要素を探すdriver.find_elements(By.LINK_TEXT,"abc")
partial link texta要素のテキストが部分一致する要素を探すdriver.find_elements(By.PARTIAL_LINK_TEXT,"abc")
namename属性が一致する要素を探すdriver.find_elements(By.NAME,"abc")
tag nameタグ名が一致する要素を探すdriver.find_elements(By.TAG_NAME,"abc")

【参考ドキュメント】
https://www.selenium.dev/ja/documentation/webdriver/elements/locators/#%E8%A6%81%E7%B4%A0%E9%81%B8%E6%8A%9E%E3%81%AE%E6%96%B9%E6%B3%95

この表は私が良く使う順に記載しています。
次から具体的に説明していきますが、コード例のidだけはfind_element最後の(s)がないことに注意してください。
これはidだけはページ内で1つというHTMLのルールがあるため、1つの要素が返却されることを意味しています。
ちなみに他のロケータにもfind_elementがありますが、先頭の1つの要素が取れるという仕様になっており、限られたケースでしか使用しないため、私は基本的にはid以外はfind_elements最後の(s)ありのメソッドを使用しています。

使用優先度1:ID指定による要素選択

ここからは具体例とともにそれぞれの要素選択方法のサンプルを記載していきます。
まずはID指定です。取得したい要素にid指定の属性があった場合、迷わずこれを使えば良いと思います。

サンプルコード

login_form = driver.find_element(By.ID, 'loginForm')

サンプルHTML

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
  </form>
 </body>
</html>

実行結果サンプル

login_form = driver.find_element(By.ID, 'loginForm')
print(login_form.tag_name)
# form が出力される

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-by-id

これで formタグの要素(element)が取得できます。id属性があれば最も簡単です。

使用優先度2:クラス名指定による要素選択

次はクラス名指定に要素選択方法です。
idがなくてもクラスが指定されているケースはよくあるので良く使用しています。
(普段使うのは find_elements メソッドですが、サンプルをわかりやすくするため find_element (sなし)メソッドを使っています。)

コードサンプル

content = driver.find_element(By.CLASS_NAME, 'content')

HTMLサンプル

<html>
 <body>
  <p class="content">Site content goes here.</p>
</body>
</html>

実行結果サンプル

content = driver.find_element(By.CLASS_NAME, 'content')
print(content.text)
# Site content goes here.

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-elements-by-class-name

クラス名に複数の指定がある場合

クラス名指定は結構便利ですが、1つ注意点があります。
クラス名はよく複数指定されるケースがあります。↓こんな場合、

<div class="content test">TEST</div>

こんな場合は、.(ドット)区切りで指定します。

content = driver.find_element(By.CLASS_NAME, 'content.test')

これで取得できるのですが、たまに取得出来ないケースがあるようです。
私の場合は、AWS Lambdaがこのケースで取得できず、結局次のCSSセレクタを使って取得しました。(ちなみにLambdaは、Python 3.7 Selenium 3.141でした)

使用優先度3:CSSセレクタ指定による要素選択

次にCSSセレクタです。
CSSに詳しい人なら迷わず使えますね。私もクラス名指定の所で書いたクラス名指定ができないケースがあるので、最近はこれを一番多用しています。

コードサンプル

content = driver.find_element(By.CSS_SELECTOR, 'p.content')

HTMLサンプル

<html>
 <body>
  <p class="content">Site content goes here.</p>
</body>
</html>

実行結果サンプル

content = driver.find_element(By.CSS_SELECTOR, 'p.content')
print(content.text)
# Site content goes here.

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-elements-by-css-selectors

クラス名にタブを.(ドット)区切りで指定というクラス名指定と同じようなシンプルな指定で使えるので簡単ですね。

クラス名の所で記載した複数のクラスが指定されていた場合の指定方法は以下になります。

# <div class="a b">text</div> の場合
find_element(By.CLASS_NAME, "a.b")# ←Lambda NG
find_element(By.CSS_SELECTOR, "div.a.b")# ←OK
find_element(By.XPATH, "//div[@class='a b']")# ←XPathのこれもOK

使用優先度4:XPath指定による要素選択

次はXPathによる指定です。
XPathは柔軟な指定ができるので、私はクラス名やCSSセレクタ指定で複数の要素が取得できてしまうケースで、敢えて1つのみの要素を指定したい場合とかに使用しています。

コードサンプル

login_form = driver.find_element(By.XPATH, "/html/body/form[1]")
login_form = driver.find_element(By.XPATH, "//form[1]")
login_form = driver.find_element(By.XPATH, "//form[@id='loginForm']")

HTMLサンプル

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
</body>
</html>

実行結果サンプル

login_form = driver.find_element(By.XPATH, "/html/body/form[1]")
login_form = driver.find_element(By.XPATH, "//form[1]")
login_form = driver.find_element(By.XPATH, "//form[@id='loginForm']")
print(login_form.tag_name)
# form が出力される(どの指定方法でも同じ結果です)

【参考ドキュメント】

https://selenium-python.readthedocs.io/locating-elements.html#locating-by-xpath

3種類の指定方法をサンプルにしていますが、取得結果はどれも同じです。

  1. htmlタグからの絶対パスで指定しています。直感的な指定が可能ですが、HTML構造が変わったら取得できなくなるので使用ケースは注意が必要です
  2. formタグの1つ目という指定です。// を使用すること絶対パス指定が不要になります。
  3. formタグ、かつ、id指定という指定の仕方です。2.のケースよりわかりやすく指定できますね。

使用優先度5:a要素テキスト指定による要素選択

次はa(アンカー)タグ内のテキスト指定する方法になります。
完全一致で指定する LINK_TEXT と 部分一致で指定する PARTIAL_LINK_TEXT があります。

コードサンプル

continue_link = driver.find_element(By.LINK_TEXT, 'Continue')
continue_link = driver.find_element(By.PARTIAL_LINK_TEXT, 'Can')

HTMLサンプル

<html>
 <body>
  <p>Are you sure you want to do this?</p>
  <a href="continue.html">Continue</a>
  <a href="cancel.html">Cancel</a>
</body>
</html>

実行結果サンプル

continue_link = driver.find_element(By.LINK_TEXT, 'Continue')
print(continue_link.text)
# Continue
continue_link = driver.find_element(By.PARTIAL_LINK_TEXT, 'Can')
print(continue_link.text)
# Cancel

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-hyperlinks-by-link-text

この指定方法は、Web画面に表示されている文字をそのまま使えるので結構便利だったりします。ただ、最近のWebでアンカータグがどれだけあるのか、画面表示の文字は頻繁に変わらないか、と考えると使用ケースは限られるため、個人的に使用ケースがあまりないかなと思っています。

使用優先度6:name属性指定による要素選択

次はname属性による指定です。
先に紹介したクラス名指定とよく勘違いするのですが、こちらはname属性になります。

コードサンプル

username = driver.find_element(By.NAME, 'username')
password = driver.find_element(By.NAME, 'password')

HTMLサンプル

<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
</body>
</html>

実行結果サンプル

username = driver.find_element(By.NAME, 'username')
print(username.tag_name)
# input

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-by-name

この指定ケースも直感的でわかりやすいのですが、name属性が指定された要素がそんなにあるかな。。。という印象なので、どちらかというとクラス名指定を良く使っています。

使用優先度7:タグ名指定による要素選択

最後は、タグ名による指定です。
これはシンプルですね。タグ名をそのまま指定します。

コードサンプル

heading1 = driver.find_element(By.TAG_NAME, 'h1')

HTMLサンプル

<html>
 <body>
  <h1>Welcome</h1>
  <p>Site content goes here.</p>
</body>
</html>

実行結果サンプル

heading1 = driver.find_element(By.TAG_NAME, 'h1')
print(heading1.text)
# Welcome

【参考ドキュメント】
https://selenium-python.readthedocs.io/locating-elements.html#locating-by-name

使用方法はシンプルなのですが、タグの直接指定がそれほど使用ケースがない気がしているので最後の紹介になります。

補足~便利?コードサンプル~

ここからは私が個人的に良く使っているコードサンプルの紹介です。

要素取得判定

冒頭で記載した通り、私は find_elements(find_elementではなく)を多用しています。
そのため、要素が意図通り取得できたかを以下のように確認するメソッドを使って判定しています。

コードサンプル

# 要素取得判定関数
def element_check(element, target):
    if len(element) > 0:
        print(target + " 個数:" + str(len(element)))
        return True
    else:
        print(target + ":要素が見つかりません")
        return False

# 要素取得判定関数呼び出し例
elements = driver.find_elements(By.TAG_NAME, 'a')
if element_check(elements, 'a') :
    for element in elements:
        print(element.text)

要素に対する操作コードサンプル

要素を取得した後の操作は基本的には以下の操作と思っています。
これだけは覚えておけば基本的な操作はできるかなというものを記載しておきます。

  • テキスト取得
  • テキスト入力
  • テキストクリア
  • クリック

コードサンプル

element.text
element.send_keys("abc")
element.clear()
element.click()

ページのタイトルを取得する

各処理を始める前にまずタイトルを取得する場合、以下のコードで簡単に取得できます。

driver = webdriver.Chrome(CHROME_DRIVER,options=Options())
print(driver.title)

HTMLを表示する

意図した動作にならない場合など、実際のHTMLを確認したいケースがあると思います。その時は、以下のコードでHTMLを取得します。

driver = webdriver.Chrome(CHROME_DRIVER,options=Options())
print(driver.page_source.encode('UTF-8'))

スクリーンショットを保存する

Web画面の操作結果を保存する、意図した動作になっているか途中の画面遷移を保存する際に利用するのがスクリーンショットです。
seleniumu では簡単にスクリーンショットを取ることができます。

コードサンプル

# スクロールを含めて全画面のスクリーンショットを取得するためヘッドレスモードにする
options = Options()
options.add_argument('--headless')
driver = webdriver.Chrome(CHROME_DRIVER,options=options)

# 全画面のスクリーンショット取得
w = driver.execute_script('return document.body.scrollWidth')
h = driver.execute_script('return document.body.scrollHeight')
driver.set_window_size(w, h)
driver.save_screenshot("screenshot.png")

指定した要素部分のみの一部のスクリーンショットを保存する

上の例だと全画面表示になってしまうため、必要な要素部分だけ取得したい場合(例えば特定のframe内だけ取得したい場合)は事前に要素取得してから、スクリーンショットを保存します。

# スクロールを含めて全画面のスクリーンショットを取得するためヘッドレスモードにする
options = Options()
options.add_argument('--headless')
driver = webdriver.Chrome(CHROME_DRIVER,options=options)

# 一部要素の全画面スクリーンショット取得
w = driver.execute_script('return document.body.scrollWidth')
h = driver.execute_script('return document.body.scrollHeight')
driver.set_window_size(w, h)
# 取得したい要素を指定する(ID指定でなくても良い)
element = driver.find_element(By.ID, 'main-element')
png = element.screenshot_as_png
# 任意のファイル名を指定してpngファイルに保存
with open('ElementScreenshot.png', 'wb') as f:
    f.write(png)

ドライバーの自動更新

ドライバーのバージョンは自分が普段使用するブラウザのバージョンと一致しておく必要があるため、ブラウザのバージョンアップが定期的にあり、その度にドライバーのダウンロードが面倒という方は以下でドライバーのインストール含めて自動化できます。

# Webdriver ManagerでChromeDriverを取得
from webdriver_manager.chrome import ChromeDriverManager
# ChromeDriverManager().install()を指定して自動インストール
driver = webdriver.Chrome(ChromeDriverManager().install(),options=options)

ちなみにブラウザとドライバーのバージョンは不一致の場合、以下のエラーメッセージが出力され、処理が異常終了します。

selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 104
Current browser version is 106.0.5249.119 with binary path C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

逆引き参考ページ

以下はseleniumでやりたいことの目的別に逆引きができるサイトになります。

https://www.seleniumqref.com/api/webdriver_gyaku.html

属性ごとの取得方法まとめ

以下は属性ごとに指定方法がまとめられて非常に参考になるサイトになります。
XPathの使い方がうまい。

https://qiita.com/VA_nakatsu/items/0095755dc48ad7e86e2f

「Chrome の自動操作を一通り」

タイトルの通り、「Chrome の自動操作を一通り」まとめてくれているサイトになります。網羅的に書かれていて非常に参考になります。

https://qiita.com/memakura/items/20a02161fa7e18d8a693

まとめ

今回はPythonのSeleniumでWeb画面操作を自動化する基礎をまとめてみました。
自分なりによく使う辞書的な位置づけでまとめてみたので、同じような人の役に立てれば嬉しいです(^^)

gspreadライブラリを使ってPythonでGoogleスプレッドシートの操作(値追加・値取得・行追加・行削除)する

概要〜Pythonでgspreadライブラリを公式ページにならってやってみてAWS LambdaでGoogleスプレッドシートに定期的に記録する〜

皆さん日々記録を取りたい時どこに記録をしていますか?
私はGoogleスプレッドシートを多用しています。
なぜなら、、、

  • Googleアカウントをもっていれば誰でも無料で使える
  • Webブラウザがあれば携帯、PC問わずアクセスできる
  • ちょっと修正したいなと思った時の修正がExcelと同じ操作感なので容易

などの理由からです。
日々自動化して記録をしたいことがあるのですが、その都度DBを用意して記録するのはそれなりに手間がかかるので私はGoogleスプレッドシートを使って日々の自動化処理を実行しています。
今回はその時に役に立つ、PythonからGoogleスプレッドシートに簡単にアクセスできるgspreadライブラリを調べたのでその整理内容になります。

出来るようになること

  • Googleスプレッドシートを開く
  • Googleスプレッドシートのシートを指定する
  • Googleスプレッドシートの値を取得する
  • Googleスプレッドシートに値を書き込む
  • Googleスプレッドシートに行を追加する/行を削除する

最終的なコードは以下になります。
これだけのコードでGoogleスプレッドシートに対する最低限の操作が出来るのでかなり簡単だったと思います。

import gspread
import json

#認証処理
gc  = gspread.service_account_from_dict('認証情報のJSON')

# ファイル名指定で開く
sh = gc.open('ファイル名')

# シート名指定
worksheet = sh.worksheet("シート名")

# A1等のラベル指定して値取得
val = worksheet.acell('B1').value

# ラベル指定して値を更新
worksheet.update('B1', 'Bingo!')

# 最終行に引数のリストの内容を1行追加
worksheet.append_row(['A','B','C'])

公式ページ

gspreadの公式ページは以下になります。

https://docs.gspread.org/en/latest/

前提条件

前提条件としてGoogleスプレッドシートにアクセスするための認証情報(JSONファイル)をGCPで取得する必要があります。(GCPを利用するのでGCPアカウントが必要になります)
今回はgspreadライブラリの説明をメインとした記事なのでこの部分は割愛しますが、以下のようなコードで取得した認証情報を使って認証処理を実装します。
gspreadライブラリを使えばたった3行です。簡単ですね。

import gspread
import json

#認証処理
gc  = gspread.service_account_from_dict('認証情報のJSON')

認証処理の更新ページURLは以下になります。
実装方法は上のサンプル以外にもあるので必要なら別の方法を確認してみてください。

https://docs.gspread.org/en/latest/oauth2.html

ワークブックを開く

それでは実際のGoogleスプレッドシートの操作の説明に移ります。
まず最初はGoogleスプレッドシートの操作するスプレッドシートを指定して開きます。
指定方法にはファイル名を指定、キーを指定、URLの指定の3つの方法があるので、扱い易い方法で開けばいいと思います。個人的にはファイル名指定が一番直感的に扱えるかなと思っています。

# ファイル名指定で開く
sh = gc.open('ファイル名')

# スプレッドシートのキー指定で開く
sh = gc.open_by_key('スプレッドシートキー')

# URL指定で開く
sh = gc.open_by_url('URL')

# スプレッドシートを取得したらスプレッドシートの内容を表示してみる
print(sh.title) #スプレッドシートのタイトルを表示する
print(sh.id) # スプレッドシートキーを表示する

ファイルを開く部分の公式ページは以下になります。

https://docs.gspread.org/en/latest/user-guide.html#opening-a-spreadsheet

シート選択

スプレッドシートが開けたら次はシートを選択します。
この辺りの操作間はExcel操作と一緒ですね。
こちらも複数の方法がありますが、基本的にはインデックスを指定するか、シート名を指定する方法になります。個人的にはこちらもシート名を指定する方法が直感的かなと思います。

# シートのインデックスを指定(先頭は0になります)
worksheet = sh.get_worksheet(0)

# シート名指定
worksheet = sh.worksheet("シート名")

# 先頭のシート指定(先頭のシートだけです。sheet2にしたところで2番目のシートは指定できません)
worksheet = sh.sheet1

# すべてのシートをリストで取得する
worksheet_list = sh.worksheets()

# シートを取得したらシートの内容を表示してみる
print(worksheet.title)  # シート名表示
print(worksheet.id) # シートID表示

公式ページは以下になります。

https://docs.gspread.org/en/latest/user-guide.html#selecting-a-worksheet

値取得

シートまで取得できたので、それではここから値を取得していきます。
A1等のラベル表記と1,2といった行と列番号を指定して取得する方法があります。
こちらはどちらの取得方法でも良いと思うので好みですかね。。。

# A1等のラベル指定して値取得
val = worksheet.acell('B1').value

# 行と列番号を指定して値取得(左:行番号、右:列番号)
val = worksheet.cell(1, 2).value

# 行番号の指定して1行の値をリストとして取得
values_list = worksheet.row_values(1)

# 列番号の指定して1列の値をリストとして取得
values_list = worksheet.col_values(1)

# 値を取得したら値の内容を表示してみる
print(val) # 値表示
print(values_list) # 取得したリストの値を表示

公式ページは以下になります。

https://docs.gspread.org/en/latest/user-guide.html#getting-a-cell-value

他にもシート全て値を取得する方法や行ごとに取得する方法が公式ページには記載されているので参照してみてください。

https://docs.gspread.org/en/latest/user-guide.html#getting-all-values-from-a-worksheet-as-a-list-of-lists

https://docs.gspread.org/en/latest/user-guide.html#getting-all-values-from-a-worksheet-as-a-list-of-dictionaries

値を更新

続いて値を更新していきます。
方法は値取得と同一になり、A1等のラベル表記と1,2といった行と列番号を指定して取得する方法があります。

# ラベル指定して値を更新
worksheet.update('B1', 'Bingo!')

# 行と列番号を指定して値更新
worksheet.update_cell(1, 2, 'Bingo!')

# 範囲を指定して値をまとめて更新
worksheet.update('A1:B2', [[1, 2], [3, 4]])

# 更新したら値の内容を表示してみる
print(worksheet.acell('B2').value) # 値表示

公式ページは以下になります。

https://docs.gspread.org/en/latest/user-guide.html#updating-cells

行操作

最後に行ごとに操作する方法の紹介になります。
実際スプレッドシートの更新は行ごとに行うことが多いと思うので、その時の操作方法になります。
方法としては、最終行に追加、指定行に追加、指定行の削除になります。
行を指定しての更新方法が見つからず私は指定行を削除後、指定行を追加することで行の更新を行っています。

# 最終行に引数のリストの内容を1行追加
worksheet.append_row(['A','B','C'])

# 指定行に引数のリストの内容を1行追加
worksheet.insert_row(['A','B','C'], 1)

# 指定行を削除
worksheet.delete_rows(2)

# 行を更新したら値の内容を表示してみる
values_list = worksheet.row_values(1)
print(values_list)

公式ページは以下になります。

https://docs.gspread.org/en/latest/api/models/worksheet.html#gspread.worksheet.Worksheet.append_row

https://docs.gspread.org/en/latest/api/models/worksheet.html#gspread.worksheet.Worksheet.insert_row

https://docs.gspread.org/en/latest/api/models/worksheet.html#gspread.worksheet.Worksheet.delete_row

まとめ

いかがだったでしょうか。
私はgspreadライブラリを使うことでかなり簡単にGoogleスプレッドシートの操作ができたと感じています。
私はこれをAWS Lambdaに実装し日々の記録を自動化しています。
機会があればLambdaへの実装方法を記事にしようと思いますが、ソースコードだけ参考に載せておきます。
認証情報をパラメータストアから取得するところがAWS Lambda特有の部分ですが、他は同じようにGoogleスプレッドシートの操作が可能です。

import gspread
import json
import boto3
import os

# パラメータストアに保存している認証情報のキー名を環境変数から取得
# PARAM_KEY = os.environ.get('●●●パラメータストアを取得する環境変数名を指定●●●')
# 私は環境変数として「PARAM_KEY」として設定
PARAM_KEY = os.environ.get('PARAM_KEY')

def lambda_handler(event, context):

    # パラメータストアに保存している認証情報(JSONファイルを取得)
    ssm = boto3.client('ssm')
    response = ssm.get_parameters(
        Names=[
            PARAM_KEY,
        ],
        WithDecryption=True
    )
    service_account_info = json.loads(response['Parameters'][0]['Value'])

    #認証処理
    gc  = gspread.service_account_from_dict(service_account_info)

    # ファイル名指定で開く
    sh = gc.open('●●●Googleスプレッドシートファイル名を指定●●●')

    # シート名指定
    worksheet = sh.worksheet("●●●操作するシート名を指定●●●")

    # A1等のラベル指定して値取得
    val = worksheet.acell('B1').value

    # ラベル指定して値を更新
    worksheet.update('B1', 'Bingo!')

    # 最終行に引数のリストの内容を1行追加
    worksheet.append_row(['A','B','C'])

Lambdaの環境変数に以下を設定

SystemsManagerのパラメータストアに以下を設定

AWS Lambda関連の記事は以下などを投稿しているので興味がある方はぜひ読んでみてください(^^)

1.AWS Lambda 入門~おすすめ本5冊の紹介~

2.AWS Lambda で Python プログラミング~Boto3 サンプル集S3編~

3.AWS Lambda SAMとは?~Cloud9でSAM Sampleを使ってPythonのLambdaプログラムを簡単にデプロイする~

これで日々の単調な作業から脱却します!

AWS Lambda SAMとは?~Cloud9でSAM Sampleを使ってPythonのLambdaプログラムを簡単にデプロイする~

概要

前のLambda投稿に続き今回もAWS Lambdaネタになります。
今回はLambda構築・設定・イベントソースマッピングからソースコードを管理・編集しやすいようにAWS サーバーレスアプリケーションモデル (Serverless Application Model)、AWS SAMにチャレンジします。

https://aws.amazon.com/jp/serverless/sam/

サンプルコードなどの簡単なプログラミングであればAWSコンソールで設定、ソースコードの直接編集すれば良いのですが、ちょっと規模が大きくなるとLambdaの設定・ソースコードをしっかり管理したい、しっかりテストしたいという状況が出てきます。

その時にかなり便利なのがAWS サーバーレスアプリケーションモデル(AWS SAM)になります。

Lambdaを使って本格的にLambdaのサービスを運用したい人、興味がある方は読んでみて下さい。

資格試験の勉強法は記事は以下を参照。

AWS初心者がAWS 認定ソリューションアーキテクト – アソシエイト資格試験に合格した時の勉強法
AWS初心者がAWS 認定ソリューションアーキテクト – プロフェッショナル資格試験に合格した時の勉強法

想定読者

  • LambdaでSAMを使ってみたい人
  • Lambdaの知識をレベルアップしたい人
  • Lambdaを実運用で使っている人

参考書籍

AWS Lambda実践ガイド 第2版

【Kindle版】AWS Lambda実践ガイド 第2版

ほぼほぼこの本を参考にさせて頂きました。
Lambdaに特化した本はあまりないので現時点で唯一の専門書と思います。
2022年になって第2版となり内容が最新化されています。

目次

  • SAM環境(Cloud9環境)準備
  • SAM初期設定
  • SAMビルド/デプロイ

SAMを使って簡単なLambda関数を作っていきます。
作業時間、たったの 30分!

SAM環境(Cloud9環境)準備

SAMを使うためには SAM CLI がインストールされている必要があります。
ローカル環境でインストールしても良いのですが、AWS の Cloud9 を使うのが一番簡単なので今回はCloud9の環境準備から説明します。

Cloud9の作成は非常に簡単で、AWSコンソールのCloud9のサービスメニュに行き、

image.png

Create environmentをクリック
image.png

Nameに任意の名前を入力
Next stepをクリック

image.png

環境設定は、基本的には任意のものを選択していいのですが、ブラウザからそのままアクセスが出来て簡単なのが direct access 、料金が安く済むものが t2.micro になります。

image.png

料金節約のため無操作30分後に自動停止するよう After 30 minutes(default) のままにしておきます。
Network settingd(advanced) はデフォルトVPC以外に作りたい時(Cloud9へのアクセスをしっかりアクセス制御したい時)に選択します。
Next step をクリック

image.png

設定内容を最終確認して問題なければ、Create environment クリック

memo_2022-05-01-11-46-16.png

数分待つとこんな感じのCloud9のトップ画面が表示されます。
実際の操作は左メニューから編集したいファイルを選択し画面中央部で編集する操作と、画面下部のコンソール部分に直接コマンドを実行する大きく2パターンの操作があります。

image.png

SAM初期設定(sam init)

それでは実際にSAMの初期設定をしていきます。
画面下部のコンソールに sam init のコマンドを実行して初期設定します。

$ pwd
/home/ec2-user/environment
$ sam init

You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.

Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1

Choose an AWS Quick Start application template
        1 - Hello World Example
        2 - Multi-step workflow
        3 - Serverless API
        4 - Scheduled task
        5 - Standalone function
        6 - Data processing
        7 - Infrastructure event management
        8 - Lambda EFS example
        9 - Machine Learning
Template: 1

 Use the most popular runtime and package type? (Python and zip) [y/N]: y

Project name [sam-app]: sam-example

Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)

    -----------------------
    Generating application:
    -----------------------
    Name: sam-example
    Runtime: python3.9
    Architectures: x86_64
    Dependency Manager: pip
    Application Template: hello-world
    Output Directory: .

    Next steps can be found in the README file at ./sam-example/README.md


    Commands you can use next
    =========================
    [*] Create pipeline: cd sam-example && sam pipeline init --bootstrap
    [*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch


SAM CLI update available (1.53.0); (1.40.1 installed)
To download: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html
$

実際の入力値は以下の4つ

  • Choice: 1(1 - AWS Quick Start Templates)
  • Template: 1(1 - Hello World Example)
  • Use the most popular runtime and package type? (Python and zip) [y/N]: y
  • Project name [sam-app]: sam-example

sam-example というプロジェクト名で、実行環境 python3.9、samテンプレート Hello World Example を選択(テンプレートはすぐに自分で編集するのでなんでも構いません)しています。

sam init コマンドが完了するとひと通り必要なフォルダ・ファイル群が作成されます。

IMG_0358.jpeg

この中で重要なのが、

  • app.py:Lambdaのソースプログラムが記載されているファイル
  • template.yml:Lambdaの設定が記載されているファイル

の二つになります。

IMG_0357.jpeg

それぞれ中身を簡単に見てみます。
まずは template.yml から。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-example

  Sample SAM Template for sam-example

# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /hello
            Method: get

Outputs:
  # ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
  # Find out more about other implicit resources you can reference within SAM
  # https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

Hello World Example のテンプレートの場合、LambdaとAPIGatewayが含まれています。
Resources: 部がそれらの記述に該当しますが

  • Type: AWS::Serverless::Function:Lambdaであることを示しています
  • Type: Api:APIGatewayであることを示しています

今回は、最小限のLambdaだけの設定にしたいので以下に書き換えます。(ついでにコメントも消してすっきりさせます)

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-example

  Sample SAM Template for sam-example

Globals:
  Function:
    Timeout: 3

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app.lambda_handler
      Runtime: python3.9

Outputs:
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

DescriptionOutputs は無くても良い設定のため必要なのは、GlobalsResources 部だけになり、たった 9行 です。

次は app.py です。
このファイルがLambdaの本体のプログラムになります。
今後、自分でプログラムを書き換えるときはこのファイルを編集します。

import json

# import requests


def lambda_handler(event, context):
    """Sample pure Lambda function

    Parameters
    ----------
    event: dict, required
        API Gateway Lambda Proxy Input Format

        Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format

    context: object, required
        Lambda Context runtime methods and attributes

        Context doc: https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html

    Returns
    ------
    API Gateway Lambda Proxy Output Format: dict

        Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
    """

    # try:
    #     ip = requests.get("http://checkip.amazonaws.com/")
    # except requests.RequestException as e:
    #     # Send some context about this error to Lambda Logs
    #     print(e)

    #     raise e

    return {
        "statusCode": 200,
        "body": json.dumps({
            "message": "hello world",
            # "location": ip.text.replace("\n", "")
        }),
    }

こちらはシンプルですね。
コメントがたくさんありますが、戻り値にjson形式の hello world も返却しているだけになってます。

SAMビルド/デプロイ(sam build/sam deploy)

ビルド

では、ビルド/デプロイをやっていきましょう。
template.yml を編集したため、シンプルに Lambda関数1つ を作成するsamテンプレートになっています。

では、ここからはコンソール操作になるので、Cloud9画面下部のコンソール部分でコマンド実行します。
まず、カレントフォルダを ~/environment/sam-example/ (自身で入力したプロジェクトフォルダ)に移動して、ビルドコマンド sam build --use-container を実行します。

実際の実行コマンドは以下の2つ

cd ~/environment/sam-example/
sam build --use-container

では、やってみます。

$ cd ~/environment/sam-example/
$ sam build --use-container
Starting Build inside a container
Building codeuri: /home/ec2-user/environment/sam-example runtime: python3.9 metadata: {} architecture: x86_64 functions: ['HelloWorldFunction']

Fetching public.ecr.aws/sam/build-python3.9:latest-x86_64 Docker container image...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Mounting /home/ec2-user/environment/sam-example as /tmp/samcli/source:ro,delegated inside runtime container
Traceback (most recent call last):
  File "samcli/__main__.py", line 12, in <module>
  File "click/core.py", line 829, in __call__
  File "click/core.py", line 782, in main
  File "click/core.py", line 1259, in invoke
  File "click/core.py", line 1066, in invoke
  File "click/core.py", line 610, in invoke
  File "click/decorators.py", line 73, in new_func
  File "click/core.py", line 610, in invoke
  File "samcli/lib/telemetry/metric.py", line 153, in wrapped
  File "samcli/lib/telemetry/metric.py", line 122, in wrapped
  File "samcli/lib/utils/version_checker.py", line 42, in wrapped
  File "samcli/cli/main.py", line 90, in wrapper
  File "samcli/commands/build/command.py", line 228, in cli
  File "samcli/commands/build/command.py", line 318, in do_cli
  File "samcli/lib/build/app_builder.py", line 172, in build
  File "samcli/lib/build/build_strategy.py", line 42, in build
  File "samcli/lib/build/build_strategy.py", line 53, in _build_functions
  File "samcli/lib/build/build_strategy.py", line 129, in build_single_function_definition
  File "samcli/lib/build/app_builder.py", line 572, in _build_function
  File "samcli/lib/build/app_builder.py", line 705, in _build_function_on_container
  File "samcli/local/docker/container.py", line 308, in wait_for_logs
RuntimeError: Container does not exist. Cannot get logs for this container
[19020] Failed to execute script __main__

おそらく、 RuntimeError: Container does not exist. Cannot get logs for this container エラーが発生します。
ビルドコマンドのオプションで --use-container(実行環境をコンテナ上に作成するオプション)を付けているのですが、Cloud9の初期ディスクだと足りません。。。
(非常にわかりにくいエラーメッセージですね。。。)

なぜなら、、、

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        484M     0  484M   0% /dev
tmpfs           492M     0  492M   0% /dev/shm
tmpfs           492M  468K  491M   1% /run
tmpfs           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1       10G  8.2G  1.9G  82% /
tmpfs            99M     0   99M   0% /run/user/1000

すでにディスク容量の 82% しており、 1.9G しか残りがないからです。。。
(sam init で大量にディスクを消費したのではなく、Cloud9は最初からディスクが少ないようです。。。)

Cloud9ディスク拡張

では、Cloud9のディスクを増やしましょう。
Cloud9はEC2のLinux上で実現されているのでEC2のメニューからLinuxのディスク拡張操作を行います。
Linuxの場合、ディスク拡張は簡単で、Cloud9を作成すると自動的にEC2のメニューに専用のEC2が出来上がっているので、そのEC2を止めた状態で、EC2のボリュームのメニューのディスクの変更からサイズを増やすだけです。

image.png
image.png

以上です。

再度EC2を起動し、Cloud9のコンソールからディスクが増えていることを確認します

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        484M     0  484M   0% /dev
tmpfs           492M     0  492M   0% /dev/shm
tmpfs           492M  464K  491M   1% /run
tmpfs           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1       15G  8.2G  6.9G  55% /
tmpfs            99M     0   99M   0% /run/user/1000

使用率 55% 残り 6.9GB になりました。
では、改めてビルドしましょう。

再ビルド

$ cd ~/environment/sam-example/
$ sam build --use-container
Starting Build inside a container
Building codeuri: /home/ec2-user/environment/sam-example runtime: python3.9 metadata: {} architecture: x86_64 functions: ['HelloWorldFunction']

Fetching public.ecr.aws/sam/build-python3.9:latest-x86_64 Docker container image...............................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Mounting /home/ec2-user/environment/sam-example as /tmp/samcli/source:ro,delegated inside runtime container

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

requirements.txt file not found. Continuing the build without dependencies.
Running PythonPipBuilder:CopySource
$

今度は成功しました。
ビルド後のディスク容量も確認しておきましょう。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        484M     0  484M   0% /dev
tmpfs           492M     0  492M   0% /dev/shm
tmpfs           492M  464K  491M   1% /run
tmpfs           492M     0  492M   0% /sys/fs/cgroup
/dev/xvda1       15G   11G  4.6G  70% /
tmpfs            99M     0   99M   0% /run/user/1000
$ 

使用率 70% 残り 4.6GB になりました。
ビルド前と比較すると 2.3GB 使用するようですね。結構使いますね。。。

デプロイ

では、いよいよデプロイです。
sam deploy --guided --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND デプロイ時のガイド付き、ロール等は自動で作成するオプションを付けています。

実行コマンドは以下の1つ。

sam deploy --guided --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND

実行します。

$ sam deploy --guided --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND

Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Not found

        Setting default arguments for 'sam deploy'
        =========================================
        Stack Name [sam-app]: sam-sample
        AWS Region [ap-northeast-1]: 
        #Shows you resources changes to be deployed and require a 'Y' to initiate deploy
        Confirm changes before deploy [y/N]: y
        #SAM needs permission to be able to create roles to connect to the resources in your template
        Allow SAM CLI IAM role creation [Y/n]: y
        Save arguments to configuration file [Y/n]: y
        SAM configuration file [samconfig.toml]: 
        SAM configuration environment [default]: 

        Looking for resources needed for deployment:
         Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-bncdmvrv3w3n
         A different default S3 bucket can be set in samconfig.toml

        Saved arguments to config file
        Running 'sam deploy' for future deployments will use the parameters saved above.
        The above parameters can be changed by modifying samconfig.toml
        Learn more about samconfig.toml syntax at 
        https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html

Uploading to sam-sample/1c2f1111422c1a9a068bc3d12653d3c4  7913 / 7913  (100.00%)

        Deploying with following values
        ===============================
        Stack name                   : sam-sample
        Region                       : ap-northeast-1
        Confirm changeset            : True
        Deployment s3 bucket         : aws-sam-cli-managed-default-samclisourcebucket-bncdmvrv3w3n
        Capabilities                 : ["CAPABILITY_IAM", "CAPABILITY_AUTO_EXPAND"]
        Parameter overrides          : {}
        Signing Profiles             : {}

Initiating deployment
=====================
Uploading to sam-sample/cc7378c1e1ecf6a93a04bc81b3006223.template  768 / 768  (100.00%)

Waiting for changeset to be created..

CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation                               LogicalResourceId                       ResourceType                            Replacement                           
-------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add                                   HelloWorldFunctionRole                  AWS::IAM::Role                          N/A                                   
+ Add                                   HelloWorldFunction                      AWS::Lambda::Function                   N/A                                   
-------------------------------------------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:changeSet/samcli-deploy1651456975/245e03ef-407d-b1c6-43702e5cd1b3-e61b


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

2022-05-02 02:03:09 - Waiting for stack create/update to complete

CloudFormation events from changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                          ResourceType                            LogicalResourceId                       ResourceStatusReason                  
-------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS                      AWS::IAM::Role                          HelloWorldFunctionRole                  -                                     
CREATE_IN_PROGRESS                      AWS::IAM::Role                          HelloWorldFunctionRole                  Resource creation Initiated           
CREATE_COMPLETE                         AWS::IAM::Role                          HelloWorldFunctionRole                  -                                     
CREATE_IN_PROGRESS                      AWS::Lambda::Function                   HelloWorldFunction                      -                                     
CREATE_IN_PROGRESS                      AWS::Lambda::Function                   HelloWorldFunction                      Resource creation Initiated           
CREATE_COMPLETE                         AWS::Lambda::Function                   HelloWorldFunction                      -                                     
CREATE_COMPLETE                         AWS::CloudFormation::Stack              sam-sample                              -                                     
-------------------------------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs                                                                                                                                                      
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunctionIamRole                                                                                                                
Description         Implicit IAM Role created for Hello World function                                                                                       
Value               arn:aws:iam::XXXXXXXXXXXX:role/sam-sample-HelloWorldFunctionRole-11AUZUABC6ASS                                                           

Key                 HelloWorldFunction                                                                                                                       
Description         Hello World Lambda Function ARN                                                                                                          
Value               arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:sam-sample-HelloWorldFunction-y2SU9rABc52s                                           
--------------------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - sam-sample in ap-northeast-1
$ 

ガイド付きなので何回か質問があるので確認して選択しましょう。
Stack Name は、自分で決める任意の名称になります。

ちなみに次回以降の更新の時は選択内容が保持されるため sam deploy コマンドでサクッとデプロイできます。

$ sam deploy
Uploading to sam-sample/287342c7c37cb1d8020451b36647bd1f  452838 / 452838  (100.00%)

        Deploying with following values
        ===============================
        Stack name                   : sam-sample
        Region                       : ap-northeast-1
        Confirm changeset            : True
        Deployment s3 bucket         : aws-sam-cli-managed-default-samclisourcebucket-bncdmvrv3w3n
        Capabilities                 : ["CAPABILITY_IAM", "CAPABILITY_AUTO_EXPAND"]
        Parameter overrides          : {}
        Signing Profiles             : {}

Initiating deployment
=====================
Uploading to sam-sample/17c228278a608cc7c3f55da042cf1ae7.template  768 / 768  (100.00%)

Waiting for changeset to be created..

CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation                               LogicalResourceId                       ResourceType                            Replacement                           
-------------------------------------------------------------------------------------------------------------------------------------------------------------
* Modify                                HelloWorldFunction                      AWS::Lambda::Function                   False                                 
-------------------------------------------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:changeSet/samcli-deploy1651457546/3cc5876f-4d81-a290-7cbc821840ed-5d26


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

2022-05-02 02:12:41 - Waiting for stack create/update to complete

CloudFormation events from changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                          ResourceType                            LogicalResourceId                       ResourceStatusReason                  
-------------------------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_IN_PROGRESS                      AWS::Lambda::Function                   HelloWorldFunction                      -                                     
UPDATE_COMPLETE                         AWS::Lambda::Function                   HelloWorldFunction                      -                                     
UPDATE_COMPLETE_CLEANUP_IN_PROGRESS     AWS::CloudFormation::Stack              sam-sample                              -                                     
UPDATE_COMPLETE                         AWS::CloudFormation::Stack              sam-sample                              -                                     
-------------------------------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs                                                                                                                                                      
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunctionIamRole                                                                                                                
Description         Implicit IAM Role created for Hello World function                                                                                       
Value               arn:aws:iam::XXXXXXXXXXXX:role/sam-sample-HelloWorldFunctionRole-11AUZUANR6ASS                                                           

Key                 HelloWorldFunction                                                                                                                       
Description         Hello World Lambda Function ARN                                                                                                          
Value              arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:sam-sample-HelloWorldFunction-yrJDo52s2SU9                                         
--------------------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - sam-sample in ap-northeast-1
$ 

Outputs に作成されたLambda関数のARNが表示されているので確認して、AWSコンソールからLambdaを確認してみましょう。今回の例だとLambda関数名は sam-sample-HelloWorldFunction-yrJDo52s2SU9 になります。

デプロイされたLambdaの設定を画面を確認すると --capabilities CAPABILITY_IAM CAPABILITY_AUTO_EXPAND オプションのおかげで必要なロールが自動作成されていることがわかります。

image.png

もちろん app.py の内容がLambdaの コードソース 部分で確認できると思います。

image.png

あとは通常のコンソール操作のtestから動作確認可能です。簡単ですね。

まとめ

お疲れ様でした!

今回はLambdaでsamを使って作成してみました。簡単なLambdaであれば、AWSコンソールで十分なのですが、Lambdaと連携するAWSサービスが増えてくれるとAWSコンソールだけではどこに何を設定したか把握しきれず限界が来ると思います。
そこでプログラムを app.py に、環境設定を template.yml にしておけば非常に管理しやすくなりますね。(テキストなのでGitでバージョン管理したり差分比較したり簡単になります)
samを使ってプログラムに集中出来るサーバーレスLambdaがもっと便利になって、開発者はより業務ロジックに集中出来る世の中になれば良いなと思います(^^)

本投稿が少しでも皆さんの良いサーバーレスライフの助けになればと思います(_ _)