LoginSignup
2
3

More than 5 years have passed since last update.

【python】100本ノックにチャレンジ!(025〜029)

Last updated at Posted at 2017-09-03

これまでの経緯などについて

最初の投稿を参照ください

ノック状況

9/24追加

第3章: 正規表現

Wikipediaの記事を以下のフォーマットで書き出したファイルjawiki-country.json.gzがある.
・1行に1記事の情報がJSON形式で格納される
・各行には記事名が"title"キーに,記事本文が"text"キーの辞書オブジェクトに格納され,そのオブジェクトがJSON形式で書き出される
・ファイル全体はgzipで圧縮される
以下の処理を行うプログラムを作成せよ.

025. テンプレートの抽出

記事中に含まれる「基礎情報」テンプレートのフィールド名と値を抽出し,辞書オブジェクトとして格納せよ

basic_info_025.py
from training.json_read_020 import uk_find
import re

def basic_info_find(lines):
    pattern1 = re.compile(r'^\{\{[redirect|基礎情報].*')
    pattern2 = re.compile(r'^\|.*')
    pattern3 = re.compile(r'^\}\}$')

    basic_dict = {}
    for line in lines.split('\n'):
        if pattern1.match(line):
            continue

        elif pattern2.match(line):
            point = line.find('=')
            MAX = len(line)
            title = line[0:point].lstrip('|').rstrip(' ')
            data = line[point:MAX].lstrip('= ')
            basic_dict.update({title: data})

        elif pattern3.match(line):
            break
    return basic_dict

if __name__=="__main__":
    lines = uk_find()
    basic_dict = basic_info_find(lines)
    for key,value in basic_dict.items():
        print(key+':'+value)

result
確立形態4:現在の国号「'''グレートブリテン及び北アイルランド連合王国'''」に変更
国章画像:[[ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章]]
国章リンク:([[イギリスの国章|国章]])
(長いので略)
Process finished with exit code 0

感想:基礎情報の結果から|で始まる行を抜き出し、=の前後で辞書のkeyとvalueへ格納するループを回した。printの結果は分かりやすいように加工した。

026. 強調マークアップの除去

25の処理時に,テンプレートの値からMediaWikiの強調マークアップ(弱い強調,強調,強い強調のすべて)を除去してテキストに変換せよ(参考: マークアップ早見表).

emphasize_remove_026.py
from training.json_read_020 import uk_find
from training.basic_info_025 import basic_info_find
import re

def emphasize_remove(basic_dict):
    pattern = re.compile(r".*'{2,4}.*")
    for key,value in basic_dict.items():
        if pattern.match(value):
            value = value.replace("\'",'')
            basic_dict.update({key:value})
    return basic_dict


if __name__ == "__main__":
    lines = uk_find()
    basic_dict = basic_info_find(lines)
    emphasize_remove_dict = emphasize_remove(basic_dict)
    for key,value in emphasize_remove_dict.items():
        print(key+':'+value)

result
GDP統計年元:2012
確立形態4:現在の国号「グレートブリテン及び北アイルランド連合王国」に変更
面積大きさ:1 E11
(長いので略)
Process finished with exit code 0

感想:該当箇所が1箇所しかなかったが、強調マークアップを全て検索できるように'{2,4}としている。見つけたらreplaceで置き換えしただけ。

027. 内部リンクの除去

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

link_remove_027.py
from training.json_read_020 import uk_find
from training.basic_info_025 import basic_info_find
from training.emphasize_remove_026 import emphasize_remove
import re

def link_remove(emphasize_remove_dict):
    pattern = re.compile(r".*\[{2}.*")
    for key,value in emphasize_remove_dict.items():
        if pattern.match(value):
            value = value.replace('[[','').replace(']]','')
            emphasize_remove_dict.update({key: value})
    return emphasize_remove_dict

if __name__=="__main__":
    lines = uk_find()
    basic_dict = basic_info_find(lines)
    emphasize_remove_dict=emphasize_remove(basic_dict)
    link_remove_dict = link_remove(emphasize_remove_dict)

    for key,value in link_remove_dict.items():
        print(key+':'+value)

result
国章画像:ファイル:Royal Coat of Arms of the United Kingdom.svg|85px|イギリスの国章
公式国名:{{lang|en|United Kingdom of Great Britain and Northern Ireland}}<ref>英語以外での正式国名:<br/>
建国形態:建国
(長いので略)
Process finished with exit code 0

