自分のためだけの新着お笑いライブ通知Botを作りました

### つくったもの

**推し芸人info（仮名）**
お気に入りの芸人を登録すると、その芸人さんの新着ライブを毎日LINEで教えてくれます。
前々からこういうのあったらいいなと思っていたものの、各サイトがなかなか機能追加してくれないので自分で作りました。
![推し芸人info_3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119757/e4607586-7397-623e-c657-51bc1789f43a.gif)

プロダクト名は`推し芸人info`（仮名）です。
infoというのは芸人のファンが有志で運営しているTwitterアカウントの通称で、その芸人のライブ・メディア出演情報をまとめてくれるものです。
たとえば[マヂカルラブリーinfo](https://twitter.com/madilove_info)さんは非常に熱量が高く、infoさんご自身にファンがついているほどです。

今は完全に自分用なので、需要があればWebサービス化しようかなと思ってます。Web上でお気に入り芸人を登録するとLINEで通知される、みたいな。

### なぜ作ったか

モチベーションはとても単純で、好きな芸人さんのライブ情報を低コストで漏らさずチェックしたいからです。
もともとお笑いが好きなのと、在宅ワークで時間に余裕ができたので、1,2週間に1回ほどのペースで配信ライブを観るようになりました。吉本興業など各社も昨年ごろから配信ライブに力を入れており、ライブ数もかなり増えています。

一方で、自分の好きな芸人の出演ライブを漏らさず見つける手段は「定期的にサイトで検索する」「Twitterを見張る」くらいしかなく、よく見るサイトに通知機能もありません。人力でのサイト巡回はコストが高いので、機械にやってもらおうと思って作りました。


### システム構成

![スクリーンショット 2022-01-25 2.16.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119757/d969e0bf-d7ba-42a9-ffc1-a564579e3bc8.png)
ざっくり以下の流れで動かしています。

1. [Scrapy](https://scrapy.org/)で各チケット販売サイトをクロールしてS3に保存
1. 別のバッチでライブ情報を読み込んで新着ライブを検知
1. LINEの[Messaging API](https://developers.line.biz/ja/services/messaging-api/)で新着ライブ情報を毎朝個人アカウントに送信

Scrapyと通知バッチは[Amazon Lightsail](https://aws.amazon.com/jp/lightsail/)というAWSのVPSで動かしています。

現在対応しているチケット販売サイトは、配信ライブ大手の`FANY Online Ticket`と`K-PRO`の2つだけですが、まだまだ網羅できていないので今後追加していくつもりです。`ワラリー！`というサイトもありますが、お笑いライブ版Wikipediaのようなもので公式の情報ではないので、今回はスルーしました。

https://online-ticket.yoshimoto.co.jp/

https://kpro-web.com/

https://warally.info/


### クローリング・通知部分の処理概要

ここからは各機能の細々としたことを書きます。

#### Scrapyで各サイトをクローリング

* Scrapyでプロジェクトを作り、その中でサイトごとにSpiderを実装
* Spiderを毎朝5時ごろに動かして、その時点で掲載されているライブ情報全件をS3に保存
    * 件数はFANY・K-PROともに毎日数百件ほど

Scrapyの基本的な使い方はいろんな書籍や記事があるので割愛します。この本を読めば大体わかると思います。

https://www.amazon.co.jp/dp/4297107384/

運用する中で「クロール結果を通知してほしい（ただし各Spider内に同じ処理を書きたくない）」という場面があり、それに関しては別で書いています。

https://qiita.com/oddgai/items/934524dfa1a8f5b0cfaf

#### 新着ライブを検知してLINE送信

毎朝9時に以下の処理を動かしています。

* PandasでS3から昨日と今日のライブ情報を読み込む
* 昨日と今日を比較して、お気に入りの芸人が出演している新着ライブを抽出
    * お気に入りの芸人はtxtファイルで管理
* 新着ライブの`DataFrame`からMessaging APIで送る用のJSONを作成
* 個人のLINEアカウントに新着ライブ情報を送信

API用のLINEアカウント作成やAPIの使い方については、[公式のリファレンス](https://developers.line.biz/ja/services/messaging-api/)が充実しているのでそちらを読むとよいと思います。「こういうJSONを書くとこういうメッセージになる」というシミュレーターも用意されていて、テンプレートも充実しているので非常に助かりました。

https://developers.line.biz/flex-simulator/

メッセージの見た目は悩みましたが、10件ライブがあったときに10回メッセージを送りたくはなかったので、下のように横に情報をスクロールできる`Flex Message`の`carousel`というタイプにしました。
![スクリーンショット 2022-01-25 3.40.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119757/70829685-1309-4ecb-a280-3d54cd0e3675.png)
ちなみに、Pythonでは下のコードを書くと上のメッセージが送られます（LINEビジネスアカウントのトークン情報が必要です）。

```python
from linebot import LineBotApi
from linebot.exceptions import LineBotApiError
from linebot.models import FlexSendMessage, TextSendMessage

line_bot_api = LineBotApi("CHANNEL_ACCESS_TOKEN")

message_json = {
  "type": "carousel",
  "contents": [
    {
      "type": "bubble",
      "hero": {
        "type": "image",
        "url": "https://cdn.shopify.com/s/files/1/0396/3151/9898/products/0101_aa0b6f5c-6e78-44ed-a21c-c8de8702a874_1024x1024@2x.jpg?v=1639629433",
        "size": "full",
        "aspectMode": "cover",
        "action": {
          "type": "uri",
          "label": "action",
          "uri": "https://online-ticket.yoshimoto.co.jp/collections/selling-well/products/madicalnoyose220101"
        },
        "aspectRatio": "16:9"
      },
      "body": {
        "type": "box",
        "layout": "vertical",
        "spacing": "xs",
        "contents": [
          {
            "type": "text",
            "text": "マヂカルラブリーno寄席",
            "wrap": true,
            "weight": "bold",
            "size": "lg"
          },
          {
            "type": "text",
            "text": "■出演者",
            "size": "sm"
          },
          {
            "type": "text",
            "text": "マヂカルラブリー、ゴー☆ジャス、ザ・ギース、モダンタイムス、ランジャタイ、永野、脳みそ夫",
            "size": "xs",
            "wrap": true
          },
          {
            "type": "text",
            "text": "■日時",
            "size": "sm"
          },
          {
            "type": "text",
            "text": "1/1（土）配信開始21:30　配信終了22:30 \n※見逃し視聴は1/8（土）21:30まで \n※チケットの販売は見逃し視聴終了日の昼12:00まで",
            "wrap": true,
            "size": "xs"
          }
        ],
        "alignItems": "center",
        "justifyContent": "space-between"
      },
      "footer": {
        "type": "box",
        "layout": "vertical",
        "spacing": "sm",
        "contents": [
          {
            "type": "button",
            "style": "link",
            "action": {
              "type": "uri",
              "label": "詳細を見る",
              "uri": "https://online-ticket.yoshimoto.co.jp/collections/selling-well/products/madicalnoyose220101"
            },
            "height": "sm"
          }
        ],
        "offsetTop": "-10px",
        "paddingAll": "none"
      }
    },
	{
      "type": "bubble",
      "hero": {
        "type": "image",
        "url": "https://cdn.shopify.com/s/files/1/0396/3151/9898/products/22.1.18__10___3_1024x1024@2x.jpg?v=1642140188",
        "size": "full",
        "aspectMode": "cover",
        "action": {
          "type": "uri",
          "label": "action",
          "uri": "https://online-ticket.yoshimoto.co.jp/products/%E7%B2%97%E5%93%81%E3%81%AB%E5%8B%9D%E3%81%A3%E3%81%9F%E3%82%89%EF%BC%91%EF%BC%90%E4%B8%87%E5%86%86-1-18-19-00?mls_content=nana"
        },
        "aspectRatio": "16:9"
      },
      "body": {
        "type": "box",
        "layout": "vertical",
        "spacing": "xs",
        "contents": [
          {
            "type": "text",
            "text": "粗品に勝ったら１０万円",
            "wrap": true,
            "weight": "bold",
            "size": "lg"
          },
          {
            "type": "text",
            "text": "■出演者",
            "size": "sm"
          },
          {
            "type": "text",
            "text": "霜降り明星 粗品、オダウエダ、軟水、10億円、真空ジェシカ（人力舎）...",
            "size": "xs",
            "wrap": true
          },
          {
            "type": "text",
            "text": "■日時",
            "size": "sm"
          },
          {
            "type": "text",
            "text": "1/18（火）配信開始19:00　配信終了21:00\n※見逃し視聴は1/25（火）19:00まで\n※チケットの販売は見逃し視聴終了日の昼12:00まで",
            "wrap": true,
            "size": "xs"
          }
        ],
        "alignItems": "center",
        "justifyContent": "space-between"
      },
      "footer": {
        "type": "box",
        "layout": "vertical",
        "spacing": "sm",
        "contents": [
          {
            "type": "button",
            "style": "link",
            "action": {
              "type": "uri",
              "label": "詳細を見る",
              "uri": "https://online-ticket.yoshimoto.co.jp/products/%E7%B2%97%E5%93%81%E3%81%AB%E5%8B%9D%E3%81%A3%E3%81%9F%E3%82%89%EF%BC%91%EF%BC%90%E4%B8%87%E5%86%86-1-18-19-00?mls_content=nana"
            },
            "height": "sm"
          }
        ],
        "offsetTop": "-10px",
        "paddingAll": "none"
      }
    }
  ]
}
line_bot_api.push_message(to="USER_ID", messages=FlexSendMessage(alt_text="新着ライブがあります！", contents=message_json))
```


### 感想

自分が欲しかったものをほぼイメージ通りに作ることができたので満足です。
冒頭にも書いたように、今は1人用の構成なのでBotとして公開するのは難しいですが、需要があればWebサービス化しようかなと思ってます。