Slackでリアクションしてますか?
Slackのリアクションってその会社のカルチャーが表れる気がします。
ネクストではどんな絵文字が使われているんでしょうか?

Slack APIからメッセージを取得して絵文字リアクションをPythonで集計してみました。
すぐに使いたい人は記事を飛ばして以下からどうぞ!
https://github.com/NXSW/slack-reaction-counter
Slackアプリを作る
Slack APIを利用するため、集計用のSlackアプリを作りました。
Slack APIのYour Appsを開き、Create New Appを選びます。

今回は設定を再現しやすいように、From an app manifestから作りました。
使用したマニフェストはこちらです。
display_information:
name: Emoji Reaction Counter
description: 指定したチャンネルの絵文字リアクションを読み取り専用で集計します
oauth_config:
scopes:
user:
- channels:history
- channels:read
- groups:history
- groups:read
- emoji:read
settings:
org_deploy_enabled: false
socket_mode_enabled: false
token_rotation_enabled: false付けた権限は次の5つです。
channels:history: 公開チャンネルの投稿を読むchannels:read: 公開チャンネルの一覧を読むgroups:history: 非公開チャンネルの投稿を読むgroups:read: 非公開チャンネルの一覧を読むemoji:read: カスタム絵文字の一覧を読む
すべてUser Tokenの読み取り権限です。集計するだけなので、投稿やリアクションを変更する権限は付けませんでした。
権限を追加した場合は、Slackアプリをワークスペースへ再インストールして反映します。


アプリをワークスペースへインストールして次の手順に進みましょう。



User OAuth Tokenが発行されたらコピーしておきましょう。
Bot User OAuth Tokenではないので注意してください。2種類あります。 User OAuth Tokenです。
Pythonでメッセージを取得する
Slack公式のPython SDKを使いました。
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install "slack-sdk>=3.36.0,<4".env.exampleをコピーし、ローカル用の.envを作ります。
cp .env.example .env発行されたトークンを.envへ設定しました。
SLACK_USER_TOKEN=さっきのOAuth Token一度にすべてのメッセージが返るとは限らないため、next_cursorがなくなるまで繰り返します。
def fetch_history(client, channel, oldest, latest):
cursor = ""
while True:
response = client.conversations_history(
channel=channel,
oldest=str(oldest.timestamp()),
latest=str(latest.timestamp()),
inclusive=True,
limit=200,
cursor=cursor or None,
)
yield from response.get("messages", [])
cursor = (response.get("response_metadata") or {}).get("next_cursor", "")
if not cursor:
break全公開チャンネルを対象にすると、APIを呼ぶ回数も増えます。
レート制限を受けたときは、Slack SDKのRateLimitErrorRetryHandlerで最大5回まで待って再試行するようにしました。
client = WebClient(token=token)
client.retry_handlers.append(RateLimitErrorRetryHandler(max_retry_count=5))無制限に再試行すると終わらなくなるので、5回で打ち切ります。
スレッドの返信も取得する
conversations.historyだけでは、スレッド内の返信をすべて集計できません。
親メッセージにreply_countがあった場合は、conversations.repliesも呼び出します。
ここで少し気を付ける必要がありました。
conversations.repliesの結果にはスレッドの親メッセージも含まれます。そのまま足すと、親メッセージのリアクションを二重に数えてしまいます。
for message in response.get("messages", []):
if message.get("ts") != parent_ts:
yield messageまた、期間中の返信でも、スレッドの親メッセージは期間より前に投稿されていることがあります。
今回は指定期間の30日前まで遡り、返信のある親メッセージを探すようにしました。完全にすべての古いスレッドを探すわけではありません。必要なら実行時に日数を増やせます。
リアクション数を足す
メッセージにreactionsがあれば、絵文字名ごとにcountを足します。
for reaction in message.get("reactions") or []:
name = reaction.get("name")
count = reaction.get("count")
counts[name] += count
message_counts[name] += 1
channel_counts[channel][name] += countusersの長さではなく、countを使いました。
Slackのreactions.listの説明によると、usersには全員が入っていない場合がありますが、countは全ユーザー分を表すようです。
実行してみる
作成したプログラムを実行します。
--all-channelsを付けると、conversations.listでチャンネル一覧を取得します。公開チャンネルはすべて、非公開チャンネルは自分が参加しているものを集計します。
python3 count_reactions.py \
--all-channels \
--since 2026-08-01 \
--until 2026-08-31集計から外したいチャンネルがある場合は、--exclude-channelへチャンネル名またはチャンネルIDを指定します。複数ある場合は繰り返します。先頭の#はなくても大丈夫です。
python3 count_reactions.py \
--all-channels \
--exclude-channel チャンネル名 \
--exclude-channel チャンネルIDでも \
--since 2026-08-01 \
--until 2026-08-31一部のチャンネルだけを集計する場合は、--channelを指定します。複数指定もできます。
python3 count_reactions.py \
--channel チャンネル名 \
--channel チャンネルID \
--since 2026-08-01 \
--until 2026-08-31
確認したメッセージ: 59884
リアクション付き: 4561
リアクション合計: 79576万メッセージ!60,000回もやりとりしていることにおどろいた。
結果はresults/へ出力されます。
results/
├── ranking.csv
├── ranking.md
└── summary.jsonここ1年で一番使われていた絵文字ランキング!
結果はこちらです。
| 順位 | 絵文字 | リアクション数 | 付いたメッセージ数 | カスタム絵文字 |
|---|---|---|---|---|
| 1 | 1535 | 1037 | ○ | |
| 2 | 1135 | 954 | – | |
| 3 | 703 | 597 | – | |
| 4 | 331 | 247 | ○ | |
| 5 | 269 | 192 | ○ | |
| 6 | 238 | 204 | – | |
| 7 | 196 | 138 | – | |
| 8 | 195 | 70 | ○ | |
| 9 | 184 | 161 | ○ | |
| 10 | | 161 | 128 | ○ |
ほうほうほう。
まじめか!
会社の色が出ていますね〜
感謝深い集団。
1位が
はなんだか素敵ですね。
やってみた感想
95チャンネルの過去1年分のリアクションを集計するのはめちゃくちゃ時間かかりましたw(体感30分くらい)
すぐ使える内容になっていますので、ぜひ使ってみてください!
https://github.com/NXSW/slack-reaction-counter

ここまで読んでいただき、ありがとうございます。もしこの記事の技術や考え方に少しでも興味を持っていただけたら、ネクストのエンジニアと気軽に話してみませんか。
- 選考ではありません
- 履歴書不要
- 技術の話が中心
- 所要時間30分程度
- オンラインOK