電気使用量を毎日LINE通知！AWS Lambda × Seleniumで自動化 ⚡

## 🎯 目的

最近、電気代がどんどん高くなっていますよね？
毎日、サイトにログインして前日の電気使用量を確認するのが日課になっていましたが、正直面倒くさい…。🤦‍♂️

そこで、**バッチ処理で毎日LINEに通知する仕組み**を作れば楽になるし、
今まで触れたことのない技術を試せる良い機会になると思い、挑戦してみました！💡

この記事はその備忘録です。🔖

---

## 🛠 システム構成

仕組みはシンプルです。以下のようなフローで動作します。

📌 **電気使用量をスクレイピング** → **AWS Lambda で取得＆保存** → **LINE Notify で通知！**

![tokyo-gas.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3785830/39aeb223-3074-8271-7dc2-b34071734be6.png)

---

## 🔔 LINE Notifyの設定

公式ドキュメントを参考に、サクッと設定完了！

👉 [LINE Notifyの設定方法](https://zenn.dev/protoout/articles/18-line-notify-setup)

テスト通知も問題なく成功！🎉

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3785830/f0bb1238-237d-9829-7fd5-820195f2aa95.png)

---

## 🏗 Lambda関数の作成

### 📍 スクレイピング用Lambda

Pythonの `selenium` を使って東京ガスのサイトから電気使用量を取得します。

```python
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import datetime
import boto3

driver = webdriver.Chrome()
driver.get('https://members.tokyo-gas.co.jp/')
time.sleep(10)

driver.find_element(By.NAME,"loginId").send_keys("")
driver.find_element(By.NAME,"password").send_keys("")
driver.find_element(By.ID,"submit-btn").click()
time.sleep(5)

driver.get('https://members.tokyo-gas.co.jp/usage?tab=electricity')
time.sleep(5)
driver.find_element(By.ID,"segmented-button-daily").click()
time.sleep(5)

daily = driver.find_element(By.XPATH,'//*[@id="mtg-karte-electricity"]/div/div/div[2]/div/div[1]/div[2]/div[2]/div/div[1]/div').text
print(daily)

driver.quit()

today = datetime.datetime.now()
year_month = today.strftime("%Y%m")
day = today.strftime("%d")
key = f'{year_month}/{day}.txt'

s3 = boto3.client('s3')
s3.put_object(Bucket='tokyo-gas-electricity', Key=key, Body=daily)
```

💡 **ローカルでは動いたのにLambdaではエラー発生…😱**

原因を調べたところ、Lambdaの環境には `selenium` がプリインストールされていないことが判明！

💡 **解決策：Docker+ECRを使う！**

[参考記事](https://tks2.co.jp/2023/12/02/aws-lambda-selenium-python312/)

最終的にECR経由でLambdaをデプロイすることで解決！✨

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3785830/c00d34eb-40a6-60b8-d516-11e007729de0.png)

### 📍 LINE通知用Lambda

```python
import json
import boto3
import datetime
import urllib.request

def lambda_handler(event, context):
    s3 = boto3.client('s3')
    TOKEN = '作成したアクセストークン'
    api_url = 'https://notify-api.line.me/api/notify'
    BUCKET_NAME = 'tokyo-gas-electricity'
    
    yesterday = datetime.datetime.now() - datetime.timedelta(days=1)
    year = str(yesterday.year)
    month = str(yesterday.month).zfill(2)
    day = str(yesterday.day).zfill(2)
    weekdays_jp = ["日", "月", "火", "水", "木", "金", "土"]
    weekday_jp = weekdays_jp[int(yesterday.strftime("%w"))]
    
    object_key = f'{year}/{month}/{day}.txt'
    try:
        response = s3.get_object(Bucket=BUCKET_NAME, Key=object_key)
        file_content = response['Body'].read().decode('utf-8')
        
        message = f"\n{month}/{day}({weekday_jp})の電気使用量は\n{file_content}です！"
        send_line_notify(api_url, TOKEN, message)
        
        return {'statusCode': 200, 'body': 'Message sent successfully'}
    except Exception as e:
        return {'statusCode': 400, 'body': str(e)}

def send_line_notify(api_url, token, message):
    request_headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Authorization': 'Bearer ' + token
    }
    params = {'message': message}
    data = urllib.parse.urlencode(params).encode('ascii')
    req = urllib.request.Request(api_url, headers=request_headers, data=data, method='POST')
    urllib.request.urlopen(req)
```

---

## ✅ 結果

EventBridgeでスケジュール実行した結果…

✅ **無事にLINE通知が届いた！🎉**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3785830/5ce744b8-3dab-17e6-fd9a-e87bff26d2d8.png)

---

## 🔥 まとめ

💡 **学びポイント**
1. AWS Lambda で `selenium` を使うには Docker+ECR が便利！
2. LINE Notify の設定は簡単にできる！
3. EventBridge でLambdaを定期実行できる！

🚀 **今後のアップデート**
- **電気料金の計算**
- **過去の使用量と比較**

今後も改良して、より便利なシステムにしていきたいと思います！💪

---

最後まで読んでいただき、ありがとうございました！🙌