2018年03月04日

言語処理100本ノックでPython入門 #20 - gzipの読み込みとJSON

  
本日から、言語処理100本ノック 2015の第3章: 正規表現へ入ります。 まずは問題20。

■ 問題
Wikipediaの記事を以下のフォーマットで書き出したファイルjawiki-country.json.gzがある.
  • 1行に1記事の情報がJSON形式で格納される 
  •  各行には記事名が"title"キーに,記事本文が"text"キーの辞書オブジェクトに格納され,そのオブジェクトがJSON形式で書き出される 
  • ファイル全体はgzipで圧縮される 
以下の処理を行うプログラムを作成せよ.

20. JSONデータの読み込み
Wikipedia記事のJSONファイルを読み込み,「イギリス」に関する記事本文を表示せよ.問題21-29では,ここで抽出した記事本文に対して実行せよ.

■ Pythonのコード
import json
import gzip
def extract(title): with gzip.open('jawiki-country.json.gz', 'rt', encoding='utf8') as fin: for line in fin: jsd = json.loads(line) if jsd['title'] == title: return jsd['text'] return ''
def main(): article = extract('イギリス') with open('england-article.txt', 'w', encoding='utf8') as fout: fout.write(article)
if __name__ == '__main__': main()

ソースコードは、GitHubで公開しています。

■ 今回のトピックなど


gzipファイルの読み込み

import gzip
とgzipモジュールをインポートし、gzip.openメソッドでオープンします。
with gzip.open('jawiki-country.json.gz', 'rt', encoding='utf8') as fin:
    for line in fin:
        ...
2番目の引数を'rt'として、テキストファイルであることを指定します。
'r' にしてしまうとバイナリモードでオープンしてしまうので、注意が必要です。
後は、通常のテキストファイルと同じように扱えます。


JSONデータの扱い

JSONを読むには、
import json
とjsonモジュールをインポートします。

で、以下のようにjson.loadでJOSNデータを読み込みます・
with gzip.open('jawiki-country.json.gz', 'rt', encoding='utf8') as fin:
    jsd = json.load(fin)

あれ、例外が発生しました。
json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 27837)

どうも、json形式じゃないよと、例外が出ているようです。

実際に、jsonファイルの中を見てみたら、最初が [] で囲まれてないから、配列ではありません。
このファイルは、「1行1行が、json形式になってる」ということらしいです。

そのため、以下のようなコードを書くことで、無事読み込んで、該当のtextを取り出すことができました。
def extract(title):
    with gzip.open('chap03/jawiki-country.json.gz', 'rt', encoding='utf8') as fin:
        for line in fin:
            jsd = json.loads(line)
            ......
    return ''

load(), loads()の違いってなんだろうということだけど、loads()の末尾のsは、stringのsらしいです。
load一つで、オーバーロードしてくれたほうがありがたいんだけどなー。

で、loads/loadの結果は、辞書形式になるようなので、jsd['title']のようにして、各項目にアクセスできます。

結果は、'england-article.txt'に書き出しています。 問題文に「問題21-29では,ここで抽出した記事本文に対して実行せよ.」とあるので、問題21以降は、この'england-article.txt' を入力ファイルとします。


■結果

結果の一部を載せます。
{{redirect|UK}}
{{基礎情報 国
|略名 = イギリス
|日本語国名 = グレートブリテン及び北アイルランド連合王国
|公式国名 = {{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>英語以外での正式国名:<br/>
*{{lang|gd|An Rioghachd Aonaichte na Breatainn Mhor agus Eirinn mu Thuath}}([[スコットランド・ゲール語]])<br/>
*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}([[ウェールズ語]])<br/>
*{{lang|ga|Riocht Aontaithe na Breataine Moire agus Tuaisceart na hEireann}}([[アイルランド語]])<br/>
*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Gledh}}([[コーンウォール語]])<br/>
*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}([[スコットランド語]])<br/>
**{{lang|sco|Claught Kangrick o Docht Bratain an Norlin Airlann}}、{{lang|sco|Unitet Kangdom o Great Brittain an Norlin Airlann}}(アルスター・スコットランド語)</ref>
|国旗画像 = Flag of the United Kingdom.svg
|国章画像 = [[ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章]]
|国章リンク = ([[イギリスの国章|国章]])
|標語 = {{lang|fr|Dieu et mon droit}}<br/>([[フランス語]]:神と私の権利)
|国歌 = [[女王陛下万歳|神よ女王陛下を守り給え]]
|位置画像 = Location_UK_EU_Europe_001.svg
|公用語 = [[英語]](事実上)
|首都 = [[ロンドン]]
|最大都市 = ロンドン
……以下省略