はじめに
Pythonを勉強するため、東京工業大学の岡崎教授が出題されている言語処理100本ノック 2015を解いていきます。
より深く理解するため、別解や利用したライブラリの解説もまとめていきます。
環境
- Python3.6
- OS : Linux Mint
OSがMacからLinux Mintに変わりました。
問題
3章からWikiを解析する問題になっています。
Wikipediaの記事を以下のフォーマットで書き出したファイルjawiki-country.json.gzがある.
- 1行に1記事の情報がJSON形式で格納される
- 各行には記事名が"title"キーに,記事本文が"text"キーの辞書オブジェクトに格納され,そのオブジェクトがJSON形式で書き出される
- ファイル全体はgzipで圧縮される
以下の処理を行うプログラムを作成せよ.
23. セクション構造
記事中に含まれるセクション名とそのレベル(例えば"== セクション名 =="なら1)を表示せよ.
Point
- ファイルの読み込み、イギリスの記事抽出は20と同じ。
- セクション行の判別と
=
の数を読み取る
レベルとセクションの例はこんな感じ。
1 : == セクションの見出し ==
2 : === サブセクションの見出し ===
3 : ==== サブサブセクションの見出し ====
解答:Python
正規表現で()
は中身を取り出すことができます。
Pythonのre.match()
関数では()
で抽出した箇所の文字列を得ることができます。
セクション行は正規表現r'^=+.+=+$'
で判別できます。
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_section(string):
return re.match(r'^=+.+=+$', string)
def get_section_level(string):
m = re.match(r'^(=+)(.+?)=+$', string)
# m.group(1) => '==='
return ' name : {0}\tlevel : {1} '.format(m.group(2), len(m.group(1)) - 1)
def main():
fname = 'jawiki-country.json.gz'
text = read_wiki(fname, 'イギリス').split('\n')
# print(len(text))
# カテゴリの行を表示する
for line in text:
if is_section(line):
# print(line, end=' : ')
print(get_section_level(line))
if __name__ == '__main__':
main()
出力
セクション名とレベルをそれぞれ出しています。
$ python 23.\ セクション構造.py
name : 国名 level : 1
name : 歴史 level : 1
name : 地理 level : 1
name : 気候 level : 2
name : 政治 level : 1
name : 外交と軍事 level : 1
name : 地方行政区分 level : 1
name : 主要都市 level : 2
name : 科学技術 level : 1
name : 経済 level : 1
name : 鉱業 level : 2
name : 農業 level : 2
name : 貿易 level : 2
name : 通貨 level : 2
name : 企業 level : 2
name : 交通 level : 1
name : 道路 level : 2
name : 鉄道 level : 2
name : 海運 level : 2
name : 航空 level : 2
name : 通信 level : 1
name : 国民 level : 1
name : 言語 level : 2
name : 宗教 level : 2
name : 婚姻 level : 2
name : 教育 level : 2
name : 文化 level : 1
name : 食文化 level : 2
name : 文学 level : 2
name : 哲学 level : 2
name : 音楽 level : 2
name : イギリスのポピュラー音楽 level : 3
name : 映画 level : 2
name : コメディ level : 2
name : 国花 level : 2
name : 世界遺産 level : 2
name : 祝祭日 level : 2
name : スポーツ level : 1
name : サッカー level : 2
name : 競馬 level : 2
name : モータースポーツ level : 2
name : 脚注 level : 1
name : 関連項目 level : 1
name : 外部リンク level : 1
解説
re.match(r'^=+.+=+$', string)
でセクション行を判別。
セクション名とレベルの取得は関数get_section_level(string)
で行っています。
def get_section_level(string):
m = re.match(r'^(=+)(.+?)=+$', string)
# m.group(1) => '==='
return ' name : {0}\tlevel : {1} '.format(m.group(2), len(m.group(1)) - 1)
()
の中身がm.group(n)
で取れることを利用して=
の長さなど取得しました。
次の記事
前の問題:22. カテゴリ名の抽出
次の問題:24. ファイル参照の抽出
Python:ファイルダウンロードの進行状況とファイルサイズを表示する方法。urllib
Pythonschedule2024-02-27
【Python】tqdmでforの進捗状況を表示する
PythonColabolatoryschedule2021-02-16
学習済みの日本語単語ベクトルをColabolatoryで試してみる
自然言語処理PythonColabolatoryschedule2021-02-04
Unity ML-Agentsで新しく学習環境を作る
Unity機械学習C#PythonDeepLearningschedule2021-01-22
27. 内部リンクの除去
自然言語処理100本ノックPythonschedule2020-03-17