Blog

PythonでSlackの絵文字ランキングを作ってみた話

絵文字めっちゃ使いますよね

今やIT系の会社以外でも業務に欠かせないツールとなったSlack。
皆さんも利用しているかと思います。

ご存知の通り、Slackの「絵文字」機能はオリジナルを作って使用出来るのがマジでスーパーウルトラ便利ですよね。巷では、LINEスタンプを超えたコミュニケーションコンテンツ!Twitterに何故ないのか不思議なくらいハイソサエティー!などと言われています。本当かは知りません、巷ってどこですか。

Slackの絵文字でその会社の風土が分かる、と言われて久しいですが実はあながち間違いではないような気もしております。本日はSlack絵文字の使用頻度ランキングから弊社マイスター・ギルドを紐解いて行こうかと思います。そう、オレ達はいつだって見切り発車、合言葉は「とりあえずやってみよう」

まずは集計してみよう!

集計システムの開発は弊社エンジニアKさんが担当してくださいました。
ありがとうございます!

使用言語:Python
動作環境:Python 3.7
開発環境:Anaconda

<集計対象>
・3/30~4/29までの1ヶ月間
・パブリックチャンネルのみ
・本文、コメント、リアクション

下準備

●Slackから対象期間のメッセージをダウンロードする(説明割愛)

●データはJSONファイルで出力されるので構造を把握する

本文:
blocksリスト > elementsリスト > オブジェクト > “type”の値が「emoji」 > “name”の値に絵文字の名前が記述されている
コメント:
同上。ただしコメントには”root”オブジェクトがありその中に返信をした本文の情報があるのでそこで使用した絵文字は重複なので無視する
リアクション:
本文、コメントともに、”reactions”リスト内に絵文字の名前と回数が書かれている

●上記の情報を取得して使用絵文字とそれぞれの使用回数を求める

出力結果のフォーマット

●集計結果は設定ファイルで指定したフォルダに「emoji.csv」として出力される
●「:絵文字の名前:,使用回数」のフォーマットで使用回数昇順で縦に出力する
●結果をSlackにコピペしやすいよう絵文字の名前の前後に「:」を追加して出力する

設定ファイル

{
    "Input":{
        "FolderPath":"", ←jsonファイルが入っているフォルダのパス
        "Range":30, ←集計範囲(単位:日) 実施日より設定した過去以降は対象外
        "IgnoreList":[ ←無視する絵文字リスト
            {
                "name":"seiko"
            },
            {
                "name":"mitori_cool"
            },
            {
                "name":"mitori"
            },
            {
                "name":"elt"
            },
            {
                "name":"新たに無視する絵文字の名前"
            }
        ]
    },
    "Output":{
        "FolderPath":"" ←集計結果のcsvファイルを出力するフォルダパス
    }
}

処理ソース

#jsonファイルが範囲内かチェック
def datetimeCheck(jsoudata , rimit):
    #ファイルパスから拡張子なしのファイル名のみ取得
    filename=os.path.splitext(os.path.basename(jsoudata))[0]

    if len(filename) <10:
        #10文字以下の時は対象外
        #今回のデータだとchannels.json,users.json
        return False
    elif len(filename) >10:
     #10文字以上の時は後ろから10文字取得
        filename=filename[-10:]
    try:
     #比較する為、文字列からdatetimeに変換
        target = datetime.datetime.strptime(filename,"%Y-%m-%d")
    except ValueError:
     #変換時にエラーが出るときはファイル名の後ろ10文字がyyyy-mm-ddの文字列でないと判断し対象外
       #今回のデータだとintegration_logs.json
        return False

    #範囲内チェック
    if  target < rimit:
        #指定した範囲より過去のものは対象外
        return False
    else:
        return True


