schedule2019-01-18

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

はじめに

言語処理100本ノック 2015

Pythonを勉強するため、東京工業大学の岡崎教授が出題されている言語処理100本ノック 2015を解いていきます。

より深く理解するため、別解や利用したライブラリの解説もまとめていきます。

約半年ぶりに再開しました。 コツコツ勉強できる人になりたい。

環境

Python3.6

OS : mac
3章からWikiを解析する問題になっています。

問題

第3章: 正規表現

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

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

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

Point

  • ファイルの読み込み、イギリスの記事抽出は20と同じ。
  • Help:カテゴリをみてマークアップを確認する。
  • カテゴリのみを抽出できる正規表現を作る。

解答:Python

ソースコードの前にカテゴリについて確認しておく。

category

wikiのページの最下部にあるこれがカテゴリ。 カテゴリが振られていると、同じカテゴリに分類されたページのリストが自動生成される。

形式は[[Category:カテゴリ名]]あるいは、[[Category:カテゴリ名|ソートキー]]です。 似ている表記では、リンクが[[リンク名]]と近いので混合しないようにする。 カテゴリのみを抽出する正規表現はr'^\[\[Category:.+\]\]$'となります。 (改行は前段階で除いている)

ちなみに日本語版ウィキペディアではソートキーをひらがなの清音で記述するそうです。

Source code

import gzip
import json
import re


def read_wiki(fname, tiltle):
    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']


def is_category(string):
    # カテゴリー行を正規表現で判定
    return re.match(r'^\[\[Category:.+\]\]$', string)


def main():
    fname = 'jawiki-country.json.gz'
    text = read_wiki(fname, 'イギリス').split('\n')

    # カテゴリの行を表示する
    for line in text:
        if is_category(line):
            print(line)

出力

$ python 21.\ カテゴリ名を含む行を抽出.py
[[Category:イギリス|*]]
[[Category:英連邦王国|*]]
[[Category:G8加盟国]]
[[Category:欧州連合加盟国]]
[[Category:海洋国家]]
[[Category:君主国]]
[[Category:島国|くれいとふりてん]]
[[Category:1801年に設立された州・地域]]

解説

ファイルの読み込み、イギリスの記事抽出は20と同じくread_wiki()を使う。 イギリスの記事を読み込んだら、各行を走査してカテゴリ行を判定する。 判定はis_category(string)に任せカテゴリだと判定した行を出力した。

次の記事

Python3で言語処理100本ノックまとめ

前の問題:20. JSONデータの読み込み

次の問題:22. カテゴリ名の抽出