夜田たんの知的生活実践

ほそく・ながく・ゆるく続くブログを目指します(だいたい週一で更新中)

2020年に投稿した記事でワードクラウドを作ってみた

wordcloud-all-rev

昨年もやっていますが、今年はブログを移転して静的サイトになったことからコードを改修しました。

前回からの改修点

  • 元ファイルをBloggerから抽出したxmlファイルではなく、Pelicanで生成したローカルのhtmlファイルに変更
  • xmlモジュールではなくBeautiful Soupでパースする
  • 品詞別のワードクラウドを作ってみる

コード

まずは完成品から。
Beautiful Soupだとかなりコードがコンパクトになりました!

# -*- coding: utf-8 -*-

import logging
import sys
import datetime
import glob
from bs4 import BeautifulSoup
from janome.tokenizer import Tokenizer
from wordcloud import WordCloud
from tqdm import tqdm

# =======================================================
# folder
SRC_DIR = r"C:\path-to-html-folder"
DST_DIR = r"C:\path-to-output-folder"
# setting for wordcloud
FONT_PATH = r"C:\Windows\Fonts\UDDigiKyokashoN-R.ttc"
WC_WIDTH = 300
WC_HEIGHT = 300
BACKGROUND = 'darkslategray'
COLOR_MAP = 'Pastel1'
STOP_WORDS = {u'自分',
              }
# html elements omitted
DELETE_TAGS = ['figure', 'code']

# =======================================================
# logging
logger = logging.getLogger('WordCloud')
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(formatter)
logger.addHandler(ch)


# =======================================================
# get html files
def get_html_list():
    name = sys._getframe().f_code.co_name
    logger.info(name + '_start')

    # glob
    htmllist = glob.glob(SRC_DIR + '\\**\\*.html', recursive=True)
    return htmllist


# =======================================================
# get main section from html files
def parse_html(html_list):
    name = sys._getframe().f_code.co_name
    logger.info(name + '_start')

    text = ''

    for htmlfile in tqdm(html_list):
        # exclude index.html
        if 'index.html' not in str(htmlfile):
            soup = BeautifulSoup(open(htmlfile, mode='r', encoding='utf-8'), 'html.parser')

            # get main section(article -> section)
            honbun = soup.article.section

            # delete figure & code tags
            delete_tags = honbun.findAll(DELETE_TAGS)
            if delete_tags:
                for tag in delete_tags:
                    tag.decompose()

            # delete html tags
            text += honbun.get_text()

    return text


# =======================================================
# tokenize
def keitaiso(text):
    name = sys._getframe().f_code.co_name
    logger.info(name + '_start')

    hinshi = ['名詞', '動詞', '形容詞', '副詞']
    pure_text = [''] * len(hinshi)

    tok = Tokenizer()
    tokens = tok.tokenize(text)
    for token in tqdm(tokens):
        # create list for each word class
        for i in range(len(hinshi)):
            if token.part_of_speech.split(',')[0] == hinshi[i]:
                pure_text[i] += ' ' + token.base_form

    # create dict for each word class
    pure_text_dict = {}
    for i in range(len(hinshi)):
        pure_text_dict[hinshi[i]] = pure_text[i]
    # create all text
    pure_text_dict['all'] = ' '.join(pure_text)

    return pure_text_dict


# =======================================================
# create word cloud
def make_wc(text):
    name = sys._getframe().f_code.co_name
    logger.info(name + '_start')

    now = datetime.datetime.now()
    nowstring = now.strftime('%Y%m%d') + '-' + now.strftime('%H%M%S')

    # setting for word cloud
    wc = WordCloud(
        width=WC_WIDTH, height=WC_HEIGHT,
        background_color=BACKGROUND,
        colormap=COLOR_MAP,
        font_path=FONT_PATH,
        prefer_horizontal=1,
        stopwords=STOP_WORDS,
        max_words=100,
        min_font_size=6)

    # create png file for each word class
    for t in tqdm(text.keys()):
        wc.generate(text[t])
        wc.to_file(DST_DIR + '\\' + 'word_cloud_' + t + '_' + nowstring + '.png')


# =======================================================
# main
def main():
    html_list = get_html_list()
    text = parse_html(html_list)
    pure_text = keitaiso(text)
    make_wc(pure_text)


if __name__ == '__main__':
    main()

出来上がった画像

除外ワードほぼなし

ソースのSTOP_WORDSで除外ワードが設定できますが、ほぼノーガードでのワードクラウドはこんな感じです。

wordcloud-all

すべて

wordcloud-noun

名詞

wordcloud-verb

動詞

wordcloud-adjective

形容詞

wordcloud-adverb

副詞

これを見ると、特に副詞の特徴が顕著ですね……。
ついつい使ってしまう単語がまるわかりです。
動詞や形容詞はイマイチ特徴がでにくかったので、除外ワードを設定してみました。

除外ワード設定

名詞・動詞・形容詞の除外ワードに下記を設定して、画像を再作成してみます。

STOP_WORDS = {u'自分', u'の', u'こと', u'よう', u'ため',
              u'ない',
              u'する', u'いる', u'ある', u'なる', u'れる', u'られる', }

wordcloud-all-rev

すべて

wordcloud-noun-rev

名詞

wordcloud-verb-rev

動詞

wordcloud-adjective-rev

形容詞

これで結構ブログ記事の特徴が出てきました。
無意識に使いがちな(特にたいした意味のない)単語などは、意識して取り除いていけば、文章力も上がるような気がしています。

参考資料

大変お世話になりました!