2018年03月15日

言語処理100本ノックでPython入門 #25 - re.DOTALL/re.MULTILINEオプション

  

言語処理100本ノック 2015の問題25に挑戦です。 

■ 問題

問題20で作成したファイルを入力として、以下の問題を解きます。
25. テンプレートの抽出
記事中に含まれる「基礎情報」テンプレートのフィールド名と値を抽出し,辞書オブジェクトとして格納せよ.

■ 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): wdict[k] = v return wdict
def main(): 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()
'england-article.txt'は問題20で作成したファイルです。これを入力ファイルとしています。


■ 今回のトピック等

今回はいろいろと勉強になりました。

re.DOTALLオプション

まずは、基礎情報のところだけを抜き出し、それから、フィールドと値を取り出そうと考えました。 しかし、
re.search(r'\{\{基礎情報(.+?)\}\}\n', article)
って書いても一致しません。どうしてって悩みましたが、re.DOTALLというオプションが必要なようです。
re.DOTALLは、正規表現のドット.に改行も含めるという指定です。

途中で、対応していない`}}\n`があったら、正しく取り出せないんですが、そういた記述はないようなので これで良しとします。

re.MULTILINEオプション

次に、フィールドと値を取り出します。調べると、"公式国名"の値は改行が含まれていて複数行にわたっています。 次のように書いてみました。
pat = r'^\|(.+?)\s*=\s*(.+?)(?<!<br/>)\n'
reg = re.compile(pat, re.DOTALL)

正規表現の (?<!...) は、... とマッチしない場合にマッチします。つまり、(?<!--<br/-->)は、文字列`<br />`を含まないという指定です。

でも、うまくいきません。複数行の検索においては、行頭の ^ を各行の行頭とマッチさせるには、re.DOTALLとは別にre.MULTILINE を指定する必要がありました。
reg = re.compile(pat, re.MULTILINE | re.DOTALL)

finditer/findallメソッド 

finditerメソッドを使うと、matchオブジェクトを列挙することができます。

最初に書いたコード。
wdict = {}
for m in reg.finditer(basicInfo):
    wdict[m.group(1)] = m.group(2)
return wdict 

次に書いたコード。
wdict = {}
for k, v in reg.findall(basicInfo):
    wdict[k] = v
return wdict    
findallメソッド使うと、こんな書き方もできるんですね。

findallメソッドは、戻り値はmatchオブジェクトではないので、group()などは利用できません。
その代わり、グループ指定がある場合は、そのタプルのリストが返るので、for文で上のようにタプルの要素を分解して取得することができます。

今回のコードでは、これを採用しました。
今回の例だと、()によるグルーピングは2つですが、3つの場合は、3つの要素を持つタプルになるので、
 
for g1, g2, g3 in reg.findall(s):
のように書けます。


■ 結果
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年)|1707年連合法]]まで)
確立形態2 : [[グレートブリテン王国]]建国<br />([[連合法 (1707年)|1707年連合法]])
確立形態3 : [[グレートブリテン及びアイルランド連合王国]]建国<br />([[連合法 (1800年)|1800年連合法]])
確立形態4 : 現在の国号「'''グレートブリテン及び北アイルランド連合王国'''」に変更
通貨 : [[スターリング・ポンド|UKポンド]] (&pound;)
通貨コード : GBP
面積値 : 244,820
面積大きさ : 1 E11
面積順位 : 76
首相等氏名 : [[デーヴィッド・キャメロン]]
首相等肩書 : [[イギリスの首相|首相]]
首都 : [[ロンドン]]