0
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?

はじめに

この記事は②です。
①.https://qiita.com/minatopi/items/0230de1d4f888943bfff

API作ったけど使いにくーい(あらすじ)

①の記事でAPIを作ったんだけど、感想で述べた通りに、pico w使って液晶に表示させてみたんだけど、記事数が多くて読み込むの重いし、限定的に表示するようにしました。

目標

LNE、pico wの液晶で、閲覧数、ハート数の変化を検知できるようにする。

LINEで検知

https://qiita.com/tomorrow56/items/3fe31d709fcc0ba1c806
上の記事を参考にしました。
image.png
と、
image.png
を入手して、これをgithabを使って自分のアカウントに送ります。

作りたいもの

  • JSON取得
  • 前回データとの差分比較
  • 変化があればLINE通知
  • 最新状態を保存

全体の流れ

JSON取得
      │
      ▼
前回のデータ(cache.json)を読む
      │
      ▼
差分を比較
      │
      └─2人以上に閲覧されている。イイネが押されている。
           │
           ├─LINE通知
           ├─履歴(output.json)へ保存
           │
      ┌────┘
      │
      ├─それ以外
      │
30日たっているなら、そのデータは削除
      │
      ▼
最新データをcache.jsonへ保存
      │
      ▼
heartbeat.txt更新

https://qiita.com/kouz496/items/338cdf601bc3f291480c
│┤├┌└などの書き方。

コード説明

1. 定数の定義

URL = "https://minatopi.github.io/chanpro-api/data.json"

ACCESS_TOKEN = os.environ.get("LINE_TOKEN")
USER_ID = os.environ.get("LINE_USER_ID")

ここでは

  • 監視対象のJSON
  • LINE Messaging APIのアクセストークン
  • 通知先ユーザーID
    を設定しています。

アクセストークンは環境変数から取得しているため、ソースコードへ秘密情報を書かずに済みます。

2. LINE通知

def send_line(msg):

この関数はLINE Messaging APIを利用してPush通知を送ります。

送信するJSONは

{
  "to": "ユーザーID",
  "messages": [
    {
      "type": "text",
      "text": "通知内容"
    }
  ]
}

というシンプルな構造です。

エラーが発生してもプログラム全体は停止せず、

try:
    ...
except Exception:

で安全に処理しています。

3. JSONの読み込み・保存

load_json()

load_json(path, default)

ファイルが存在すれば読み込み、

存在しない・壊れている場合は

default

を返します。

これにより初回実行でもエラーになりません。

save_json()

tmp = path + ".tmp"

一旦

cache.json.tmp

へ保存してから

os.replace()

で置き換えています。

これはアトミック書き込みと呼ばれる方法で、

途中で停止してもJSONファイルが壊れにくくなります。

4. Heartbeat

write_heartbeat()

現在時刻を
heartbeat.txt

へ保存しています。

2025-06-28T10:15:21+00:00

のようなISO8601形式になります。

これによって

  • BOTが動いているか
  • GitHub Actionsが正常終了したか

を確認できます。

5. JSON取得

def fetch():

ここでは

requests.get(URL)

でJSONを取得しています。

取得後

return r.json()

によってPythonの辞書へ変換します。

6. 履歴の整理

cleanup_history()

履歴は増え続けるため、
30日前
より古いデータを削除しています。

cutoff = now - timedelta(days=30)

として比較しています。

7. メイン処理

main()

ここがプログラム全体の中心になります。

最初に
cache.json
と
output.json
を読み込みます。
続いて最新JSONを取得します。

8. 初回実行

初回は比較対象がありません。

そのため

if not cache:

で判定しています。

初回は

記事タイトル
いいね数
閲覧数

だけ保存して終了します。

通知は送りません。

9. 差分比較

各記事について

title

をキーとして比較します。

prev = cache.get(title)

で前回データを取得します。

変化条件は
likeが変わった
または
閲覧数が2以上増えた
です。

if (
    prev.get("like") != like
    or (
        views - prev.get("views") >= 2
    )
):

という条件になっています。

10. LINE通知

変化があれば

📌 更新検知
記事タイトル
👍 10 → 12
👀 150 → 168

のようなメッセージを生成します。

send_line(msg)

を呼ぶだけで通知できます。

11. 履歴保存

通知した内容は

history.append()

で保存します。
保存されるデータは

{
  "title": "...",
  "like_before": 10,
  "like_after": 12,
  "views_before": 100,
  "views_after": 108,
  "updated_at": "2025-06-28T..."
}

となります。
これにより後から変化履歴を確認できます。

12. 最後に保存

最後に

save_json(CACHE_FILE, new_cache)

で今回取得したデータを保存します。
次回実行時はこれが比較対象になります。

今回のソースコード

今回のソースコード↓
https://github.com/minatopi/LINE-chanpro-Surveillance
動いているはずのAPI的な奴↓
https://minatopi.github.io/LINE-chanpro-Surveillance/output.json

感想

  • LINEから、どれくらい見られているかわかりやすくなった。
  • pico wの液晶ディスプレイからも見れるようになった。
  • 30日後にはデータ消えるから、重くならない。
0
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
0
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?