感想:026の問題に似ていて[[から始まる内部リンク部分を見つけたら[[と]]をreplaceで置き換えしただけ。

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

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

markup_remove_028.py
from training.json_read_020 import uk_find
from training.basic_info_025 import basic_info_find
from training.emphasize_remove_026 import emphasize_remove
from training.link_remove_027 import link_remove
import re

#poundを除去する関数。
def pound_check(value):
    pattern = re.compile(r".*pound.*")
    if pattern.match(value):
        value = value.replace("(&pound;)",'')
        return value
    else:
        return  value

#brタグを除去する関数。
def br_check(value):
    pattern1 = re.compile(r".*<br.*")
    if pattern1.match(value):
        value = value.replace("<br />", '').replace("<br/>", '')
        return value
    else:
        return value

#refタグとreference記述を除去する関数。
def ref_check(value):
    pattern2 = re.compile(r".*<ref.*")
    if pattern2.match(value):
        start_point = value.find("<ref")
        value = value[0:start_point]
        return value
    else:
        return value

#{{と}}を除去する関数。
def brackets_check(value):
    pattern3 = re.compile(r".*\{\{.*")
    if pattern3.match(value):
        value = value.replace("{{","").replace("}}","")
        #lang|en|United〜とした場合に最初のパイプから4文字以降を取得#
        start_point = value.find("|")+4
        value = value[start_point:len(value)]
        return value
    else:
        return value

#ファイル:除去する関数。
def file_check(value):
    pattern4 = re.compile(r".*ファイル.*")
    if pattern4.match(value):
        value = value.replace('ファイル:','')
        start_point = value.find("|")
        value = value[0:start_point]
        return value
    else:
        return value

#半角の|を除去する関数。|のみと|+()が存在するパターンを除去。
def pipe_check(value):
     pattern5 = re.compile(r".*\|.*")
     pattern6 = re.compile(r".*\(.*")
     if pattern5.match(value) and pattern6.match(value) :
         end_point = value.find("|")
         value = value[0:end_point] + ")"
         return value
     elif pattern5.match(value):
         end_point = value.find("|")
         value = value[0:end_point]
         return value
     else:
         return value

#全角の(を除去する関数
def other_check(value):
    pattern7 = re.compile(r"^\(")
    if pattern7.match(value):
        value = value.replace("(","")
        return value
    else:
        return value

def markup_remove(link_remove_dict):
    for key,value in link_remove_dict.items():
        value = pound_check(value)
        value = br_check(value)
        value = ref_check(value)
        value = brackets_check(value)
        value = file_check(value)
        value = pipe_check(value)
        value = other_check(value)
        link_remove_dict.update({key:value})

    return link_remove_dict


if __name__=="__main__":
    lines = uk_find()
    basic_dict = basic_info_find(lines)
    emphasize_remove_dict=emphasize_remove(basic_dict)
    link_remove_dict = link_remove(emphasize_remove_dict)
    markup_remove_dict = markup_remove(link_remove_dict)

    for key,value in markup_remove_dict.items():
        print(key+':'+value)

    print(len(markup_remove_dict.items()))

result
確立年月日1:927年/843年
公式国名:United Kingdom of Great Britain and Northern Ireland
確立形態1:イングランド王国/スコットランド王国(両国とも連合法 (1707年))
位置画像:Location_UK_EU_Europe_001.svg
標語:Dieu et mon droit(フランス語:神と私の権利)
ccTLD:.uk / .gb
国旗画像:Flag of the United Kingdom.svg
通貨:スターリング・ポンド
(長いので略)
Process finished with exit code 0

感想:まずどんなマークアップを引っ掛けるか確認するためにマークアップを見つけてはコンパイルパターンを作ってを繰り返した。。。そして1行ごとにすべてのパターンで評価することに。しかし、全角表記はナシだろ。。。なんで引っかからないのかすごく悩んだよ。。。疲れたっす。

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

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

get_url_029.py
# -*- coding:utf-8-*-

from training.json_read_020 import uk_find
from training.basic_info_025 import basic_info_find
import requests
import urllib.parse
import json
import re

def image_query(filename):
    url = "https://commons.wikimedia.org/w/api.php?"
    action = "action=query&"
    titles = "titles=File:"+urllib.parse.quote(filename)+"&"
    prop = "prop=imageinfo&"
    iiprop="iiprop=url&"
    format = "format=json"
    parameter = url +action+titles+prop+iiprop+format
    return parameter

def get_request(parameter):
    pattern = re.compile(r".*\"url\".*")
    r = requests.get(parameter)
    data = r.json()
    json_data =json.dumps(data["query"]["pages"]["347935"]["imageinfo"],indent=4)
    for temp in json_data.split('\n'):
        if(pattern.search(temp)):
            url_data = temp.replace(" ","")
        else:
            continue

    return url_data

if __name__=="__main__":
    lines = uk_find()
    basic_dict = basic_info_find(lines)
    parameter=image_query(basic_dict['国旗画像'])
    get_url = get_request(parameter)
    print(get_url)

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

Process finished with exit code 0

感想:最初は何をやればいいのかよくわからなかった問題。色々ググってたら要はwikimediaにファイル名に関するデータを検索するリクエストを投げて、レスポンスから画像ファイルがアップされているURLを見つけろということだった。この題意を理解するのにめっちゃ時間かかった、、、色んな意味で勉強になった問題でした。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3