Pythonで Word Cloud を使ってみたことを書きました。
*Word Cloud とは
文章データを可視化する手法のひとつで、文章のなかで出現頻度が高い文字を大きく、出現頻度が低い文字を小さくして分布をわかりやすくした図のことです。*環境
- MacOS
- Python 2.7.14
- matplotlib 2.2.3
- mecab-python 0.996
- requests 2.20.1
- wordcloud 1.5.0
- beautifulsoup4 4.6.3
- image 1.5.27
*各種ライブラリのインストール
任意の作業用のフォルダに移動し、仮想環境を作成します。$ virtualenv env
$ source env/bin/activate
Word Cloud のライブラリをインストールします。
GitHubにパッケージが上がっているので、クローンしてからインストールします。
$ git clone https://github.com/amueller/word_cloud
$ cd word_cloud/
$ python setup.py install
各種ライブラリをインストールします。
$ brew install mecab-ipadic
$ pip install mecab-python
$ pip install beautifulsoup4
$ pip install requests
$ pip install -U matplotlib
$ pip install image
$ pip install requests[security]
*テキストデータを準備
今回は PyCon2018の発表資料について書かれている Qiita の記事から文章データを取得させていただきました。取得は、HTML や XML のパーサである BeautifulSoup を使ってWebスクレイピングをしています。
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import requests
url = 'https://qiita.com/kobaboy/items/46ff9f19b9ea5638fa8e'
res = requests.get(url)
soup = BeautifulSoup(res.text)
text = soup.body.section.get_text().replace('\n', '').replace('\t', '')
*テキストを単語区切りに編集
文章を単語ごとに区切るために、形態素解析をするための解析エンジンである MeCab を使います。MeCab.Tagger()
のパラメーターに-Owakati
を指定すると分かち書き、-Ochasen
を指定すると形態素解析をしてくれます。今回は形態素解析をして、単語と品詞のセットをリストで取得しています。
# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup
import requests
import MeCab as mc <--追加
url = 'https://qiita.com/kobaboy/items/46ff9f19b9ea5638fa8e'
res = requests.get(url)
soup = BeautifulSoup(res.text)
text = soup.body.section.get_text().replace('\n', '').replace('\t', '')
# ------- 追加 -------
st_text = text.encode('utf-8')
tagger = mc.Tagger('-Ochasen')
words = tagger.parse(st_text)
<出力結果>
PyCon PyCon PyCon 名詞-固有名詞-組織
JP JP JP 名詞-一般
2018 2018 2018 名詞-数
ひろがる ヒロガル ひろがる 動詞-自立 五段・ラ行 基本形
Python Python Python 名詞-一般
の ノ の 助詞-連体化
資料 シリョウ 資料 名詞-一般
...
*Word Cloud を作成
WordCloud()
にパラメータを指定して作成します。パラメータの説明は下記に載っています。
stop_words=
を指定することで、意味のない単語を除外することができます。font_path=
に日本語のフォントを指定しないと、文字化けをしてしまいます。今回はMacにデフォルトで用意されているフォントを使用しましたが、日本語のフォントであれば他でも大丈夫です。今回は指定していませんが、
WordCloud()
の引数にmask=
で画像を指定すると、その形で Word Cloud を作成してくれます。Word Cloud を作成したら、
word_cloud.to_file()
で指定したフォルダに結果を書き出すことができます。# -*- coding: utf-8 -*-
from wordcloud import WordCloud
from bs4 import BeautifulSoup
import requests
import MeCab as mc
from os import path <--追加
# 文章データを取得
url = 'https://qiita.com/kobaboy/items/46ff9f19b9ea5638fa8e'
res = requests.get(url)
soup = BeautifulSoup(res.text)
text = soup.body.section.get_text().replace('\n', '').replace('\t', '')
# 形態素解析
st_text = text.encode('utf-8')
tagger = mc.Tagger('-Ochasen')
words = tagger.parse(st_text)
# ------- 追加 -------
stop_words = [u'てる', u'いる', u'なる', u'れる', u'する', u'ある', u'こと', u'これ', u'さん', u'して', \
u'くれる', u'やる', u'くださる', u'そう', u'せる', u'した', u'思う', \
u'それ', u'ここ', u'ちゃん', u'くん', u'', u'て', u'に', u'を', u'は', u'の', u'が', u'と', u'た', u'し', u'で', \
u'ない', u'も', u'な', u'い', u'か', u'ので', u'よう', u'']
# WordCloudを作成
word_cloud = WordCloud(
font_path='/System/Library/Fonts/ヒラギノ明朝 ProN.ttc',
background_color="white",
width=900,
height=500,
stopwords=set(stop_words)).generate(keywords)
# ファイルに書き出し
word_cloud.to_file(path.join(path.dirname(__file__), 'sample.png'))
<出力結果>
*図に描画
ファイルに書き出すだけでも十分なのですが、作成したWord Cloud を図に描画してみます。図の描画は、Pythonでグラフや画像を作成するライブラリである
matplotlib
を使います。今回はOSの標準ビューアで表示させています。# -*- coding: utf-8 -*-
import matplotlib <--追加
matplotlib.use('TkAgg') <--追加
import matplotlib.pyplot as plt <--追加
from wordcloud import WordCloud
from bs4 import BeautifulSoup
import requests
import MeCab as mc
from os import path
# 文章データを取得
url = 'https://qiita.com/kobaboy/items/46ff9f19b9ea5638fa8e'
res = requests.get(url)
soup = BeautifulSoup(res.text)
text = soup.body.section.get_text().replace('\n', '').replace('\t', '')
# 形態素解析
st_text = text.encode('utf-8')
tagger = mc.Tagger('-Ochasen')
words = tagger.parse(st_text)
stop_words = [u'てる', u'いる', u'なる', u'れる', u'する', u'ある', u'こと', u'これ', u'さん', u'して', \
u'くれる', u'やる', u'くださる', u'そう', u'せる', u'した', u'思う', \
u'それ', u'ここ', u'ちゃん', u'くん', u'', u'て', u'に', u'を', u'は', u'の', u'が', u'と', u'た', u'し', u'で', \
u'ない', u'も', u'な', u'い', u'か', u'ので', u'よう', u'']
# WordCloudを作成
word_cloud = WordCloud(
font_path='/System/Library/Fonts/ヒラギノ明朝 ProN.ttc',
background_color="white",
width=900,
height=500,
stopwords=set(stop_words)).generate(keywords)
# ファイルに書き出し
word_cloud.to_file(path.join(path.dirname(__file__), 'sample.png'))
# ------- 追加 -------
# 図に描画
plt.imshow(word_cloud)
plt.axis("off")
plt.figure(figsize=(15, 12))
plt.show()
<出力結果>
*所感
作成した図に重複した文字があったり、意味のない文字が混じっているのが気になりますが、とりあえず Word Cloud を作成することができました。正確な結果を表示させるために、もう少し色々試してみようと思います。また、今回試したWebページの文章以外にも、CSVデータやAPIでの取得結果などといった色々なデータでも試してみたいと思います。
*まとめ
コードを少し綺麗にしたものを載せておきます。# -*- coding: utf-8 -*-
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from wordcloud import WordCloud
from bs4 import BeautifulSoup
import requests
import MeCab as mc
from os import path
def get_analysis_mecab_words(text):
st_text = text.encode('utf-8')
tagger = mc.Tagger('-Ochasen')
words = tagger.parse(st_text)
outputs = []
for w in words.split('\n'):
word = w.split('\t')
if word[0] == 'EOS':
break
word_type = word[3].split('-')[0]
if word_type in ['形容詞', '動詞', '名詞', '副詞']:
outputs.append(word[0])
return outputs
def get_keywords(url):
res = requests.get(url)
soup = BeautifulSoup(res.text)
text = soup.body.section.get_text().replace('\n', '').replace('\t', '')
outputs = get_analysis_mecab_words(text)
return ' '.join(outputs).decode('utf-8')
def view_image(word_cloud):
word_cloud.to_file(path.join(path.dirname(__file__), 'sample.png'))
plt.imshow(word_cloud)
plt.axis("off")
plt.figure(figsize=(15, 12))
plt.show()
if __name__ == '__main__':
url = 'https://qiita.com/kobaboy/items/46ff9f19b9ea5638fa8e'
keywords = get_keywords(url)
stop_words = [u'てる', u'いる', u'なる', u'れる', u'する', u'ある', u'こと', u'これ', u'さん', u'して', \
u'くれる', u'やる', u'くださる', u'そう', u'せる', u'した', u'思う', \
u'それ', u'ここ', u'ちゃん', u'くん', u'', u'て', u'に', u'を', u'は', u'の', u'が', u'と', u'た', u'し', u'で', \
u'ない', u'も', u'な', u'い', u'か', u'ので', u'よう', u'']
word_cloud = WordCloud(
font_path='/System/Library/Fonts/ヒラギノ明朝 ProN.ttc',
background_color="white",
width=900,
height=500,
stopwords=set(stop_words)).generate(keywords)
view_image(word_cloud)