Edited at

素人の言語処理100本ノック:21

More than 1 year has passed since last update.

言語処理100本ノック 2015の挑戦記録です。環境はUbuntu 16.04 LTS + Python 3.5.2 :: Anaconda 4.1.1 (64-bit)です。過去のノックの一覧はこちらからどうぞ。


第3章: 正規表現


Wikipediaの記事を以下のフォーマットで書き出したファイルjawiki-country.json.gzがある.

・1行に1記事の情報がJSON形式で格納される

・各行には記事名が"title"キーに,記事本文が"text"キーの辞書オブジェクトに格納され,そのオブジェクトがJSON形式で書き出される

・ファイル全体はgzipで圧縮される

以下の処理を行うプログラムを作成せよ.



21. カテゴリ名を含む行を抽出


記事中でカテゴリ名を宣言している行を抽出せよ.



出来上がったコード:


main.py

# coding: utf-8

import gzip
import json
import re
fname = 'jawiki-country.json.gz'

def extract_UK():
'''イギリスに関する記事本文を取得

戻り値:
イギリスの記事本文
'''

with gzip.open(fname, 'rt') as data_file:
for line in data_file:
data_json = json.loads(line)
if data_json['title'] == 'イギリス':
return data_json['text']

raise ValueError('イギリスの記事が見つからない')

# 正規表現のコンパイル
pattern = re.compile(r'''
^ # 行頭
( # キャプチャ対象のグループ開始
.* # 任意の文字0文字以上
\[\[Category:
.* # 任意の文字0文字以上
\]\]
.* # 任意の文字0文字以上
) # グループ終了
$ # 行末
'''
, re.MULTILINE + re.VERBOSE)

# 抽出
result = pattern.findall(extract_UK())

# 結果表示
for line in result:
print(line)



実行結果:


端末

[[Category:イギリス|*]]

[[Category:英連邦王国|*]]
[[Category:G8加盟国]]
[[Category:欧州連合加盟国]]
[[Category:海洋国家]]
[[Category:君主国]]
[[Category:島国|くれいとふりてん]]
[[Category:1801年に設立された州・地域]]


問題20の結果の利用

問題21-29は問題20で抽出した記事本文が対象のため、前問のコードをそのままextract_UK()として関数化しました。


カテゴリ名を含む行とは?

問題20で抽出した記事本文の書式がよく分からなかったのですが、問題26で参考情報として紹介されているマークアップ早見表を見ると[[Category:]]で括られている部分を指すようなので、それを抽出するコードにしてみました。


正規表現

正規表現の詳細はre — 正規表現操作に解説がありますが、かなり複雑です。これはしばらく使わないとすぐに忘れてしまいますね。コードには冗長なコメントがたくさん入っていますが、自身の備忘のためということでご了承ください。慣れたら少しずつ減らしていきます。


raw string記法

正規表現の文字列リテラルの先頭に付いているrraw string記法と呼ばれるもので、Pythonの文字列リテラル内でバックスラッシュ\が特別扱いされなくなります。通常、バックスラッシュを文字列リテラル内で扱う際はバックスラッシュを前に付けてエスケープしないといけませんが、正規表現でもバックスラッシュは同様のエスケープが必要なので、バックスラッシュ1文字を表現するだけで\\\\になってしまい非常に読みにくくなります。それを避ける記法だそうです。詳細はre — 正規表現操作を参照してください。


re.MULTILINE

re.MULTILINEは、検索対象のデータが複数行のために指定しています。これをつけないと^$が検索対象の先頭や末尾にしかマッチせず、途中の改行が相手にされなくなってしまいます。


re.VERBOSE

re.VERBOSEは、正規表現の途中にコメントを入れるために指定しています。これを指定すると、#でコメントが入れられます。ただし、空白や#を指定する際はバックスラッシュでのエスケープが必要になります。

 

22本目のノックは以上です。誤りなどありましたら、ご指摘いただけますと幸いです。


実行結果には、100本ノックで用いるコーパス・データで配布されているデータの一部が含まれます。この第3章で用いているデータのライセンスはクリエイティブ・コモンズ 表示-継承 3.0 非移植日本語訳)です。