「言語処理100本ノック」 第3章をPythonで解く
言語処理100本ノックの3章を解きました。
3章は、正規表現を用いてwikipediaの文書を処理する問題です。
解答例としてどうぞ。質問,ご指摘などがありましたら、コメントしてください。
言語処理100本ノック第3章
20. JSONデータの読み込み
Wikipedia記事のJSONファイルを読み込み,「イギリス」に関する記事本文を表示せよ.問題21-29では,ここで抽出した記事本文に対して実行せよ.
import json def chose_uk(): with open('jawiki-country.json', 'r') as json_file: for line in json_file: line = json.loads(line) if line['title'] == 'イギリス': uk_file = line break return uk_file if __name__ == '__main__': print(chose_uk())
jsonファイルを読み込むために標準ライブラリのjson
を利用します。
21. カテゴリ名を含む行を抽出
記事中でカテゴリ名を宣言している行を抽出せよ.
import re import json uk_file = chose_uk() lines = uk_file['text'].split('\n') pattern = r"\[\[Category:.*\]\]" for line in lines: if re.match(pattern, line): print(line)
[[Category〜]]
となっている部分を正規表現で抜き出します。
22. カテゴリ名の抽出
記事のカテゴリ名を(行単位ではなく名前で)抽出せよ.
import re import json uk_file = chose_uk() lines = uk_file['text'].split('\n') pattern = r"\[\[Category:.*\]\]" for line in lines: if re.match(pattern, line): line = re.sub(r"\[\[Category:", " ", line) line = re.sub(r"(\|.*)*(\|\*)*(\]\])", " ", line) print(line)
21で行った処理に加えて、[[ ]]
などの余分な部分を正規表現で指定して削除します。
23. セクション構造
記事中に含まれるセクション名とそのレベル(例えば"== セクション名 =="なら1)を表示せよ.
import re import json uk_file = chose_uk() lines = uk_file['text'].split('\n') pattern = r"=.+=" for line in lines: if re.match(pattern, line): result = line.count('=') // 2 - 1 line = re.sub(r"=", "", line) print(line, 'レベル: {}'.format(result))
=
で囲まれている部分を見つけて、=
の数を数えてレベルを決めます。
24. ファイル参照の抽出
記事から参照されているメディアファイルをすべて抜き出せ
import re import json uk_file = chose_uk() lines = uk_file['text'].split('\n') pattern = r".*(ファイル|File):" for line in lines: if re.match(pattern, line): line = re.sub(r".*(ファイル|File):", "", line) line = re.sub(r"\|.*", "", line) print(line)
25. テンプレートの抽出
自然数Nをコマンドライン引数などの手段で受け取り,入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ.
import re import json def make_uk_dict(): uk_file = chose_uk() lines = uk_file['text'].split('\n') pattern = r"\|.*\s=\s.*" uk_dict = {} for line in lines: if re.match(pattern, line): key = re.sub(r"(=.*|\|)", "", line) value = re.sub(r".*=", "", line) uk_dict[key] = value return uk_dict if __name__ == '__main__': uk_dict = make_uk_dict() for key in uk_dict: print(key, uk_dict[key])
26. 強調マークアップの除去
25の処理時に,テンプレートの値からMediaWikiの強調マークアップ(弱い強調,強調,強い強調のすべて)を除去してテキストに変換せよ(参考: マークアップ早見表)
import re import json def delete_markup(uk_dict): pattern = r".*'+.*'+" for key in uk_dict: if re.match(pattern, uk_dict[key]): uk_dict[key] = re.sub(r"'+", "", line) return uk_dict if __name__ == '__main__': uk_dict = make_uk_dict() print(delete_markup(uk_dict))
27. 内部リンクの除去
26の処理に加えて,テンプレートの値からMediaWikiの内部リンクマークアップを除去し,テキストに変換せよ(参考: マークアップ早見表)
import re import json def delete_link(uk_dict): pattern = r".*\[\[.*\]\].*" for key in uk_dict: if re.match(pattern, uk_dict[key]): if re.match(r"^(?!.*:).+$", uk_dict[key]): uk_dict[key] = re.sub(r".*\[\[.*\|", "", uk_dict[key]) uk_dict[key] = re.sub(r"\[\[", "", uk_dict[key]) uk_dict[key] = re.sub(r"\]\]\)|\]\]", "", uk_dict[key]) return uk_dict if __name__ == '__main__': uk_dict = make_uk_dict() uk_dict = delete_markup(uk_dict) uk_dict = delete_link(uk_dict) print(uk_dict)
28. MediaWikiマークアップの除去
各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).
import re import json def delete_media_markup(uk_dict): pattern = r".*{{.*\|.*\|.*}}.*" for key in uk_dict: if re.match(pattern, uk_dict[key]): if re.match(pattern, uk_dict[key]): uk_dict[key] = re.sub(r"{{.*\|.*\|", "", uk_dict[key]) uk_dict[key] = re.sub(r"}}", "", uk_dict[key]) return uk_dict if __name__ == '__main__': uk_dict = make_uk_dict() uk_dict = delete_markup(uk_dict) uk_dict = delete_link(uk_dict) uk_dict = delete_media_markup(uk_dict) print(uk_dict)
29. 国旗画像のURLを取得する
テンプレートの内容を利用し,国旗画像のURLを取得せよ.(ヒント: MediaWiki APIのimageinfoを呼び出して,ファイル参照をURLに変換すればよい)
import re import json import requests if __name__ == '__main__': uk_dict = make_uk_dict() uk_dict = delete_markup(uk_dict) uk_dict = delete_link(uk_dict) uk_dict = delete_media_markup(uk_dict) params = {'action':'query', 'titles':'File:' + uk_dict["国旗画像 "], 'format':'json', 'prop':'imageinfo', 'iiprop':'url', 'User-Agent':'knakajima' } url = 'https://www.mediawiki.org/w/api.php' result = requests.get(url, params).json() print(result['query']['pages']['-1'])