Serverless Frameworkを使ってKindleの価格を通知するLINE Botを作ってみた

# 概要

Amazonのほしい物リストをスクレイピングし、その情報を通知するLINE Botを作成しました。
特に **_Kindle_** 向けに最適化されています。

Amazon EventBridgeによる定期実行、もしくはメッセージに対する応答として、Kindle版と紙の本の価格やポイントを通知するLINE Botです。
![kindle-wishlist-to-line.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/668d0c63-e0b4-1ed3-d9e4-71cb8161882e.jpeg)

# プロジェクトの目的と動機

Kindleの値下げを見逃さないために開発しました。

Kindleの価格はセール時に大きく下がることがありますが、AmazonのスマホアプリではKindleの価格を確認できず、値下げを逃すことがしばしばありました。
その課題を解決するために、このLINE Botを作りました。

# 技術スタック
技術スタックは以下のようになっています。

![technology-stack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/f37b5220-c2cd-bf1d-b3d0-272dd3ed588a.png)
- **Node.js**: このプロジェクトはNode.jsで実装されています。
- **Puppeteer**: Amazonのほしい物リストから情報をスクレイピングするために使用します。
- **LINE Messaging API**: 通知をLINEに送信するために使用します。
- **Serverless Framework**: AWSへのデプロイと管理を容易にするために使用しています。
- **AWS Lambda**: バックエンドの処理を実行するために使用します。
- **API Gateway**: LINEのWebhookを処理するために使用します。
- **Amazon EventBridge**: 定期的な通知をスケジュールするために使用します。

# 構築手順

このプロジェクトでは、ほしい物リストのURLを環境変数で設定して利用します。
そのため、各ユーザーが自身のほしい物リストに合わせて設定を行う必要があります。

### 1. リポジトリのクローン
    $ git clone https://github.com/GorillaSwe/kindle-wishlist-to-line.git

### 2. Serverless Framework が使う IAMユーザーの作成 と AWS CLI の設定
AWSコンソールにログインし、IAMの**ユーザーの作成**をクリックし、任意のユーザー名を入力します。
![click-create-iam-user.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/6ff2b44b-1f3d-4b12-1e3d-e199071bf473.png)

**ポリシーを直接アタッチする**を選択し、**AdministratorAccess**を選択し、ユーザーを作成します。
![create-iam-user.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/3b9ed1ad-c592-c096-8c56-0e91f9365968.png)
IAMロールの権限を制限したい場合は以下サイトを参考に独自でセットアップして下さい。

https://www.serverless.com/framework/docs/providers/aws/guide/iam

ユーザーが作成できたら、**アクセスキーを作成**から**アクセスキー**と**シークレットアクセスキー**を作成します。
![create-aws-access-key.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/beb62a19-505d-d9f0-0934-fe627adfded5.png)

続いて、AWS CLIをインストールし、先ほど取得した**アクセスキー**と**シークレットアクセスキー**を入力しIAMユーザーの認証情報を設定します。

    $ aws configure
      AWS Access Key ID [None]: Your Access Key ID
      AWS Secret Access Key [None]: Your AWS Secret Access Key
      Default region name [None]: ap-northeast-1
      Default output format [None]: json

### 3. Line Bot の準備
まずは以下の公式サイトにアクセスします。

https://developers.line.biz/ja/

自分のLINEアカウントにログインします。
![login-line-developper.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/257c9ed4-c89e-c4bb-b31a-8b1087da09dc.png)

**作成**をクリックし、任意のプロバイダー名でプロバイダーを作成します。
![create-provider.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/3e98b746-0f06-a7a1-a0f5-1bca9f1ffbb3.png)

**Messaging API**を選択しチャネルを作成します。
チャネル名やアイコンは任意で設定して下さい。
![スクリーンショット 2024-02-10 21.10.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/0c794d0c-e3cf-eac0-b74e-4e6e0cb0893a.png)

チャネルが作成できたら、**チャネル基本設定**から**チャネルシークレット**・**ユーザーID**をメモしておきます。
![スクリーンショット 2024-02-11 15.49.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/8eaa93ce-4af2-05e1-9ebd-9ddd1766e34b.png)

