2018年12月21日金曜日

Pythonで国会会議録からワードクラウドを作成する

Pythonで国会会議録のテキストを取得するでは、国会会議録の検索APIを使って国会会議録の発言テキストを取得した。せっかく取得できるようになったので、発言テキストでワードクラウドを作ってみる。ワードクラウドの作成にはPythonのWordCloudパッケージを使う。


環境


Ubuntu 16.04(WSL)とPython3.5.2。
他にPythonライブラリのPandas、matplotlibも使うのでインストールしておく。



国会会議録の発言テキスト取得


取得する発言テキストは、最新の国家基本政策委員会合同審査会(党首討論)の会議録。Pythonで国会会議録のテキストを取得するのコードを利用するが、各発言の先頭は「~君」などの発言者ではじまるので、正規表現で取り除くように修正する。

今回は、会議録全体の発言(進行役の鉢呂委員長の発言は除く)と、安倍首相の発言それぞれをワードクラウドにする。以下のコードでそれぞれdebate.txt、abe.xtというテキストファイルに保存する。

from urllib.request import Request, urlopen
from urllib.parse import quote
from urllib.error import URLError, HTTPError
import re
import pandas as pd
import xml.etree.ElementTree as ET

def create_query():
    """
    リクエストクエリの作成
    """
    # 国家基本政策委員会合同審査会(党首討論)1回分の発言を取得する
    params = {
        'nameOfMeeting': '国家基本政策委員会合同審査会',
        'maximumRecords': 1
        }

    return '&'.join(['{}={}'.format(key, value) for key, value in params.items()])

def parse_xml(res_xml):
    root = ET.fromstring(res_xml)

    try:
        # 取得したデータはPandasのデータフレームにする
        header = ['Date', 'Meeting', 'Speaker', 'Speech']
        df = pd.DataFrame(columns=header)

        for record in root.findall('./records/record/recordData/meetingRecord'):
            # 会議録情報の取得
            nameOfMeeting = record.find('nameOfMeeting').text
            issue = record.find('issue').text
            meeting = '{} {}'.format(nameOfMeeting, issue)
            date = record.find('date').text
            for speechRecord in record.findall('speechRecord'):
                # 発言者と発言の取得
                speaker = speechRecord.find('speaker').text
                speech = speechRecord.find('speech').text
                if speaker is not None:
                    # 先頭のspeechRecord(speechOrder=0)は出席者一覧などの会議録情報なのでスキップ

                    # 話者(speaker)を除去
                    # (拍手)など括弧でかこまれた箇所を除去
                    # 他人の発言中の発言〔~〕を除去
                    # 全角空白を除去(先頭に全角空白がある文がある)
                    speech = re.sub(r'\A○.*?君()|) |(.*?)|〔.*?〕| ', '', speech)

                    # データフレームに1行ずつ追加していく
                    row = [date, meeting, speaker, speech]
                    df.loc[len(df.index)] = row

        # 会議全体の発言をテキストファイルに保存
        # 鉢呂委員長は進行役なので除外
        with open('debate.txt', 'w') as f1:
            f1.write(''.join(df[df['Speaker'] != '鉢呂吉雄']['Speech'].tolist()))

        # 安倍首相の発言をテキストファイルに保存
        with open('abe.txt', 'w') as f2:
            f2.write(''.join(df[df['Speaker'] == '安倍晋三']['Speech'].tolist()))
    except ET.ParseError as e:
        print('ParseError: {}'.format(e.code))

def main():
    # クエリはパーセントエンコードしておく
    request_url = 'http://kokkai.ndl.go.jp/api/1.0/meeting?' + quote(create_query())

    req = Request(request_url)

    try:
        with urlopen(req) as res:
            res_xml = res.read().decode('utf8')
    except HTTPError as e:
        print('HTTPError: {}'.format(e.reason))
    except URLError as e:
        print('URLError: {}'.format(e.reason))
    else:
        parse_xml(res_xml)

