言語処理100本ノック 2015「第3章: 正規表現」の28本目「MediaWikiマークアップの除去」記録です。今回でマークアップ除去系は終わりです。新しく覚える内容はなく、今まで習ったことを実践で使うノックです。
参考リンク
リンク | 備考 |
---|---|
028.MediaWikiマークアップの除去.ipynb | 回答プログラムのGitHubリンク |
素人の言語処理100本ノック:28 | 多くのソース部分のコピペ元 |
ゼロから覚えるPython正規表現の基本とTips | 当ノックで学習した内容を整理しました |
正規表現 HOWTO | Python公式の正規表現How To |
re --- 正規表現操作 | Python公式のreパッケージ説明 |
Help:早見表 | Wikipediaの代表的なマークアップの早見表 |
環境
種類 | バージョン | 内容 |
---|---|---|
OS | Ubuntu18.04.01 LTS | 仮想で動かしています |
pyenv | 1.2.15 | 複数Python環境を使うことがあるのでpyenv使っています |
Python | 3.6.9 | pyenv上でpython3.6.9を使っています 3.7や3.8系を使っていないことに深い理由はありません パッケージはvenvを使って管理しています |
上記環境で、以下のPython追加パッケージを使っています。通常のpipでインストールするだけです。
種類 | バージョン |
---|---|
pandas | 0.25.3 |
第3章: 正規表現
学習内容
Wikipediaのページのマークアップ記述に正規表現を適用することで,様々な情報・知識を取り出します.
正規表現, JSON, Wikipedia, InfoBox, ウェブサービス
ノック内容
Wikipediaの記事を以下のフォーマットで書き出したファイルjawiki-country.json.gzがある.
- 1行に1記事の情報がJSON形式で格納される
- 各行には記事名が"title"キーに,記事本文が"text"キーの辞書オブジェクトに格納され,そのオブジェクトがJSON形式で書き出される
- ファイル全体はgzipで圧縮される
以下の処理を行うプログラムを作成せよ.
28. MediaWikiマークアップの除去
27の処理に加えて,テンプレートの値からMediaWikiマークアップを可能な限り除去し,国の基本情報を整形せよ.
課題補足(「MediaWikiマークアップ」について)
「MediaWikiマークアップを可能な限り」ですか・・・
ファイル内の以下の部分を正規表現で抽出しています。
種類 | 書式 | 参照元 |
---|---|---|
ファイル | [[ファイル:Wikipedia-logo-v2-ja.png|thumb|説明文]] | Help:早見表 |
外部リンク | [http://www.example.org] [http://www.example.org 表示文字] |
Help:早見表 |
Template:Lang | {{lang|言語タグ|文字列}} | Template:Lang |
HTMLタグ | <tag> |
なし |
回答
回答プログラム 028.MediaWikiマークアップの除去.ipynb
from collections import OrderedDict
from pprint import pprint
import re
import pandas as pd
def extract_by_title(title):
df_wiki = pd.read_json('jawiki-country.json', lines=True)
return df_wiki[(df_wiki['title'] == title)]['text'].values[0]
wiki_body = extract_by_title('イギリス')
basic = re.search(r'''
^\{\{基礎情報.*?\n #検索語句(\はエスケープ処理)、非キャプチャ、非貪欲
(.*?) #任意の文字列
\}\} #検索語句(\はエスケープ処理)
$ #文字列の末尾
''', wiki_body, re.MULTILINE+re.VERBOSE+re.DOTALL)
templates = OrderedDict(re.findall(r'''
^\| # \はエスケープ処理、非キャプチャ
(.+?) # キャプチャ対象(key)、非貪欲
\s* # 空白文字0文字以上
= # 検索語句、非キャプチャ
\s* # 空白文字0文字以上
(.+?) # キャプチャ対象(Value)、非貪欲
(?: # キャプチャ対象外のグループ開始
(?=\n\|) # 改行(\n)+'|'の手前(肯定の先読み)
| (?=\n$) # または、改行(\n)+終端の手前(肯定の先読み)
) # キャプチャ対象外のグループ終了
''', basic.group(1), re.MULTILINE+re.VERBOSE+re.DOTALL))
# マークアップ除去
def remove_markup(string):
# 強調マークアップの除去
# 除去対象:''他との区別''、'''強調'''、'''''斜体と強調'''''
replaced = re.sub(r'''
(\'{2,5}) # 2〜5個の'(マークアップの開始)
(.*?) # 任意の1文字以上(対象の文字列)
(\1) # 1番目のキャプチャと同じ(マークアップの終了)
''', r'\2', string, flags=re.MULTILINE+re.VERBOSE)
# 内部リンク・ファイルの除去
# 除去対象:[[記事名]]、[[記事名|表示文字]]、[[記事名#節名|表示文字]]、[[ファイル:Wi.png|thumb|説明文]]
replaced = re.sub(r'''
\[\[ # '[['(マークアップ開始)
(?: # キャプチャ対象外のグループ開始
[^|]*? # '|'以外の文字0文字以上、非貪欲
\| # '|'
)*? # グループ終了、このグループが0以上出現、非貪欲(No27との変更点)
( # グループ開始、キャプチャ対象
(?!Category:) # 否定の先読(含んだ場合は対象外としている)
([^|]*?) # '|'以外が0文字以上、非貪欲(表示対象の文字列)
)
\]\] # ']]'(マークアップ終了)
''', r'\1', replaced, flags=re.MULTILINE+re.VERBOSE)
# Template:Langの除去
# 除去対象:{{lang|言語タグ|文字列}}
replaced = re.sub(r'''
\{\{lang # '{{lang'(マークアップ開始)
(?: # キャプチャ対象外のグループ開始
[^|]*? # '|'以外の文字が0文字以上、非貪欲
\| # '|'
)*? # グループ終了、このグループが0以上出現、非貪欲
([^|]*?) # キャプチャ対象、'|'以外が0文字以上、非貪欲(表示対象の文字列)
\}\} # '}}'(マークアップ終了)
''', r'\1', replaced, flags=re.MULTILINE+re.VERBOSE)
# 外部リンクの除去
# 除去対象[http(s)://xxxx] 、[http(s)://xxx xxx]
replaced = re.sub(r'''
\[https?:// # '[http://'(マークアップ開始)
(?: # キャプチャ対象外のグループ開始
[^\s]*? # 空白以外の文字が0文字以上、非貪欲
\s # 空白
)? # グループ終了、このグループが0か1出現
([^]]*?) # キャプチャ対象、']'以外が0文字以上、非貪欲(表示対象の文字列)
\] # ']'(マークアップの終了)
''', r'\1', replaced, flags=re.MULTILINE+re.VERBOSE)
# HTMLタグの除去
# 除去対象 <xx> </xx> <xx/>
replaced = re.sub(r'''
< # '<'(マークアップの開始)
.+? # 1文字以上、非貪欲
> # '>'(マークアップの終了)
''', '', replaced, flags=re.MULTILINE+re.VERBOSE)
return replaced
for i, (key, value) in enumerate(templates.items()):
replaced = remove_markup(value)
templates[key] = replaced
# 変わったものを表示
if value != replaced:
print(i, key)
print('変更前\t', value)
print('変更後\t', replaced)
print('----')
pprint(templates)
回答解説
「ファイル」除去
前回ノックの「内部リンク」除去とほぼ同じなので、該当部分正規表現に修正をしています。
具体的には下記の1つ目のグループの終わりを)??
から)*?
へと変更しています。ファイルの場合は[[ファイル:Wikipedia-logo-v2-ja.png|thumb|説明文]]
と|
が2回以上登場するので、0回以上にしています。
replaced = re.sub(r'''
\[\[ # '[['(マークアップ開始)
(?: # キャプチャ対象外のグループ開始
[^|]*? # '|'以外の文字0文字以上、非貪欲
\| # '|'
)*? # グループ終了、このグループが0以上出現、非貪欲(No27との変更点)
( # グループ開始、キャプチャ対象
(?!Category:) # 否定の先読(含んだ場合は対象外としている)
([^|]*?) # '|'以外が0文字以上、非貪欲(表示対象の文字列)
)
\]\] # ']]'(マークアップ終了)
''', r'\1', replaced, flags=re.MULTILINE+re.VERBOSE)
以下がファイル除去の変更前と変更後です。
4 国章画像
変更前 [[ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章]]
変更後 イギリスの国章
「Template:Lang」除去
{{lang|言語タグ|文字列}}
形式を「文字列」のみに置換しています。
# 除去対象:{{lang|言語タグ|文字列}}
replaced = re.sub(r'''
\{\{lang # '{{lang'(マークアップ開始)
(?: # キャプチャ対象外のグループ開始
[^|]*? # '|'以外の文字が0文字以上、非貪欲
\| # '|'
)*? # グループ終了、このグループが0以上出現、非貪欲
([^|]*?) # キャプチャ対象、'|'以外が0文字以上、非貪欲(表示対象の文字列)
\}\} # '}}'(マークアップ終了)
''', r'\1', replaced, flags=re.MULTILINE+re.VERBOSE)
以下が「Template:Lang」除去結果です。
2 公式国名
変更前 {{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>英語以外での正式国名:<br/>
*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}([[スコットランド・ゲール語]])<br/>
*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}([[ウェールズ語]])<br/>
*{{lang|ga|Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann}}([[アイルランド語]])<br/>
*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh}}([[コーンウォール語]])<br/>
*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}([[スコットランド語]])<br/>
**{{lang|sco|Claught Kängrick o Docht Brätain an Norlin Airlann}}、{{lang|sco|Unitet Kängdom o Great Brittain an Norlin Airlann}}(アルスター・スコットランド語)</ref>
変更後 United Kingdom of Great Britain and Northern Ireland英語以外での正式国名:
*An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath(スコットランド・ゲール語)
*Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon(ウェールズ語)
*Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann(アイルランド語)
*An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh(コーンウォール語)
*Unitit Kinrick o Great Breetain an Northren Ireland(スコットランド語)
**Claught Kängrick o Docht Brätain an Norlin Airlann、Unitet Kängdom o Great Brittain an Norlin Airlann(アルスター・スコットランド語)
----
6 標語
変更前 {{lang|fr|Dieu et mon droit}}<br/>([[フランス語]]:神と私の権利)
変更後 Dieu et mon droit(フランス語:神と私の権利)
「外部リンク」除去
httpsも含めて除去しています。
# 除去対象[http(s)://xxxx] 、[http(s)://xxx xxx]
replaced = re.sub(r'''
\[https?:// # '[http://'(マークアップ開始)
(?: # キャプチャ対象外のグループ開始
[^\s]*? # 空白以外の文字が0文字以上、非貪欲
\s # 空白
)? # グループ終了、このグループが0か1出現
([^]]*?) # キャプチャ対象、']'以外が0文字以上、非貪欲(表示対象の文字列)
\] # ']'(マークアップの終了)
''', r'\1', replaced, flags=re.MULTILINE+re.VERBOSE)
以下が外部リンク除去部分です。
23 人口値
変更前 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>
変更後 63,181,775United Nations Department of Economic and Social Affairs>Population Division>Data>Population>Total Population
----
26 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>
変更後 1兆5478億IMF>Data and Statistics>World Economic Outlook Databases>By Countrise>United Kingdom
「HTMLタグ」除去
HTMLタグも除去しています。「<
と>
に囲まれていたら」という単純な正規表現。
# 除去対象 <xx> </xx> <xx/>
replaced = re.sub(r'''
< # '<'(マークアップの開始)
.+? # 1文字以上、非貪欲
> # '>'(マークアップの終了)
''', '', replaced, flags=re.MULTILINE+re.VERBOSE)
以下が結果です。結構多いですね。
2 公式国名
変更前 {{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>英語以外での正式国名:<br/>
*{{lang|gd|An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath}}([[スコットランド・ゲール語]])<br/>
*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon}}([[ウェールズ語]])<br/>
*{{lang|ga|Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann}}([[アイルランド語]])<br/>
*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh}}([[コーンウォール語]])<br/>
*{{lang|sco|Unitit Kinrick o Great Breetain an Northren Ireland}}([[スコットランド語]])<br/>
**{{lang|sco|Claught Kängrick o Docht Brätain an Norlin Airlann}}、{{lang|sco|Unitet Kängdom o Great Brittain an Norlin Airlann}}(アルスター・スコットランド語)</ref>
変更後 United Kingdom of Great Britain and Northern Ireland英語以外での正式国名:
*An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu Thuath(スコットランド・ゲール語)
*Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon(ウェールズ語)
*Ríocht Aontaithe na Breataine Móire agus Tuaisceart na hÉireann(アイルランド語)
*An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh(コーンウォール語)
*Unitit Kinrick o Great Breetain an Northren Ireland(スコットランド語)
**Claught Kängrick o Docht Brätain an Norlin Airlann、Unitet Kängdom o Great Brittain an Norlin Airlann(アルスター・スコットランド語)
----
6 標語
変更前 {{lang|fr|Dieu et mon droit}}<br/>([[フランス語]]:神と私の権利)
変更後 Dieu et mon droit(フランス語:神と私の権利)
----
23 人口値
変更前 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>
変更後 63,181,775United Nations Department of Economic and Social Affairs>Population Division>Data>Population>Total Population
----
26 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>
変更後 1兆5478億IMF>Data and Statistics>World Economic Outlook Databases>By Countrise>United Kingdom
----
29 GDP値MER
変更前 2兆4337億<ref name="imf-statistics-gdp" />
変更後 2兆4337億
----
32 GDP値
変更前 2兆3162億<ref name="imf-statistics-gdp" />
変更後 2兆3162億
----
33 GDP/人
変更前 36,727<ref name="imf-statistics-gdp" />
変更後 36,727
----
37 確立形態2
変更前 [[グレートブリテン王国]]建国<br />([[連合法 (1707年)|1707年連合法]])
変更後 グレートブリテン王国建国(1707年連合法)
----
39 確立形態3
変更前 [[グレートブリテン及びアイルランド連合王国]]建国<br />([[連合法 (1800年)|1800年連合法]])
変更後 グレートブリテン及びアイルランド連合王国建国(1800年連合法)
----
48 ccTLD
変更前 [[.uk]] / [[.gb]]<ref>使用は.ukに比べ圧倒的少数。</ref>
変更後 .uk / .gb使用は.ukに比べ圧倒的少数。
----
50 注記
変更前 <references />
変更後
出力結果(実行結果)
プログラム実行すると最後に以下の結果が出力されます。すっきりしました。
OrderedDict([('略名', 'イギリス'),
('日本語国名', 'グレートブリテン及び北アイルランド連合王国'),
('公式国名',
'United Kingdom of Great Britain and Northern '
'Ireland英語以外での正式国名:\n'
'*An Rìoghachd Aonaichte na Breatainn Mhòr agus Eirinn mu '
'Thuath(スコットランド・ゲール語)\n'
'*Teyrnas Gyfunol Prydain Fawr a Gogledd Iwerddon(ウェールズ語)\n'
'*Ríocht Aontaithe na Breataine Móire agus Tuaisceart na '
'hÉireann(アイルランド語)\n'
'*An Rywvaneth Unys a Vreten Veur hag Iwerdhon Glédh(コーンウォール語)\n'
'*Unitit Kinrick o Great Breetain an Northren Ireland(スコットランド語)\n'
'**Claught Kängrick o Docht Brätain an Norlin Airlann、Unitet '
'Kängdom o Great Brittain an Norlin Airlann(アルスター・スコットランド語)'),
('国旗画像', 'Flag of the United Kingdom.svg'),
('国章画像', 'イギリスの国章'),
('国章リンク', '(国章)'),
('標語', 'Dieu et mon droit(フランス語:神と私の権利)'),
('国歌', '神よ女王陛下を守り給え'),
('位置画像', 'Location_UK_EU_Europe_001.svg'),
('公用語', '英語(事実上)'),
('首都', 'ロンドン'),
('最大都市', 'ロンドン'),
('元首等肩書', '女王'),
('元首等氏名', 'エリザベス2世'),
('首相等肩書', '首相'),
('首相等氏名', 'デーヴィッド・キャメロン'),
('面積順位', '76'),
('面積大きさ', '1 E11'),
('面積値', '244,820'),
('水面積率', '1.3%'),
('人口統計年', '2011'),
('人口順位', '22'),
('人口大きさ', '1 E7'),
('人口値',
'63,181,775United Nations Department of Economic and Social '
'Affairs>Population Division>Data>Population>Total Population'),
('人口密度値', '246'),
('GDP統計年元', '2012'),
('GDP値元',
'1兆5478億IMF>Data and Statistics>World Economic Outlook '
'Databases>By Countrise>United Kingdom'),
('GDP統計年MER', '2012'),
('GDP順位MER', '5'),
('GDP値MER', '2兆4337億'),
('GDP統計年', '2012'),
('GDP順位', '6'),
('GDP値', '2兆3162億'),
('GDP/人', '36,727'),
('建国形態', '建国'),
('確立形態1', 'イングランド王国/スコットランド王国(両国とも1707年連合法まで)'),
('確立年月日1', '927年/843年'),
('確立形態2', 'グレートブリテン王国建国(1707年連合法)'),
('確立年月日2', '1707年'),
('確立形態3', 'グレートブリテン及びアイルランド連合王国建国(1800年連合法)'),
('確立年月日3', '1801年'),
('確立形態4', '現在の国号「グレートブリテン及び北アイルランド連合王国」に変更'),
('確立年月日4', '1927年'),
('通貨', 'UKポンド (£)'),
('通貨コード', 'GBP'),
('時間帯', '±0'),
('夏時間', '+1'),
('ISO 3166-1', 'GB / GBR'),
('ccTLD', '.uk / .gb使用は.ukに比べ圧倒的少数。'),
('国際電話番号', '44'),
('注記', '')])