社内Slackの人気絵文字調査してみた


[社内で使われているSlackの人気絵文字を調査してみた](https://techblog.securesky-tech.com/entry/2019/01/08/) を読み、興味があったのでやってみました。

## やってみた

まるパクリにならないように

- カスタム絵文字を集計するモード
- デフォルト絵文字も含めた絵文字を集計するモード

を作成しました。

結果の前に軽くソースコードを紹介したいと思います。[**ソースコード**](https://github.com/keisuke111/slack_emoji_count)

### 引数でモードを判断

```python:
if len(sys.argv) == 2:
    channel = get_channel_list(params)

    if sys.argv[1] == 'all':        # 全絵文字のランキング
        emojis = count_emoji(channel, params)
    elif sys.argv[1] == 'custom':   # カスタム絵文字のランキング
        custom_emojis = get_custom_emoji(params)
        emojis = count_custom_emoji(channel, custom_emojis, params)
    else:
        print('$ python main.py <all or cumtom>')
        quit()
else:
    print('$ python main.py <all or cumtom>')
    quit()
```

実行時に渡した引数でモードを変更できるようにしたくてこのように実装しました。
本当はもう少し親切な（指定なしの時とか）動作にしたかったです。


### チャンネル一覧を取得

```python:main.py
def get_channel_list(params):
    r = requests.get("https://slack.com/api/channels.list", params=params)
    json = r.json()

    # PublicChannelのIDを格納
    channels = []

    for channel in json["channels"]:
        channels.append(channel["id"])

    print("パブリックチャンネル数: ", len(channels))
    return channels
```

2つのモードに共通する部分です。パブリックチャンネルのみ取得できます。
ちなみに8/12の朝の時点でチャンネル数は

```bash
パブリックチャンネル数:  699
```

でした。（多いかどうかはわからない！）

### 全ての絵文字モード

```python:main.py
def count_emoji(channels, param):
    # 絵文字を格納
    emojis = {}

    for channel in channels:
        params.update(count=1000, channel=channel)

        r = requests.get("https://slack.com/api/channels.history", params=params)
        json = r.json()

        # メッセージがない時
        if "messages" in json == False:
            continue

        # チャンネルのメッセージ分（MAX1000）
        for message in json["messages"]:
            if "reactions" in message:
                # ついたリアクションの種類分
                for reaction in message["reactions"]:
                    # 集計リストに追加
                    if reaction["name"] in emojis:
                        emojis[reaction["name"]] += reaction["count"]
                    else:
                        emojis[reaction["name"]] = reaction["count"]
        
        # 制限対策
        time.sleep(1)

    print("絵文字数: ", len(emojis))
    return emojis
```

SlackのAPIでは各チャンネルの最新1000件までしか取れないようなので、更新の多いチャンネル少ないチャンネルによって超正確な集計ではないんですが、問題ない程度だと思います。

あと、メッセージがないチャンネルがあったので（作成ミスで即アーカイブ）考慮しています。
API制限も詳しく書いてなくてわからなかったので少しsleep入れておきました:tea:

```
絵文字数:  2188
```

でした。

### カスタム絵文字だけモード

1. カスタム絵文字のリストを作成
2. 集計

という形で実装しました。

```python:main.py
def get_custom_emoji(params):
    r = requests.get("https://slack.com/api/emoji.list", params=params)
    json = r.json()

    # カスタム絵文字を格納
    emojis = {}

    for emoji in json["emoji"]:
        emojis.update({ f"{emoji}" : 0 })

    print("カスタム絵文字数: ", len(emojis))
    return emojis
```

```python:main.py
def count_custom_emoji(channels, emojis, params):
    for channel in channels:
        params.update(count=1000, channel=channel)

        r = requests.get("https://slack.com/api/channels.history", params=params)
        json = r.json()

        # メッセージがない時
        if "messages" in json == False:
            continue

        # チャンネルのメッセージ分（MAX1000）
        for message in json["messages"]:
            if "reactions" in message:
                # ついたリアクションの種類分
                for reaction in message["reactions"]:
                    # カスタム絵文字から探して数を更新
                    for emoji, count in emojis.items():
                        if emoji == reaction["name"]:
                            emojis[emoji] = count + reaction["count"]

        # 制限対策
        time.sleep(1)
    
    return emojis
```

全ての絵文字モードと大差ないんですが、事前に作成したカスタム絵文字のリストにある絵文字のみ加算していく
という感じになっています。

```
カスタム絵文字数:  1235
```

でした。

*2188 - 1235 =* ***953*** デフォルト絵文字は953個もあるんですね〜（あってるかな）

### ソート

流石に数が多すぎるのでソートの段階で上位30個に減らしました。

```python:main.py
def sort_30(emojis):
    emojis_sorted = sorted(emojis.items(), key=lambda x:x[1], reverse=True)[:30]

    return emojis_sorted
```

## 結果

### 全ての絵文字モード

<img width="89" alt="スクリーンショット 2020-08-12 17.40.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137649/9542f24b-0426-9844-f077-3d3d760d7f4a.png">

特に驚くところはなく使いやすい絵文字が上位にきているな、という印象でした。
とりあえず:eye:は付けがちですね。

:scream:が上位にいるのはなんでですかね？？？

### カスタム絵文字モード

<img width="89" alt="スクリーンショット 2020-08-12 17.38.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137649/95b3011b-151e-45e6-160e-47aa63ebf754.png">

ここでも特に語ることはないんですが、実は5ヶ月前に同じ集計をしたのでそちらと合わせてみてみたいと思います。

---

|2020/03|2020/08|
|---|---|
|||
|<img width="89" alt="スクリーンショット 2020-08-12 17.51.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137649/434463eb-b3c6-0222-f77f-c8c97ca416d1.png">| <img width="89" alt="スクリーンショット 2020-08-12 17.38.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137649/78ca6bec-73ff-e442-524b-78856f070c4d.png">

`:ohayou:` が急成長しているのはリモートワークになり勤務開始時に多く付けられているからですね。20倍くらいの増加です。
同じ理由で `:otsukaresama:` も5倍に伸びています。
声でのコミュニケーションが取れない分リアクションは良いですね:v:

## おわり

今回はSlackの絵文字の調査をしてみました。
次は最近できた絵文字で人気の絵文字とか調べてみたいですね！

ソースコードへのアドバイス待ってます:relaxed: