🔖

私のブログの記事をWord Cloudにしてみた

に公開

今回は、私のテックブログの記事をWord Cloudにして、どんな言葉がよく使われているか調べてみました。この記事で164記事目であり、結構な数の記事を出してきたのでどんな言葉をよく使っているか調べたくなりやってみた次第です。

WordCloudとは?

WordCloudとはどのような単語がよく利用されているかをわかりやすく可視化するためのツールになります。画像内に文字が表示されるのですが、その文字が大きければ大きいほど利用頻度が多い単語になります。結果はこの後実際にお見せします。

WordCloud実装する

対象ドキュメント

私はZennの記事をGitHubにて管理しています。GitHubで管理する場合、フォルダ構成は以下のようになっています。

 articles
  aaa.md
  bbb.md
  ...
 books
 images
 scraps

articlesフォルダ以下に記事をmarkdownでおいているので、このファイル一覧を取得しそれを読み込むことでテキストを収集します。

環境構築

uvを利用して環境構築をします。

uv init zenn_blog_wordcloud -p 3.12
cd zenn_blog_wordcloud
uv add wordcloud matplotlib click

ソースコード

それでは実際にWordCloudを作成するコードの全体像をまずみてみましょう。

word_cloud.py
import click
import pathlib
from wordcloud import WordCloud
import matplotlib.pyplot as plt

TARGET_DIRECTORY = "/Users/user/Documents/Blog/zenn_publication/articles"
FONT_PATH = '/System/Library/Fonts/Supplemental/Arial Unicode.ttf'
STOPWORDS = {
    'the', 'is', 'and', 'a', 'of', "published", "topics", "idea", "0m", "tech", "Akasan", "jpg", "png", "gif"
}

def get_all_text() -> str:
    markdown_files = pathlib.Path(TARGET_DIRECTORY).rglob('*.md')
    all_text = ""

    for file_path in markdown_files:
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                all_text += f.read() + " "
        except Exception as e:
            print(f"ファイルの読み込みエラー: {file_path}, エラー: {e}")

    return all_text


def create_word_cloud(all_text: str, width: int, height: int, max_words: int):
    wordcloud = WordCloud(
        background_color='white',
        width=width,
        height=height,
        font_path=FONT_PATH,
        max_words=max_words,
        stopwords=STOPWORDS,
    ).generate(all_text)

    plt.figure(figsize=(10, 5))
    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis('off')
    plt.show()
    wordcloud.to_file('markdown_wordcloud.png')


@click.command()
@click.option("-W", "--width", type=int, default=1600)
@click.option("-H", "--height", type=int, default=800)
@click.option("-m", "--max_words", type=int, default=400)
def main(width: int, height: int, max_words: int):
    all_text = get_all_text()
    create_word_cloud(all_text, width=width, height=height, max_words=max_words)


if __name__ == "__main__":
    main()

まず、冒頭で定義している定数は以下の目的になります。

  • TARGET_DIRECTORY: テックブログのmarkdownが置かれているパス
  • FONT_PATH: WordCloudに利用するフォントのパス
  • STOPWORDS: WordCloudに含めないようにしたい単語一覧

次にマークダウンファイルを読み込んでテキストを取得するためにget_all_textを実装します。pathlibを用いて再帰的にマークダウンファイルを探し、見つかったファイルについてファイルを読み込みテキストを取得します。

def get_all_text() -> str:
    markdown_files = pathlib.Path(TARGET_DIRECTORY).rglob('*.md')
    all_text = ""

    for file_path in markdown_files:
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                all_text += f.read() + " "
        except Exception as e:
            print(f"ファイルの読み込みエラー: {file_path}, エラー: {e}")

    return all_text

最後にWordCloudを作る機能をcreate_word_cloudとして実装します。wordcloud.WordCloudクラスを利用すると、generateで与えた文字列からWordCloudを作成します。max_wordsに単語数を指定することで、出力に含める単語数を指定することができます。作成したwordcloudインスタンスはmatplotlibと組み合わせて使うことで画像として扱うことができます。また、wordcloud.to_fileとすることでmatplotlibを経由せずに画像を保存することができます。

def create_word_cloud(all_text: str, width: int, height: int, max_words: int):
    wordcloud = WordCloud(
        background_color='white',
        width=width,
        height=height,
        font_path=FONT_PATH,
        max_words=max_words,
        stopwords=STOPWORDS,
    ).generate(all_text)

    plt.figure(figsize=(10, 5))
    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis('off')
    plt.show()
    wordcloud.to_file('markdown_wordcloud.png')

プラスして、今回はclickを利用してコマンドラインから画像サイズやmax_wordsを指定できるようにしています。

WordCloudを作成

それでは先ほど実装したコードを実行してみましょう。

uv run word_cloud.py

するとmarkdown_wordcloud.pngファイルが作成されます。

結果をみるとpythonやwith、defなどPythonに関連する単語が多く利用されていることが確認できます。

まとめ

今回は私の記事を対象にWordCloudを作成してみました。今はPython関連のものが多いですが、年末にはこの状況が変わっていると思うのである程度日数が立った段階で改めて作ってみて比較してみようと思います。

Discussion