はじめに
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で圧縮される
以下の処理を行うプログラムを作成せよ.
26. 強調マークアップの除去
25の処理時に,テンプレートの値からMediaWikiの強調マークアップ(弱い強調,強調,強い強調のすべて)を除去してテキストに変換せよ(参考: マークアップ早見表).
Point
強調マークアップは以下の通り。
種類 | 入力内容 | 表示結果 |
---|---|---|
他との区別(斜体) | ''他との区別'' | 他との区別 |
強調(太字) | '''強調''' | 強調 |
斜体と強調 | '''''斜体と強調''''' | 斜体と強調 |
'
が2、3,5個で囲まれた箇所の中身を取り出せば良さそうです。
4個がないのは不思議ですが、2~5個の'
に囲まれた箇所を見つけます。
例えば、前回の出力の中では以下の行が該当します。
'確立形態4': "現在の国号「'''グレートブリテン及び北アイルランド連合王国'''」に変更",
解答:Python
前後同じ個数の繰り返し文字を検出するにはr"('{2,5})(.*?)(\1)"
とします。
{min,max}
は直前の文字のmin以上、max以下の繰り返しを抽出。
{min,max}
が最長一致、{min,max}?
が最短一致となる。
(\n)
はn番目の括弧と同じ文字を抽出する。
r"('{2,5})(.*?)(\1)"
の場合、1番目の'
と同じ数の'
を抽出できる。
Source code
# coding: utf-8
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 get_basic_information(string):
m1 = re.search(r'{{基礎情報 国.*?', string)
# print(m1.end())
m2 = re.search(r'(.*)\n}}\n', string[m1.end():])
return string[m1.end():m2.end()+1]
def remove_emphasis(string):
# 強調を除去
# m = re.match(r"(.*)('{2,5})(.*?)(\2)(.*)", string) 何故か{2,5}で'がひとつ残る
m = re.match(r"(.*)('{3,5})(.*?)(\2)(.*)", string)
if m is None:
return string
dst = m.group(1) + m.group(3) + m.group(5)
# print(dst)
return dst
def main():
fname = 'jawiki-country.json.gz'
text = read_wiki(fname, 'イギリス')
# print(len(text))
text = get_basic_information(text).split('\n')
basic_info = {}
for line in text:
m = re.match(r'\|(.+)( = )(.*)', line)
if m is None:
continue
val = remove_emphasis(m.group(3).strip())
basic_info[m.group(1).strip()] = val
# JSONで表示を整形
print(json.dumps(basic_info, sort_keys=True, indent=4, ensure_ascii=False))
if __name__ == '__main__':
main()
出力
テンプレートを抽出して強調を削除しています。 ※表示は見やすくJSONで整えました。
$ python 26.\ 強調マークアップの除去.py
{
"GDP/人": "36,727<ref name=\"imf-statistics-gdp\" />",
"GDP値": "2兆3162億<ref name=\"imf-statistics-gdp\" />",
"GDP値MER": "2兆4337億<ref name=\"imf-statistics-gdp\" />",
"GDP値元": "1兆5478億<ref name=\"imf-statistics-gdp\">[http://www.imf.org/external/pubs/ft/weo/2012/02/weodata/weorept.aspx?pr.x=70&pr.y=13&sy=2010&ey=2012&scsm=1&ssd=1&sort=country&ds=.&br=1&c=112&s=NGDP%2CNGDPD%2CPPPGDP%2CPPPPC&grp=0&a= IMF>Data and Statistics>World Economic Outlook Databases>By Countrise>United Kingdom]</ref>",
"GDP統計年": "2012",
"GDP統計年MER": "2012",
"GDP統計年元": "2012",
"GDP順位": "6",
"GDP順位MER": "5",
"ISO 3166-1": "GB / GBR",
"ccTLD": "[[.uk]] / [[.gb]]<ref>使用は.ukに比べ圧倒的少数。</ref>",
"人口値": "63,181,775<ref>[http://esa.un.org/unpd/wpp/Excel-Data/population.htm United Nations Department of Economic and Social Affairs>Population Division>Data>Population>Total Population]</ref>",
"人口大きさ": "1 E7",
"人口密度値": "246",
"人口統計年": "2011",
"人口順位": "22",
"位置画像": "Location_UK_EU_Europe_001.svg",
"元首等氏名": "[[エリザベス2世]]",
"元首等肩書": "[[イギリスの君主|女王]]",
"公式国名": "{{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>英語以外での正式国名:<br/>",
"公用語": "[[英語]](事実上)",
"国旗画像": "Flag of the United Kingdom.svg",
"国歌": "[[女王陛下万歳|神よ女王陛下を守り給え]]",
"国章リンク": "([[イギリスの国章|国章]])",
"国章画像": "[[ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章]]",
"国際電話番号": "44",
"夏時間": "+1",
"建国形態": "建国",
"日本語国名": "グレートブリテン及び北アイルランド連合王国",
"時間帯": "±0",
"最大都市": "ロンドン",
"標語": "{{lang|fr|Dieu et mon droit}}<br/>([[フランス語]]:神と私の権利)",
"水面積率": "1.3%",
"略名": "イギリス",
"確立年月日1": "[[927年]]/[[843年]]",
"確立年月日2": "[[1707年]]",
"確立年月日3": "[[1801年]]",
"確立年月日4": "[[1927年]]",
"確立形態1": "[[イングランド王国]]/[[スコットランド王国]]<br />(両国とも[[連合法 (1707年)|1707年連合法]]まで)",
"確立形態2": "[[グレートブリテン王国]]建国<br />([[連合法 (1707年)|1707年連合法]])",
"確立形態3": "[[グレートブリテン及びアイルランド連合王国]]建国<br />([[連合法 (1800年)|1800年連合法]])",
"確立形態4": "現在の国号「グレートブリテン及び北アイルランド連合王国」に変更",
"通貨": "[[スターリング・ポンド|UKポンド]] (£)",
"通貨コード": "GBP",
"面積値": "244,820",
"面積大きさ": "1 E11",
"面積順位": "76",
"首相等氏名": "[[デーヴィッド・キャメロン]]",
"首相等肩書": "[[イギリスの首相|首相]]",
"首都": "[[ロンドン]]"
}
"確立形態4": "現在の国号「グレートブリテン及び北アイルランド連合王国」に変更",
強調マークアップを除けました。
コメントにあるように何故か{2,5}
で'
がひとつ残る。
'''文字'''
-> '文字'
となる。
{2,5}
が最長一致{2,5}?
が最短一致
となっているはずなのに・・・
参考:正規表現一覧
次の記事
前の問題:25. テンプレートの抽出
前の問題:27. 内部リンクの除去
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