2022年1月10日月曜日

Pythonで絵文字のワードクラウドを作成する

PythonではWordcloudを使うと簡単にワードクラウドを作成できる(Pythonで国会会議録からワードクラウドを作成する)。ワークラウドは文章中のに出現する単語をその出現数などに応じて大きさなどを変えて配置するものだが、今回は絵文字だけを使ったワードクラウド(絵文字クラウド)を作成してみる。


環境

WSL2(Ubuntu20.04)。

$ lsb_release -dr
Description:    Ubuntu 20.04.3 LTS
Release:        20.04
$ python3 -V
Python 3.8.10


データの収集

絵文字クラウドを作成するには絵文字を含むテキストが必要になる。そこでTwitter APIを利用してツイートを収集する。今回はTweepy4でリアルタイムツイートを取得するのようにTweepyを利用する。以下コードでツイートのランダムサンプリングを1000件取得してpickle形式で保存しておく。

import pickle

import tweepy

# Twitter APIの認証情報
# Twitterの開発者向けのページで取得したキーとトークンを使う
CONSUMER_KEY = 'Consumer Key'
CONSUMER_SECRET = 'Consumer Secret'
ACCESS_TOKEN = 'Access Token'
ACCESS_TOKEN_SECRET = 'Access Token Secret'

# 取得するツイート数
TWEET_COUNT = 1000

# 取得したツイートを保存するパス
PKL_PATH = './tweet.pkl'


class TwStream(tweepy.Stream):
    texts = []

    def on_status(self, status):
        # status(APIで取得できるデータ)を受け取ったときにon_statusが実行される
        print('-------------------------')
        # スクリーンネームとツイートを表示
        print(f'{len(self.texts)} @{status.author.screen_name} {status.text}')

        self.texts.append(status.text)

        if len(self.texts) >= TWEET_COUNT:
            self.disconnect()


def main():
    twstream = TwStream(
        CONSUMER_KEY,
        CONSUMER_SECRET,
        ACCESS_TOKEN,
        ACCESS_TOKEN_SECRET
    )

    # 日本語ツイートに限定してランダムサンプリングを取得
    twstream.sample(languages=['ja'])

    with open(PKL_PATH, 'wb') as f:
        pickle.dump(twstream.texts, f)


if __name__ == '__main__':
    main()


必要なモジュールなどのインストール

絵文字クラウドの作成に必要なPythonモジュールなどをインストールする。

$ pip3 install wordcloud emoji

$ pip3 list | grep -e wordcloud -e emoji
emoji                    1.2.0
wordcloud                1.8.1


絵文字クラウドの作成

準備ができたので絵文字クラウドを作成する。保存したツイートからから絵文字を抽出して絵文字ごとの出現頻度を集計し、ワードクラウドを作成する。ただし、pngなどの画像に保存するとフォントが表示されない絵文字があるのでSVGで保存する。

import pickle
from collections import Counter

from wordcloud import WordCloud
import emoji

# 取得したツイートを保存したパス
PKL_PATH = './tweet.pkl'

# 最小絵文字頻度
MIN_COUNT = 3


def extract_emojis(text):
    # テキストから絵文字を抽出
    return [c for c in text if c in emoji.UNICODE_EMOJI['en']]


def counter(texts):
    # 絵文字がないテキストを除外
    col = [Counter(t) for t in texts if len(t) > 0]

    # 各テキストの絵文字数を合計
    return sum(col, Counter())


def load_tweets():
    with open(PKL_PATH, 'rb') as f:
        texts = pickle.load(f)

    print(f'len={len(texts)}')
    return texts


def create_word_cloud(features):
    # 絵文字クラウドの作成
    wordcloud = WordCloud(
        background_color='white',
        width=300,
        height=300,
        max_font_size=200
    )
    wordcloud.generate_from_frequencies(frequencies=features)

    # 絵文字クラウドを保存
    # pngなどの画像に直接保存するとフォントが正常に表示されない絵文字があるのでSVGで保存
    # wordcloud.to_file("./emojicloud.png")
    wordcloud_svg = wordcloud.to_svg(embed_font=True)
    with open('./emojicloud.svg', 'w') as f:
        f.write(wordcloud_svg)


def main():
    texts = load_tweets()
    emojis = [extract_emojis(t) for t in texts]
    emoji_freq = counter(emojis)

    # 出現頻度MIN_COUNT以上に制限
    features = {term: cnt for term, cnt in emoji_freq.items() if cnt >= MIN_COUNT}
    print(features)

    create_word_cloud(features)


if __name__ == '__main__':
    main()


作成したSVGをWindowsのChrome、Firefoxで表示するとそれぞれ以下の通り。フォントが違うのか微妙な違いがある。



0 件のコメント:

コメントを投稿