LoginSignup
2
4

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-08-27

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

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

ノック状況

9/24追加

第3章: 正規表現

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

020. JSONデータの読み込み

Wikipedia記事のJSONファイルを読み込み,「イギリス」に関する記事本文を表示せよ.問題21-29では,ここで抽出した記事本文に対して実行せよ.

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

import json
import gzip
import re

def uk_find():
    basepath = '/Users/masassy/PycharmProjects/Pywork/training/'
    filename = 'jawiki-country.json.gz'
    pattern = r"イギリス"
    with gzip.open(basepath + filename, 'rt')as gf:
        for line in gf:
            # json.loadsはstr→dict、json.loadはfile→dict
            json_data = json.loads(line)
            if (re.match(json_data['title'], pattern)):
                return json_data['text']

if __name__ == "__main__":
    json_data = uk_find()
    print(json_data)

result
{{redirect|UK}}
{{基礎情報 国
|略名 = イギリス

(長いので中略)

[[Category:島国|くれいとふりてん]]
[[Category:1801年に設立された州・地域]]

Process finished with exit code 0

感想:gzip.openで読み込んだファイルのデータ形式とjson_dataのデータ形式について理解できるまで時間がかかった。

021. カテゴリ名を含む行を抽出

記事中でカテゴリ名を宣言している行を抽出せよ.

category_021.py
from training.json_read_020 import uk_find
import re

if __name__=="__main__":
    pattern = re.compile(r'.*Category.*')
    lines = uk_find()
    for line in lines.split('\n'):
        if pattern.match(line):
            print(line)

result
[[Category:イギリス|*]]
[[Category:英連邦王国|*]]
[[Category:G8加盟国]]
[[Category:欧州連合加盟国]]
[[Category:海洋国家]]
[[Category:君主国]]
[[Category:島国|くれいとふりてん]]
[[Category:1801年に設立された州・地域]]

Process finished with exit code 0

感想:正規表現の.*検索文字.*とlines.split('\n')の組み合わせで検索文字が含まれる行を返せることに気づくのに時間がかかった

022. カテゴリ名の抽出

記事のカテゴリ名を(行単位ではなく名前で)抽出せよ.

category_str_022.py
from training.json_read_020 import uk_find
import re

if __name__=="__main__":
    pattern = re.compile(r'.*Category:.*')
    pattern2 = re.compile(r'.*\|.*')
    lines = uk_find()
    for line in lines.split('\n'):
        if pattern.match(line):
            strip_line=line.lstrip("[[Category:").rstrip("]]")
            if pattern2.match(strip_line):
                N = strip_line.find('|')
                strip_line2 = strip_line[:N]
                print(strip_line2)
            else:
                print(strip_line)
result
イギリス
英連邦王国
G8加盟国
欧州連合加盟国
海洋国家
君主国
島国
1801年に設立された州・地域

Process finished with exit code 0

感想:Categoryを抜き出してから行内に|がある場合は|の位置でスライスする場所を特定させる部分が工夫ポイント。

023. セクション構造

記事中に含まれるセクション名とそのレベル(例えば"== セクション名 =="なら1)を表示せよ.

section_023.py
import re
from training.json_read_020 import uk_find

if __name__=="__main__":
    pattern = re.compile(r'^=.*')
    pattern2 = re.compile(r'^={2}')
    pattern3 = re.compile(r'^={3}')
    pattern4 = re.compile(r'^={4}')

    lines=uk_find()
    for line in lines.split('\n'):
        if pattern.match(line):
            if pattern4.match(line):
                print(line.lstrip('====').rstrip('====')+':レベル4')
            elif pattern3.match(line):
                print(line.lstrip('===').rstrip('===')+':レベル3')
            elif pattern2.match(line):
                print(line.lstrip('==').rstrip('==')+':レベル2')
            else:
                print('no match')
result
国名:レベル2
歴史:レベル2
地理:レベル2
気候:レベル3
(長いので略)

Process finished with exit code 0

感想:コンパイルパターンを4つ作ってからまず=から始まる行を抜き出して、後はレベルに応じて処理を分岐させたが、けっこう強引。他にもいい方法がありそう。

024. ファイル参照の抽出

記事から参照されているメディアファイルをすべて抜き出せ.

media_024.py
from training.json_read_020 import uk_find
import re

if __name__=="__main__":
    pattern = re.compile(r".*(ファイル|File).*")
    pattern2 = re.compile(r"^|.*")
    lines = uk_find()
    for line in lines.split('\n'):
        if pattern2.search(line):
            line = line.lstrip('|')
        if pattern.search(line):
            start = line.find(':')+1
            end = line.find('|')
            print(line[start:end])

result
Royal Coat of Arms of the United Kingdom.svg
Battle of Waterloo 1815.PNG
The British Empire.png
Uk topo en.jpg
BenNevis2005.jpg
(長いので略)

感想:スライスの位置を決めるのに、マークアップ早見表からファイルの部分の形式にあった処理を実施したのが工夫ポイント

2
4
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
4