1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS LambdaとMessaging APIでLINEに自動通知機能を設定

Last updated at Posted at 2025-01-18

作ったもの

お出かけイベントサイトから情報を取得し、LINEで自動配信する仕組み

全体の流れ

[AWSアカウント作成 & ログイン]
[Messaging APIを利用する準備]
[実行するスクリプトの作成]
[Lambda関数の作成]
[ライブラリ (requests, bs4, jpholiday, line-bot-sdk) の準備]
[LINEチャネルアクセストークン、通知先のユーザーIDを環境変数に設定]
[EventBridge でのスケジュールルールを作成]
[動作確認、テスト]



  • [実行するスクリプトの作成]
    Pythonでイベントサイトの情報をスクレイピングするスクリプトを作成
#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import requests
from bs4 import BeautifulSoup
from datetime import date, timedelta
import jpholiday
from urllib.parse import urlencode

from linebot import LineBotApi
from linebot.models import TextSendMessage

# 1. 週末の日付計算
def get_weekend_dates():
    """
    毎週金曜に実行される想定。
    翌日(土曜)を開始日、日曜を一旦の終了日とし、
    月曜が祝日の場合はそちらを終了日にする。
    """
    # 毎週の金曜の日付
    today = date.today()
    # 土曜
    start_date = today + timedelta(days=1)
    # 日曜
    sunday = start_date + timedelta(days=1)
    # 月曜
    monday = sunday + timedelta(days=1)
    
    if jpholiday.is_holiday(monday):
        end_date = monday
    else:
        end_date = sunday    
    return start_date, end_date

# 2. いこーよ (iko-yo.net) のイベント検索ページからHTMLを取得
def fetch_ikoyo_events(start_date, end_date):
    """
    いこーよ の検索パラメータに合わせてrequestsを送る。
    start_date / end_date は datetime.date 型。
    
    """
    
    base_url = "https://iko-yo.net/events"
    
    # クエリパラメータの設定
    params = {
        "end_date[day]":     end_date.day,
        "end_date[month]":   end_date.month,
        "end_date[year]":    end_date.year,
        
        # prefecture_ids[] は固定値 (沖縄)  適宜変更
        "prefecture_ids[]": "47",
        
        "start_date[day]":   start_date.day,
        "start_date[month]": start_date.month,
        "start_date[year]":  start_date.year, 
    }
    
    query_str = urlencode(params, doseq=True)
    final_url = f"{base_url}?{query_str}"
    
    response = requests.get(final_url)
    if response.status_code != 200:
        return None
    return response.text

# 3. HTMLを解析してイベント情報を抽出
def parse_ikoyo_events(html):
    """
    いこーよ イベント検索のHTMLをBeautifulSoupで解析し、
    タイトル、開催日程、場所、URL等をリストにまとめて返す。
    
    実際のHTML構造に合わせてクラス名等を適宜変更してください。
    """
    soup = BeautifulSoup(html, "html.parser")
    events = []
    
    for item in soup.select(".c-grid__item"):
        
        a_tag = item.select_one("a")
        
        title_tag = item.select_one(".c-grid__title.c-link--underline.p-event-list__title")
        
        date_tag = item.select_one(".c-container--xs.u-text--bold.u-text--orange_e")
        
        place_tag = item.select_one(".c-container--xs.u-text--sm.u-text--gray_8")
        
        if not title_tag:
            continue
        
        title = title_tag.get_text(strip=True)
        link = ""
        if a_tag and a_tag.has_attr("href"):
            link = "https://iko-yo.net" + a_tag["href"]
            
            
        date_str = date_tag.get_text(strip=True) if date_tag else "日程不明"
        place_str = place_tag.get_text(strip=True) if place_tag else "場所不明"
        
        events.append({
            "title": title,
            "link": link,
            "date": date_str,
            "place": place_str,
        })
    
    return events
        
    
# 4. メイン処理 スクレイピング後、Messaging APIでLINE通知
def main():
    # 1. 週末の日付を決定 (土曜〜日曜 or 祝日なら月曜)
    start_date, end_date = get_weekend_dates()
    
    # 2. いこーよからHTML取得 (例: 都道府県指定なし→全国)
    html = fetch_ikoyo_events(start_date, end_date)
    if not html:
        print("イベント情報の取得に失敗しました")
        return
    
    # 3. スクレイピングでイベント情報をリスト化
    events = parse_ikoyo_events(html)
    if not events:
        print("イベント情報が見つかりませんでした")
    else:
        lines = [f"【週末のおでかけ情報】\n{start_date} 〜 {end_date}\n"]
        for i, e in enumerate(events, start=1):
            msg = (
                f"{i}. {e['title']}\n"
                f"   日程 : {e['date']}\n"
                f"   場所 : {e['place']}\n"
                f"   URL  : {e['link']}\n"
            )
            lines.append(msg)     
        text_message = "\n".join(lines)
    
    # 4. LINE Messaging API: プッシュ通知
    #    - 「YOUR_CHANNEL_ACCESS_TOKEN」 → 実際のチャネルアクセストークンに置き換え Lambda環境変数に設定
    #    - 「USER_ID」 → 送りたい相手のユーザID(またはグループID) Lambda環境変数に設定
    
    # 環境変数から読み込む
    channel_access_token = os.environ["LINE_ACCESS_TOKEN"]
    user_id = os.environ["LINE_USER_ID"]
    
    line_bot_api = LineBotApi(channel_access_token)
    
    # 5. メッセージ送信
    line_bot_api.push_message(
        user_id, 
        TextSendMessage(text=text_message)
        )
    print("LINE通知完了")
    
#  Lambda用のエントリポイント
def lambda_handler(event, context):
    """
    Lambdaで実行されたときに呼ばれる関数。
    main()を呼ぶだけでOK。
    """
    main()
    return {
        "statusCode": 200,
        "body": "Success"
    }
# ローカルで python main.py 実行時
if __name__ == "__main__":
    main()

  • [ライブラリ (requests, bs4, jpholiday, line-bot-sdk) の準備]
    Lambda Layers を使って設定

1.ローカル環境でフォルダを用意し、必要なライブラリをインストール

mkdir layer-dir
cd layer-dir
pip install requests beautifulsoup4 jpholiday line-bot-sdk -t python

2.zipに圧縮

zip -r layer.zip python

3.Lambdaでレイヤーの作成
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/creating-deleting-layers.html




1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?