次に、**Messaging API設定**から**チャネルアクセストークン**を発行し、メモしておきます。
![スクリーンショット 2024-02-11 16.05.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/d616fc34-d423-d49a-f588-2bdd72256db8.png)

最後に、**Messaging API設定**のQRコードを読み込み、LINE Botを登録しておきます。
![スクリーンショット 2024-02-11 16.09.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/f6763c49-735f-cb8b-5da7-f18847ebcbb4.png)

### 4. パッケージのインストール

    $ npm install
    
### 5. `.env` ファイルの準備

- プロジェクトルート直下に.envファイルを作成します。
- LINE Messaging APIの認証情報とAmazonのほしい物リストのURLを.envファイルに記入します。
- Amazonのほしい物リストが**公開**に設定されていることを確認します。

```dosini
# .env
AMAZON_WISHLIST_URL="Your Amazon Wishlist URL"
CHANNEL_ACCESS_TOKEN="Your LINE Access Token"
CHANNEL_SECRET="Your LINE Channel Secret"
USER_ID="Your LINE User ID"
```

### 6. AWS へのデプロイ
- 以下コマンドでAWSへのデプロイが実行され、API GatewayのエンドポイントURLが表示されます。

```dosini
$ npm run deploy
 （中略）
 Deploying kindle-wishlist-to-line to stage dev (ap-northeast-1)
 ✔ Service deployed to stack kindle-wishlist-to-line-dev (49s)

 endpoint: POST - https://XXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/webhook
  functions:
   lineWebhookHandler: kindle-wishlist-to-line-dev-lineWebhookHandler (71 MB)
   scheduledHandler: kindle-wishlist-to-line-dev-scheduledHandler (71 MB)
```

### 7. Webhook URL の設定

LINE Developersに再度ログインし、取得したAPI GatewayのエンドポイントURLを**Webhook URL**に設定します。

![スクリーンショット 2024-02-12 15.35.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/85a14a27-4ab0-072a-4295-96eed8bd9050.png)

**Webhookの利用**もONに設定します。
![スクリーンショット 2024-02-12 15.36.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/8e5d5247-fb42-07f9-43eb-4e18c11bc3ec.png)

### 8. 結果

Amazon EventBridgeによる定期実行、もしくはメッセージに対する応答時に以下のように出力されます。
![kindle-wishlist-to-line.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/458297/668d0c63-e0b4-1ed3-d9e4-71cb8161882e.jpeg)

### 定期実行のタイミング変更
`serverless.yml`でAmazon EventBridgeの定期実行を定義しています。
現状は日本時間の朝7時に設定していますが、変更したい場合は`rate: cron(0 22 * * ? *)`を修正して下さい。
Amazon EventBridgeでは、Cronで設定するイベント時刻はタイムゾーンがUTC（協定世界時）となっているため、日本標準時（JST）との時差を考慮して下さい。
```yml
functions:
  scheduledHandler:
    handler: src/handlers/scheduledHandler.handleScheduledEvent
    events:
      - schedule:
          rate: cron(0 22 * * ? *)
          enabled: true
```

詳細なコードは、GitHubのリポジトリで公開しています。
興味のある方は是非チェックしてみてください。

https://github.com/GorillaSwe/kindle-wishlist-to-line

## 注意点
Amazonへのスクレイピングを行う際は、アクセス頻度や速度に注意して下さい。
サーバーに過度な負荷をかけてしまうと、偽計業務妨害罪に問われる可能性があるので、使用する際は十分にご注意ください。

# まとめ
この記事では、Amazonのほしい物リストを通知するLINE Botの作成過程を説明しました。
間違っている箇所や疑問に思ったことがあれば、ぜひコメントをください！

最後まで読んでいただき、ありがとうございました。
次回は、スクレイピングの実装について具体的に深掘りしていきます。

(2024/2/15追記)
スクレイピングの実装について、深掘りした記事を作成しました。
こちらも読んでいただけると嬉しいです。

https://qiita.com/GorillaSwe/items/a2c815c8a2e252387808