#概要
物語の舞台が地元だったりすると、それだけで読んでしまうタイプなので
COTOHAの固有表現抽出を、利用して物語の舞台を、抽出・図示するものを作成してみた。
#処理の流れ
1.青空文庫より任意の小説を取得
2.COTOHA API(固有表現抽出)で地名(LOC)のみ取得
3.取得した地名を利用して、WordCroudで図示する。
#環境
Google Colaboratory
#ライブラリ
・個別にインストールが必要なものはwordcloudのみ。
(Google Colaboratoryは事前にある程度のライブラリがインストール済みなので、便利です)
以下のコマンドを実行すれば、事前準備は完了です。
!pip install wordcloud
!apt-get -y install fonts-ipafont-gothic
!rm /root/.cache/matplotlib/fontlist-v300.json
!git clone --branch master --depth 1 https://github.com/aozorabunko/aozorabunko.git
#コード
1.青空文庫より任意の小説を取得する部分
from bs4 import BeautifulSoup
def get_word():
#クローンしたhtmlからパスを指定(サンプルは太宰治のグッド・バイ)
path_to_html='aozorabunko/cards/000035/files/258_20179.html'
#BeautifulSoupでhtml解析
with open(path_to_html, 'rb') as html:
soup = BeautifulSoup(html, 'lxml')
main_text = soup.find("div", class_='main_text')
for yomigana in main_text.find_all(["rp","h4","rt"]):
yomigana.decompose()
sentences = [line.strip() for line in main_text.text.strip().splitlines()]
aozora_text=','.join(sentences)
#cotoha apiコール用に文字数で分割(1800文字ごと)
aozora_text_list = [aozora_text[i: i+1800] for i in range(0, len(aozora_text), 1800)]
return aozora_text_list
また、COTOHAが実行できるように、文字列を1800文字ごとに分割して配列化してます。
(ちゃんと調べてないですが2000文字でダメで、1800文字で実行したらイケたので。。ちゃんと調べろよ)
2.COTOHA_APIを呼び出しする部分
import os
import urllib.request
import json
import configparser
import codecs
import sys
import time
client_id = "各自のクライアントID"
client_secret = "各自のシークレットキー"
developer_api_base_url = "https://api.ce-cotoha.com/api/dev/nlp/"
access_token_publish_url = "https://api.ce-cotoha.com/v1/oauth/accesstokens"
def cotoha_call(sentence):
# アクセストークン取得
def getAccessToken():
url = access_token_publish_url
headers={
"Content-Type": "application/json;charset=UTF-8"
}
data = {
"grantType": "client_credentials",
"clientId": client_id,
"clientSecret": client_secret
}
data = json.dumps(data).encode()
req = urllib.request.Request(url, data, headers)
res = urllib.request.urlopen(req)
res_body = res.read()
res_body = json.loads(res_body)
access_token = res_body["access_token"]
return access_token
# API URL指定(固有表現抽出)
base_url_footer = "v1/ne"
url = developer_api_base_url + base_url_footer
headers={
"Authorization": "Bearer " + getAccessToken(), #access_token,
"Content-Type": "application/json;charset=UTF-8",
}
data = {
"sentence": sentence
}
data = json.dumps(data).encode()
time.sleep(0.5)
req = urllib.request.Request(url, data, headers)
try:
res = urllib.request.urlopen(req)
# リクエストでエラーが発生した場合の処理
except urllib.request.HTTPError as e:
# ステータスコードが401 Unauthorized or 500 Internal Server Errorならアクセストークンを取得し直して再リクエスト
if e.code == 401 or 500:
access_token = getAccessToken()
headers["Authorization"] = "Bearer " + access_token
time.sleep(0.5)
req = urllib.request.Request(url, data, headers)
res = urllib.request.urlopen(req)
# 401 or 500 以外のエラーなら原因を表示
else:
print ("<Error> " + e.reason)
#sys.exit()
res_body = res.read()
res_body = json.loads(res_body)
return res_body
COTOHA(固有表現抽出)を呼び出す部分、エラー401と500の場合のみリトライするようにしてます。
3.WordCloudで図示する部分
from wordcloud import WordCloud
import matplotlib.pyplot as plt
from PIL import Image
def get_wordcrowd_mask(text):
#日本語フォント指定
f_path = '/usr/share/fonts/opentype/ipafont-gothic/ipagp.ttf'
#wcパラメタ指定
wc = WordCloud(background_color="white",
width=500,
height=500,
font_path=f_path,
collocations=False,
).generate( text )
#画面描写
plt.figure(figsize=(5,5), dpi=200)
plt.imshow(wc, interpolation="bilinear")
plt.axis("off")
plt.show()
WordCloudを利用して、テキストを図示する部分です。
4.メイン
aozora_text_list = get_word()
json_list = []
loc_str = ''
cnt = 0
for i in aozora_text_list:
cnt+=1
print( str(cnt) + '/' + str(len(aozora_text_list)) )
json_list.append(cotoha_call(i))
for i in json_list:
for j in i['result']:
if(j['class'] == 'LOC'):
loc_str = loc_str + j['form'] + ","
get_wordcrowd_mask(loc_str)
1~3を単純に実行している部分
また、APIコール時の進捗を、以下出力結果のように表出してます。(n/1でテキスト分割時の配列内の個数)
1/9
2/9
3/9
4/9
5/9
6/9
7/9
8/9
9/9
#出力結果
すこし、地名と関係なさそうな文字が混じってはいますが、概ね抽出できてそうですね。
以下、他にも試してみた結果。
なんか楽しいな。。。
#まとめ
COTOHAもColabも無償で使用できて、手軽に言語処理に触れる
環境なのですごいいいですね!
以上です、ご一読ありがとうございました!