🙆

Pythonで国会会議録のデータを収集してCSVに整形する

2020/11/19に公開

はじめに

自然言語処理の勉強に使うデータを集めたいのですが、興味を持てる対象を分析対象であるものを考えたときに、消費税増税やそもそも所得税とか厚生年金とかでお金取られてるのもあり、政治にやや興味があるので、国会会議録のデータが比較的簡単に引っこ抜けそうだったので、そのデータを収集することにしました。
※この記事では分析結果は載せてないので、データを取得したい方だけどうぞ。

データについて

引っ張ってくるデータは国会会議録検索システムに登録されているデータになります。なので、会議単位簡易出力や会議単位出力や発言単位出力を確認することができるデータとなっています。今回はどの会議で誰が何を発言したのかというデータを分析したいので、会議単位出力を利用します。

注意事項

クローリングやAPIの利用する上でのマナーではありますし、利用規約にも以下のように記載がありますので、なるべく負荷のかからないようにしていきましょう。

このシステムの運用に影響のあるような負荷のかかる利用(短時間での大量アクセス等)はご遠慮ください。安定運用に支障をきたすと当館が判断した場合には、予告なくアクセスを遮断する等の措置をとることがあります。

また、以下の通り非営利の場合は出典さえかけば特に問題はなさそうです。営利目的の場合は連絡しましょう。

非営利目的でのAPIの利用は、著作権者の許諾を得ることなく、自由に行っていただけます。APIを使用した成果を公表する場合には、必ず出典(国会会議録検索システム)を明記してください。
営利目的でのAPIの利用については、次の連絡先までお問い合わせください。

以下の記載もあるので、分析した成果をブログで出す場合は連絡送ってみようかと思います。

非営利目的の場合でも、上記の連絡先までお知らせいただけますと幸いです。システム改善の参考にさせていただきます。

会議単位出力のAPI仕様

会議単位出力のAPIでは以下のようなXMLのデータ構造で結果を返してくる仕様になっています。

<?xml version="1.0"?>
<data>
  <numberOfRecords> 総結果件数 </numberOfRecords>
  <numberOfReturn> 返戻件数 </numberOfReturn>
  <startRecord> 開始位置 </startRecord>
  <nextRecordPosition> 次開始位置(※存在する場合のみ) </nextRecordPosition>
  <records>
    <record>
      <recordData>
        <meetingRecord>
          <issueID> 会議録ID </issueID>
          <imageKind> イメージ種別(会議録・目次・索引・附録・追録) </imageKind>
          <searchObject> 検索対象箇所(議事冒頭・本文) </searchObject>
          <session> 国会回次 </session>
          <nameOfHouse> 院名 </nameOfHouse>
          <nameOfMeeting> 会議名 </nameOfMeeting>
          <issue> 号数 </issue>
          <date> 開催日付 </date>
          <closing> 閉会中フラグ </closing>
          <speechRecord>
            <speechID> 発言ID </speechID>
            <speechOrder> 発言番号 </speechOrder>
            <speaker> 発言者名 </speaker>
            <speakerYomi> 発言者よみ(※会議単位出力のみ) </speakerYomi>
            <speakerGroup> 発言者所属会派(※会議単位出力のみ) </speakerGroup>
            <speakerPosition> 発言者肩書き(※会議単位出力のみ) </speakerPosition>
            <speakerRole> 発言者役割(※会議単位出力のみ) </speakerRole>
            <speech> 発言(※会議単位出力のみ) </speech>
            <startPage> 発言が掲載されている開始ページ(※会議単位出力のみ) </startPage>
            <createTime> レコード登録日時(※会議単位出力のみ) </createTime>
            <updateTime> レコード更新日時(※会議単位出力のみ) </updateTime>
            <speechURL> 発言URL </speechURL>
          </speechRecord>
          <speechRecord>
            (次の発言情報)
          </speechRecord>
          <meetingURL> 会議録テキスト表示画面のURL </meetingURL>
          <pdfURL> 会議録PDF表示画面のURL(※存在する場合のみ) </pdfURL>
        </meetingRecord>
      </recordData>
    </record>
    <record>
      (次の会議録情報)
    </record>
  </records>
</data>

recordsと同じ階層には検索に関する統計量などのシステム的な出力となる情報が主に入っていて、recordsの下に会議の内容に関するデータが入っています。
recordsの中には復数のrecordが含まれ、recordごとに1つの会議の情報が入っています。
そして、recordの中のspeechRecord(発言に関する情報)は1つのrecordの中に復数含まれる構成になっています。

余談ですが、このようにネストされた繰り返し列を含むデータなので、BigQueryでは扱いやすそうなデータだなと思いました。

会議単位出力のAPIを使う

さて、いよいよ会議単位出力のAPIを使っていきましょう。
以下のように開始日付と終了日付をmain関数に渡せば、result.csvに結果を保存していくように実装してみました。

import pandas as pd
import urllib.parse
import requests
import xml.etree.ElementTree as ET

def get(url, params: dict):
    # クエリパラメータ全体をURLエンコードする必要があるため
    parameter = '?' + urllib.parse.quote('maximumRecords=5'
                                         + '&from=' + params['from']
                                         + '&until=' + params['until'])
    response = requests.get(url + parameter)
    tree = ET.fromstring(response.text)
    records = tree[4]
    return records.findall('record')

def format_meetings_to_dataframe(meeting_list: list):
    result_list = []

    for meeting in meeting_list:
        meetingRecord = meeting[0][0]
        issue_id, name_of_house, name_of_meeting, session, date, meeting_url, pdf_url = meetingRecord[
            0].text, meetingRecord[4].text, meetingRecord[
                5].text, meetingRecord[3].text, meetingRecord[
                    7].text, meetingRecord[-2].text, meetingRecord[-1].text

        for speechRecord in meetingRecord.findall('speechRecord'):
            speech_id, speech_order, speaker, speech = speechRecord[
                0].text, speechRecord[1].text, speechRecord[
                    2].text, speechRecord[7].text

            result_list.append([
                issue_id, name_of_house, name_of_meeting, session, date,
                meeting_url, speech_id, speech_order, speaker, speech, pdf_url
            ])

def main(start_date, end_date):
    url = 'http://kokkai.ndl.go.jp/api/1.0/meeting?'
    params = {'from': start_date, 'until': end_date, 'maximumRecords': 100}
    meeting_list = get(url, params)
    df_meeting = format_meetings_to_dataframe(meeting_list)
    df_meeting.to_csv('result.csv', mode='a', index=False)

if __name__ == '__main__':
    main('2019-01-01', '2019-02-01')

とりあえず、改善点はいろいろありますが、データを取ってきて、CSVの形式で保存していくことはできるようになりました。やったね。

終わりに

これで一応国会会議録のデータを取得することができたので、今後は分析に着手していこうかなと思っています。
何らかの分析結果が出たらWebアプリにしていきますので、次回のアウトプットは結構先になりそうな印象です。途中で飽きたらすみません。
どうでもよいですが、CSVにしておいてなんですが、Webアプリ作る練習のためにDBに放り込むと思います。

参考文献

国会会議録検索システム検索用APIを使って国会での発言を分析してみた

国会会議録検索システム 検索API

Discussion

ログインするとコメントできます