yamakiy’s tech blog

技術系の記事をメインにやります。

言語処理100本ノック(第3章 28 ~ 29)

yamakiy.hatenadiary.jp

28. MediaWikiマークアップの除去

27の処理に加えて,テンプレートの値からMediaWikiマークアップを可能な限り除去し,国の基本情報を整形せよ.

27は前回のコードと重複するところが多いから、再利用ついでに少しリファクタ
そうしていたらあるふと、指示がリストではなく、辞書オブジェクトで表示しろということに気づきました

25.  テンプレートの抽出
記事中に含まれる「基礎情報」テンプレートのフィールド名と値を抽出し,辞書オブジェクトとして格納せよ.
#!/usr/bin/python3.6
import json
import re
from pprint import pprint

class JawikiCountry(object):
    jawiki = ""

    # 強調マークアップの除去
    __rm_markup = lambda self, x: re.sub(r'(\'{2,5})(.*?)\1', r'\2', x, flags=re.DOTALL)
    # 内部リンクマークアップの除去
    __rm_inlink = lambda self, x: re.sub(r'\[\[(?!Category:|File:|ファイル:)(.*?)\]\]', r'\1', x, flags=re.DOTALL)
    # 外部リンクマークアップの除去
    __rm_outlink = lambda self, x: re.sub(r'\[(.*?)\]', r'\1', x, flags=re.DOTALL)
    # リダイレクトマークアップの除去
    __rm_redirect = lambda self, x: re.sub(r'#REDIRECT \[\[(.*?)\]\]', r'\1', x, flags=re.DOTALL)
    # コメントアウトの除去
    __rm_commentout = lambda self, x: re.sub(r'<!--(.*?)-->', r'\1', x, flags=re.DOTALL)
    # 署名の除去
    __rm_signature = lambda self, x: x.replace('~~~~', '')

    def __init__(self, country):
        self.jawiki = self.get_jawiki(country)

    def get_jawiki(self, country):
        jawiki_country = {}
        with open("jawiki-country.json", "r") as f:
            for i in f:
                data = json.loads(i)
                jawiki_country[data["title"]] = data["text"]
        return jawiki_country[country]

    # 可能な限りマークアップを除去
    def get_basic_info_no_markup_all(self):
        basic_info = self.get_basic_info()
        res = {}
        for line in basic_info:
            val = self.__rm_markup(line[1])
            val = self.__rm_inlink(val)
            val = self.__rm_outlink(val)
            val = self.__rm_redirect(val)
            val = self.__rm_commentout(val)
            val = self.__rm_signature(val)
            res[line[0]] = val
        return res

if __name__ == "__main__":
    jc = JawikiCountry("イギリス")
    pprint(jc.get_basic_info_no_markup_all())

"""
{'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/>\n'
         '*{{lang|gd|An Rioghachd Aonaichte na Breatainn Mhor agus Eirinn mu '
         'Thuath}}(スコットランド・ゲール語)<br/>\n'
         '*{{lang|cy|Teyrnas Gyfunol Prydain Fawr a Gogledd '
         'Iwerddon}}(ウェールズ語)<br/>\n'
         '*{{lang|ga|Riocht Aontaithe na Breataine Moire agus Tuaisceart na '
         'hEireann}}(アイルランド語)<br/>\n'
         '*{{lang|kw|An Rywvaneth Unys a Vreten Veur hag Iwerdhon '
         'Gledh}}(コーンウォール語)<br/>\n'
         '*{{lang|sco|Unitit Kinrick o Great Breetain an Northren '
         'Ireland}}(スコットランド語)<br/>\n'
         '**{{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%',
 '略名': 'イギリス',
 '確立年月日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',
 '面積順位': '76',
 '首相等氏名': 'デーヴィッド・キャメロン',
 '首相等肩書': 'イギリスの首相|首相',
 '首都': 'ロンドン'}
"""

29. 国旗画像のURLを取得する

テンプレートの内容を利用し,国旗画像のURLを取得せよ.(ヒント: MediaWiki APIimageinfoを呼び出して,ファイル参照をURLに変換すればよい)

前回の抽出結果を見ると、国旗画像は基本情報の中にある

'国旗画像', 'Flag of the United Kingdom.svg',

後はapiを利用して抽出します

#!/usr/bin/python3.6
import json
import re
from pprint import pprint

class JawikiCountry(object):
    jawiki = ""

    # 強調マークアップの除去
    __rm_markup = lambda self, x: re.sub(r'(\'{2,5})(.*?)\1', r'\2', x, flags=re.DOTALL)
    # 内部リンクマークアップの除去
    __rm_inlink = lambda self, x: re.sub(r'\[\[(?!Category:|File:|ファイル:)(.*?)\]\]', r'\1', x, flags=re.DOTALL)
    # 外部リンクマークアップの除去
    __rm_outlink = lambda self, x: re.sub(r'\[(.*?)\]', r'\1', x, flags=re.DOTALL)
    # リダイレクトマークアップの除去
    __rm_redirect = lambda self, x: re.sub(r'#REDIRECT \[\[(.*?)\]\]', r'\1', x, flags=re.DOTALL)
    # コメントアウトの除去
    __rm_commentout = lambda self, x: re.sub(r'<!--(.*?)-->', r'\1', x, flags=re.DOTALL)
    # 署名の除去
    __rm_signature = lambda self, x: x.replace('~~~~', '')

    def __init__(self, country):
        self.jawiki = self.get_jawiki(country)

    def get_jawiki(self, country):
        jawiki_country = {}
        with open("jawiki-country.json", "r") as f:
            for i in f:
                data = json.loads(i)
                jawiki_country[data["title"]] = data["text"]
        return jawiki_country[country]

    # 可能な限りマークアップを除去
    def get_basic_info_no_markup_all(self):
        basic_info = self.get_basic_info()
        res = []
        for line in basic_info:
            val = self.__rm_markup(line[1])
            val = self.__rm_inlink(val)
            val = self.__rm_outlink(val)
            val = self.__rm_redirect(val)
            val = self.__rm_commentout(val)
            val = self.__rm_signature(val)
            res += [(line[0], val)]
        return res

    def get_national_flag_url(self):
        national_flag = self.get_basic_info_no_markup_all()["国旗画像"]
        endpoint = "https://www.mediawiki.org/w/api.php"
        params = {
            'action': 'query',
            'titles': f'File: {national_flag}',
            'format': 'json',
            'iiprop': 'url',
            'prop': 'imageinfo'
        }
        res = requests.get(endpoint, params=params)
        if res.status_code == 200:
            data = json.loads(res.text)
            return data["query"]["pages"]["-1"]["imageinfo"][0]["url"]

        return ""

if __name__ == "__main__":
    jc = JawikiCountry("イギリス")
    pprint(jc.get_national_flag_url())

# https://upload.wikimedia.org/wikipedia/commons/a/ae/Flag_of_the_United_Kingdom.svg

https://upload.wikimedia.org/wikipedia/commons/a/ae/Flag_of_the_United_Kingdom.svg

github.com