2020年に投稿した記事でワードクラウドを作ってみた
昨年もやっていますが、今年はブログを移転して静的サイトになったことからコードを改修しました。
前回からの改修点
- 元ファイルを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
で除外ワードが設定できますが、ほぼノーガードでのワードクラウドはこんな感じです。
これを見ると、特に副詞の特徴が顕著ですね……。
ついつい使ってしまう単語がまるわかりです。
動詞や形容詞はイマイチ特徴がでにくかったので、除外ワードを設定してみました。
除外ワード設定
名詞・動詞・形容詞の除外ワードに下記を設定して、画像を再作成してみます。
STOP_WORDS = {u'自分', u'の', u'こと', u'よう', u'ため',
u'ない',
u'する', u'いる', u'ある', u'なる', u'れる', u'られる', }
これで結構ブログ記事の特徴が出てきました。
無意識に使いがちな(特にたいした意味のない)単語などは、意識して取り除いていけば、文章力も上がるような気がしています。
参考資料
大変お世話になりました!