😸

Web サイト監視システムを最速で構築する

2021/10/14に公開

ある Web サイトに対して、DoS にならない程度の常識的な間隔(例えば 10 分に 1 回のアクセス)で定期アクセスし、
更新があれば通知するような監視システムをパッと作るにはどうすればよいかを考えた。


通知媒体に関しては色々考えられるが、自分の場合 LINE や Twitter、Discord よりも Slack の方が反応しやすいので、Slack に通知させることにした。
Slack は Incoming Webhook というのが昔からあってお手軽だったが、最近は SDK もちゃんと用意されているのでこっちの方がつかいやすいと思う。

https://qiita.com/seratch/items/8f93fd0bf815b0b1d557

それで、Slack のトークンを記事に書いてある通りに入手したら、それを SLACK_API_TOKEN という環境変数に入れて、
差分通知のスクリプト check.py を以下のように書いておく。

from difflib import context_diff
import os

import requests
from slack_sdk.web import WebClient
client = WebClient(os.environ["SLACK_API_TOKEN"])

# 監視対象のリンク
url = "https://XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

# 古い方のファイルを読み込む
old_data = open("dump", "r").read().splitlines(keepends=True)
# 改行文字を除去
old_data = [line.rstrip() for line in old_data]

# 新しいファイルをダウンロードする
new_data = requests.get(url).text.splitlines(keepends=True)
# 改行文字を除去
new_data = [line.rstrip() for line in new_data]


if old_data != new_data:
    out = []
    for line in context_diff(old_data, new_data):
        out.append(line)
    
    client.chat_postMessage(text="".join(out), channel="#ZZZZZZZZZZZZZZ")

    with open("dump", "w") as f:
        f.write("".join(new_data))

dump という名前のファイルにサイトのデータを入れることにしたので、最初にこの名前で空ファイルを作っておく。
これでこのスクリプトを動かすと、うまく Slack に通知されることが確認できる。


次にこれを定期実行させることを考える。サーバーを持っていれば crontab を使えばよいのだが、
サーバーレスでやるにはどうするか? ここでは GitHub Actions を検討する。

上記の check.pydump ファイルを適当なリポジトリに突っ込む。
次に GitHub Actions のファイルを適当に用意する。

name: cron

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  schedule:
    - cron:  '*/10 0-8 * * *'
    
env:
  SLACK_API_TOKEN: ${{ secrets.SLACK_API_TOKEN }}

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up Python 3.9
      uses: actions/setup-python@v2
      with:
        python-version: 3.9
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install requests
        pip install slack_sdk
    - name: run checker
      run: |
        python check.py
        
    - name: commit & push
      run: |
        if ! git diff --exit-code --quiet
        then
          git config user.name github-actions
          git config user.email github-actions@github.com
          git add .
          git commit -m "Update"
          git push
        fi

'*/10 0-8 * * *' と書いたのは、日本時間で 9 時台から 17 時台に 10 分置きに動かすという意味である。JST ではなく UTC で記述することに注意する。
また、GitHub Actions の利用枠にも注意する。現在は無料枠では 2,000 分/月 であるので、これを満たすように時間を考える。
このスクリプトは 1 回動かすのに 30 秒くらいかかったので、1ヶ月に使う時間はおよそ

0.5 (分) * 6 (回/時間) * 9 (時間) * 30 (日) = 810 (分)

となる。色々なリポジトリで色々 GitHub Actions を動かしていると利用枠はあっという間に消えるので注意されたし。

Discussion