2018年03月19日

言語処理100本ノックでPython入門 #27 - 正規表現の(?:……)

  
今日は、言語処理100本ノック 2015の問題27です。

■ 問題

問題20で作成したファイルを入力として、以下の問題を解きます。

27. 内部リンクの除去
26の処理に加えて,テンプレートの値からMediaWikiの内部リンクマークアップを除去し,テキストに変換せよ(参考: マークアップ早見表).


内部リンクマークアップを除去するとは、
[[記事名]]  ==> 記事名
[[記事名|表示文字]  ==> 表示文字
[[記事名#節名|表示文字]]  ==> 表示文字
と変換せよということだと解釈。 なので、
[[ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章]]
といった、ファイル: と先頭にあるものなどは、対象外としました。


■ Pythonのコード
import json
import re

def readArticle(filename):
    with open(filename, 'r', encoding='utf8') as fin:
        return fin.read()

def getBasicInfo(article):
    basicInfo = re.search(r'\{\{基礎情報(.+?)\}\}\n', article, re.DOTALL).group(1)
    pat = r'^\|(.+?)\s*=\s*(.+?)(?<!<br/>)\n'
    reg = re.compile(pat, re.MULTILINE | re.DOTALL)
    wdict = {}
    for k, v in reg.findall(basicInfo):
        v1 = re.sub(r"''('|''')([^']+?)''+", r"\2", v)
        v2 = re.sub(r"\[\[(?:[^:\]]+?\|)?([^:]+?)\]\]", r"\1", v1)
        wdict[k] = v2
    return wdict

def main():
    # england-article.txtは、問題20(nlp20.py)で作成したファイル
    article = readArticle('england-article.txt')    
    dic = getBasicInfo(article)
    dic = sorted(dic.items(), key=lambda x: x[0])
    for item, v in dic:
        print(item, ':', v)

if __name__ == '__main__':
    main()

■ コード内の正規表現の説明
v2 = re.sub(r"\[\[(?:[^:\]]+?\|)?([^:]+?)\]\]", r"\1", v1)
の簡単な説明を。

まずは、正規表現の全体像。
r"\[\[……\]\]"
これで、内部リンクと一致させます。

途中の
(?:[^:\[]+?\|)?
は、削除して良い文字列を示しています。
(?:……)
は、後からグループ参照をしないという意味。これで、/1, /2 などは対象外になります。

[^:\[]+?
は、: と [ 以外の文字が1以上連続(+?なので最短一致)する文字列です。

その後に、|が続くパターンを示しています。 最後に?付けてるので、これが、0回か1回でマッチします。

その後の
([^:]+?)
は、:以外の任意の文字が1以上連続するパターンで、これが残すべき文字列です。\1 で参照できます。

前半の (?:……)が有効に働いています。 ?: 指定をしておかないと、\1 か \2 かのどちらを残したらよいかわからないです。


■ 結果

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/>
*{{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|イギリスの国章]]
国際電話番号 : 44
夏時間 : +1
建国形態 : 建国
日本語国名 : グレートブリテン及び北アイルランド連合王国
時間帯 : ±0
最大都市 : ロンドン
標語 : {{lang|fr|Dieu et mon droit}}<br/>(フランス語:神と私の権利)
水面積率 : 1.3%
注記 : <references />
略名 : イギリス
確立年月日1 : 927年/843年
確立年月日2 : 1707年
確立年月日3 : 1801年
確立年月日4 : 1927年
確立形態1 : イングランド王国/スコットランド王国<br />(両国とも1707年連合法まで)
確立形態2 : グレートブリテン王国建国<br />(1707年連合法)
確立形態3 : グレートブリテン及びアイルランド連合王国建国<br />(1800年連合法)
確立形態4 : 現在の国号「グレートブリテン及び北アイルランド連合王国」に変更
通貨 : UKポンド (&pound;)
通貨コード : GBP
面積値 : 244,820
面積大きさ : 1 E11
面積順位 : 76
首相等氏名 : デーヴィッド・キャメロン
首相等肩書 : 首相
首都 : ロンドン