def main():
    #設定ファイル読み込み
    json_open = open('setting.json','r')
    json_load = json.load(json_open)
    #指定されたフォルダからjsonファイルのみパスを取得(Python3.5から**を使った再帰的な処理がサポートされた)
    jsonList = list(glob.glob( json_load['Input']['FolderPath']+"/**/*.json",recursive=True))
    outputFolder = json_load['Output']['FolderPath']
    #今日の日付取得
    today = datetime.datetime.today()
    #対象範囲のリミットとなる日を求める
    rimit = today-datetime.timedelta(days=json_load['Input']['Range'])
    ignoreList = []
    for i in json_load['Input']['IgnoreList']:
        ignoreList.append(i["name"])

    #使われている絵文字の名前格納用リスト
    masterList=[]

    #jsonファイル数ループ
    for jsoudata in jsonList:
       #範囲チェック
        if datetimeCheck(jsoudata,rimit) == False:
            continue

        #jsonファイルを開く(slackのJasonファイルは日本語を含むのでencodingを指定しないとエラーになる)
        fileopen = open(jsoudata,encoding='utf-8')
        data=json.load(fileopen)
        #blocksまたはreactionsオブジェクトに書かれている絵文字の情報取得
        try:
            for i in data:
                for t in i['blocks']:
                    for s in t['elements']:
                        for l in s['elements']:
                            if l['type']=="emoji":
                                if ignoreList.count(l['name'])==0:
                                    #リストに名前追加(前後に":"を追加)
                                    masterList.append(":"+l['name']+":")

                for m in i['reactions']:
                    if ignoreList.count(m['name'])==0:
                        #カウント数ループ
                        for c in range(m['count']):
                            #リストに名前追加(前後に":"を追加)
                            masterList.append(":"+m['name']+":")
        except KeyError:
            pass

    #リスト内にそれぞれの絵文字の名前が何個入っているか求める
    emojis = collections.Counter(masterList)
    #絵文字のリストを使用回数の昇順に並べなおす
    emojis = sorted(emojis.items(),reverse = True,key=lambda x:x[1])

    #出力用フォルダがなければ作成
    if os.path.exists(outputFolder) == False:
        os.mkdir(outputFolder)

    #csvファイルに結果を出力する
    with open(outputFolder +"/emoji.csv",'w',newline="") as csvfile:
        writer = csv.writer(csvfile)
        writer.writerows(emojis)

使い方

1. 設定ファイルに必要事項を記述
2. Anaconda powershell promptを起動
3. cdコマンド使ってソースがあるフォルダに移動
4. 「python mian.py」を実行
5. 結果が書かれたemoji.csvが出力される
6. csvファイルを開いて(excel推奨)絵文字の名前と回数をSlackにコピペ

    ・設定ファイル(setting.json)は、ソース(mian.py)と同階層に置くこと
    ・SlackのJSONファイルのフォーマットが変更したときは使えない

    という事で、結果発表

    モギャーーーーーーン!!!!

    Slackの絵文字ランキングから会社の風土を紐解く、なんて言ってましたが途中かなり真面目な技術記事みたくなってしまってビックリしましたね、私も驚きました。直近1ヶ月、パブリックチャンネルで使用された絵文字のランキングはご覧の通りになりました。

    1位「いいね!」はやはりというか、まあそうだろうな、といった所でしょうか。Slack内にニュースや新技術などの記事が投稿された時や、ちょっとした一言なんかにとりあえず使えるキングオブ絵文字ですね。4位の👍、5位「すごい!」12位「ステキ!」辺りも同様のシーンでよく使用されている印象です。

    2位の「AFK」は今ならではの絵文字で、Away From Keyboard の略、つまり「離席します」の絵文字ですね。3月よりリモートワークを実施している弊社ではSlackでも自身の状況を報告することで円滑な業務を心がけております。11位はAFK後に使用する「もどりました」絵文字で、この2つは対なのですがランキングに差があるのは、絵文字が作られたタイミングだと思われます。

    6位は意外なところで大泣きの顔文字。きっと誰かが「IE対応かよ・・・」とか、「IEでエラー出てる」とか、「またIEおかしなってる」とか投稿したところにリアクションされた絵文字なんでしょうね。ひとつの絵文字からエンジニアさん達の苦労が知れますね。

    7位「草」は弊社代表が発言するとよく付く絵文字です。代表の投稿に草ばっか生やしてる会社ってどうなんって話ですが、代表もなかなかトリッキーな発言が多かったりしますので、その辺は引き分けなのかもしれないです。筆者が最近とても好きだったのは、18:30の終業を告げようと思ったらまだ18:29だった代表、です。そら草も生えますよ。

    絵文字から紐解く会社の風土

    まあ、分からないですよね。

    ただ、ランキングをご覧いただければ伝わるかと思いますが、否定的な絵文字はほとんどありません。同意や尊重、お互いに鼓舞し合うようなポジティブなものが多いです。パブリックチャンネルだけのランキングなので多少の遠慮は感じられますが、たかが絵文字、されど絵文字、ちょっとしたコミュニケーションも大切にしているのが我々マイスター・ギルドです。誰かが新しい絵文字を作ると、それで割と盛り上がっちゃう辺りも好感度高くないですか?

    ランキングに出てこないちょっと変わった絵文字なんかもたくさんありますので(むしろそっちの方が多い)、それはまた別の機会にご紹介させていただければと思います。

    マイスター・ギルドでは一緒に楽しく仕事をしてくれる仲間を募集しています!開発が大好きな方、新しいことがやってみたい方、ぜひ私達のギルドに参加してください!おもしろいSlack絵文字を思いついたら是非ご応募ください!

    【詳しくはこちら(WANTEDLY)】

    MeisterGuild(マイスター・ギルド)広報

    最先端技術のMEISTERを目指し、お互い切磋琢磨するGUILD、になりたい株式会社マイスター・ギルドです。Webシステム/サービス開発、スマホアプリ開発、AR/VR/MR開発など、さまざまな情報を発信します。

    Related Entry