if __name__ == '__main__':
    main()


WordCloudのインストール


ワードクラウドはWordCloudを使って作成する。pipでインストールできるが、画像出力に必要なpillowもインストールしておく。



日本語でワードクラウドを作成するためには日本語フォントを指定する必要があるので、フォントの場所を確認しておく。フォントファイルは/usr/share/fonts/配下にある。今回はIPAex明朝フォントを使う。



MeCabのインストールと形態素解析


ワードクラウドを作成するためには、テキストを形態素解析して分かち書きにする必要がある。形態素解析にはMeCabとmecab-ipadic-NEologdを使う。インストール方法などはmecab-ipadic-NEologdで形態素解析を新語に対応させるを参照。

ここでは、MeCabで形態素解析した品詞のうち、名詞のみで分かち書きにする。しかし、取得したテキストでは「これ」とか「さん」などの出現頻度が高く、ワードクラウドの中心になってしまう。それではちょっと面白くないワードクラウドになってしまうので、名詞のうち「代名詞」「接尾」などの品詞の詳細分類も分かち書きの対象から除外する。

import MeCab

# 取り込む品詞
cat1_list = ['名詞']

# 除外する品詞の詳細分類
cat2_list = ['代名詞', '非自立', '接尾']

m = MeCab.Tagger('-Ochasen -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')
m.parse('')

def word_wakati(text):
    """
    分かち書きテキストを返す
    """
    node = m.parseToNode(text)
    wd_list = []
    while node:
        cat1 = node.feature.split(',')[0]
        cat2 = node.feature.split(',')[1]
        if cat1 in cat1_list and cat2 not in cat2_list:
            wd_list.append(node.surface)

        node = node.next

    return ' '.join(wd_list)

def main():
    with open('debate.txt', 'r') as f1:
        debate = f1.read()

    debate_wakati = word_wakati(debate)
    print(debate_wakati)

    with open('abe.txt', 'r') as f2:
        abe = f2.read()

    abe_wakati = word_wakati(abe)
    print(abe_wakati)

if __name__ == '__main__':
    main()

上記コードを実行すると、発言テキストが以下のように分かち書きになる。



ワードクラウドの作成


まずは、会議録全体の発言テキストでワードクラウドを作る。WordCloudインスタンス作成時に、確認しておいた日本語フォントへのパスを指定する。

from wordcloud import WordCloud
import MeCab

# 取り込む品詞
cat1_list = ['名詞']

# 除外する品詞の詳細分類
cat2_list = ['代名詞', '非自立', '接尾']

m = MeCab.Tagger('-Ochasen -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')
m.parse('')

def word_wakati(text):
    """
    分かち書きテキストを返す
    """
    node = m.parseToNode(text)
    wd_list = []
    while node:
        cat1 = node.feature.split(',')[0]
        cat2 = node.feature.split(',')[1]
        if cat1 in cat1_list and cat2 not in cat2_list:
            wd_list.append(node.surface)

        node = node.next

    return ' '.join(wd_list)

def word_cloud_square(text_wakati):
    """
    ワードクラウドの作成
    """
    # font_pathに日本語フォントへのパスを指定する
    wc = WordCloud(background_color='white',
        font_path='/usr/share/fonts/opentype/ipaexfont-mincho/ipaexm.ttf',
        width=500,height=500)
    wc.generate(text_wakati)

    wc.to_file("./wcloud_square.png")

def main():
    with open('debate.txt', 'r') as f1:
        debate = f1.read()

    debate_wakati = word_wakati(debate)
    word_cloud_square(debate_wakati)

if __name__ == '__main__':
    main()

以下のようなワードクラウドが作成される。

WordCloudのサイトのGallery of Examplesをみると、四角以外にもいろんな形のワードクラウドができるらしい。安倍首相の発言で円形のワードクラウドを作るコードはこちら。以下のようなワードクラウドができる。

0 件のコメント:

コメントを投稿