"Diary" インターネットさんへの恩返し

いつもソースコードコピペばかりなので,みなさまへ少しばかりの恩返しを

言語処理100本ノック 2015をやってみた(第3章)



スポンサーリンク

いやぁ、流石に難しくなってきた。汚いコードですいません。


20. JSONデータの読み込み

【プログラム】

#!/usr/bin/env python
# coding:utf-8

import json

temp={}

f = open('jawiki-country.json', 'r')
i = 0

for line in f:
        temp[i]=json.loads(line)
        i+=1

f.close()

for k1,v1 in temp.iteritems():
        if temp[k1]["title"]==u"イギリス":
                print temp[k1]["text"]
                break

【実行&結果】

$ sudo python 20.py
{{redirect|UK}}
{{基礎情報 国
|略名 = イギリス
|日本語国名 = グレートブリテン及び北アイルランド連合王国
|公式国名 = {{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/>
・
・
・
<省略>

【苦労した点】
JSONファイル内は1行づつ、辞書型に入れる必要あり。
テキストを取ってきた後、そのまんまjson.loadでぶち込めばいいのかと思ったら、出来無いみたい。その為、1行取ってきては辞書型配列の要素[x]に入れていく必要あり。

ご参考:自然言語処理 - 言語処理100本ノックをやってみる 第3章:正規表現 - Qiita

【プログラム(ダメなやり方)】

import json
f = open('jawiki-country.json', 'r')
jsonData = json.load(f)
f.close()

【結果】

$ sudo python 20.py
Traceback (most recent call last):
  File "20.py", line 4, in <module>
    jsonData = json.load(f)
  File "/usr/lib/python2.7/json/__init__.py", line 278, in load
    **kw)
  File "/usr/lib/python2.7/json/__init__.py", line 326, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 369, in decode
    raise ValueError(errmsg("Extra data", s, end, len(s)))
ValueError: Extra data: line 2 column 1 - line 207 column 1 (char 55587 - 9949191)

・日本語処理
もう、python系の日本語処理がイマイチ理解できない。Linux環境でやっているものの日本語設定がちゃんと出来ていない状態で勢いでやっていたのでその点でちゃんと環境作るのに苦労した。
Ubuntuでlocaleを追加する方法 · DQNEO起業日記


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

【プログラム】

#!/usr/bin/env python
# coding:utf-8

import json
temp={}

f = open('jawiki-country.json', 'r')
i = 0

for line in f:
        temp[i]=json.loads(line)
        i+=1

f.close()

temp_text_arr=[]

for k1,v1 in temp.iteritems():
        if temp[k1]["title"]==u"イギリス":
                temp_text_arr = temp[k1]["text"].split("\n")
                break

for line in temp_text_arr:
        if "Category" in line:
                print line

【実行&結果】

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


22. カテゴリ名の抽出

【プログラム】

#!/usr/bin/env python
# coding:utf-8

import json
import re

temp={}

f = open('jawiki-country.json', 'r')
for i,line in enumerate(f):
        temp[i]=json.loads(line)

f.close()

temp_text_arr=[]
for k1,v1 in temp.iteritems():
        if temp[k1]["title"]==u"イギリス":
                #print temp[k1]["title"]
                temp_text_arr = temp[k1]["text"].split("\n")
                break

temp_cate_val=[]
for line in temp_text_arr:
        if "Category" in line:
                temp_cate_val = line.split(":")
                print re.sub(r'[\]\*\|]',"",temp_cate_val[1])


【実行&結果】

$ sudo python 22.py
イギリス
英連邦王国
G8加盟国
欧州連合加盟国
海洋国家
君主国
島国くれいとふりてん
1801年に設立された州・地域


23. セクション構造

【プログラム】

#!/usr/bin/env python
# coding:utf-8

import json
import re

temp={}

f = open('jawiki-country.json', 'r')
for i,line in enumerate(f):
        temp[i]=json.loads(line)
f.close()

temp_text_arr=[]

for k1,v1 in temp.iteritems():
        if temp[k1]["title"]==u"イギリス":
                #print temp[k1]["title"]
                temp_text_arr = temp[k1]["text"].split("\n")
                break

temp_cate_val=[]
for line in temp_text_arr:
        if "==" in line:
                tmp = re.sub(r"={2,4}$","",line)
                tmp = re.sub(r"^={4}","  3.",tmp)
                tmp = re.sub(r"^={3}"," 2.",tmp)
                tmp = re.sub(r"^={2}","1.",tmp)
                print tmp

【実行&結果】

sudo python 23.py
1.国名
1.歴史
1.地理
 2.気候
1.政治
1.外交と軍事
1.地方行政区分
 2.主要都市
1.科学技術
1.経済
 2.鉱業
・
・
・
<省略>

正規表現難しいなぁもっと頭がいい人だと簡単にできるだろうけど。。。
http://qiita.com/hiroshi_takezawa/items/c88162c8946805a67270
文字列の置換 (単純・正規表現) replace regexp » Python Snippets
7.2. re — 正規表現操作 — Python 2.7ja1 documentation


24. ファイル参照の抽出

【プログラム】

#!/usr/bin/env python
# coding:utf-8

import json
import re

temp={}

f = open('jawiki-country.json', 'r')
for i,line in enumerate(f):
        temp[i]=json.loads(line)
f.close()

temp_text_arr=[]

for k1,v1 in temp.iteritems():
        if temp[k1]["title"]==u"イギリス":
                temp_text_arr = temp[k1]["text"].split("\n")
                break

temp_val=[]
for line in temp_text_arr:
        if (u"ファイル" in line) or ("File:" in line):
                temp_val = filter(lambda w: len(w) > 0, re.split(r':|\|', line))
                print temp_val[1]

【実行&結果】

$ sudo python 24.py
Royal Coat of Arms of the United Kingdom.svg
Battle of Waterloo 1815.PNG
The British Empire.png
Uk topo en.jpg
BenNevis2005.jpg
Elizabeth II greets NASA GSFC employees, May 8, 2007 edit.jpg
Palace of Westminster, London - Feb 2007.jpg
David Cameron and Barack Obama at the G20 Summit in Toronto.jpg
Soldiers Trooping the Colour, 16th June 2007.jpg
Scotland Parliament Holyrood.jpg
London.bankofengland.arp.jpg
・
・
・
<省略>

これあってんのかな…一応どの表記がメディアファイルを意味するのか表記ルールがよくわからなかったのですが、行の冒頭に"ファイル"、"File:"とあるものを出力対象にしました。実際のWikipedaのページを見るとファイル名内のスペースのところ_(アンダーバー)になっているのでそこまでしたほうがいいのかな。

[参考]
ファイル名抽出部分で以下のSplitの区切り文字複数指定方法を使わせて頂きました。
Python Tips:文字列を複数の区切り文字で分割したい - Life with Python


25. テンプレートの抽出

構造は大雑把に書くとこんな感じになっている。
f:id:azumami:20150928130845p:plain


2階層目以降の値はそのままテキストとして入れた。つまり |、とか{{}}とかそのままテキストとして入っています。

【プログラム】

#!/usr/bin/env python
# coding:utf-8

import json
import re

temp={}

f = open('jawiki-country.json', 'r')
for i,line in enumerate(f):
        temp[i]=json.loads(line)
f.close()

for k1,v1 in temp.iteritems():
        if temp[k1]["title"]==u"イギリス":
                temp_text_arr = temp[k1]["text"].split("\n")
                break

pos_start=""
pos_end=""
for i,line in enumerate(temp_text_arr):
        if line == u"{{基礎情報 国":
                pos_start = i
        if line == "}}":
                pos_end = i
                break

tmp=[]
temp_ans ={}
last_field=""
for i in range(pos_start+1,pos_end):
        if re.search('^\*', temp_text_arr[i]):
                temp_ans[last_field] += temp_text_arr[i]
        else:
                tmp = temp_text_arr[i].lstrip("|").split(" = ")
                temp_ans[tmp[0]]=tmp[1]
                last_field = tmp[0]

for k,v in temp_ans.iteritems():
        print k,'=',v

【実行&結果】

$ sudo python 25.py
人口値 = 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>
国章リンク = ([[イギリスの国章|国章]])
元首等氏名 = [[エリザベス2世]]
時間帯 = ±0
標語 = {{lang|fr|Dieu et mon droit}}<br/>([[フランス語]]:神と私の権利)
面積順位 = 76


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

【プログラム】

#!/usr/bin/env python
# coding:utf-8

import json
import re

temp={}

f = open('jawiki-country.json', 'r')
for i,line in enumerate(f):
        temp[i]=json.loads(line)
f.close()

for k1,v1 in temp.iteritems():
        if temp[k1]["title"]==u"イギリス":
                temp_text_arr = temp[k1]["text"].split("\n")
                break

pos_start=""
pos_end=""
for i,line in enumerate(temp_text_arr):
        if line == u"{{基礎情報 国":
                pos_start = i
        if line == "}}":
                pos_end = i
                break

tmp=[]
temp_ans ={}
last_field=""
for i in range(pos_start+1,pos_end):
        t = temp_text_arr[i]
        t = re.sub(r"\'{2,5}","",t)
        if re.search('^\*', temp_text_arr[i]):
                temp_ans[last_field] += t
        else:
                tmp = t.lstrip("|").split(" = ")
                temp_ans[tmp[0]]=tmp[1]
                last_field = tmp[0]

print "\n\n"
for k,v in temp_ans.iteritems():
        print k,'=',v

以下を入れることで、"'"が2~5こある場合は、置換して削除

        t = temp_text_arr[i]
        t = re.sub(r"\'{2,5}","",t)

【実行&結果】

$ sudo python 26.py

<省略>
・
・
・
確立形態4 = 現在の国号「グレートブリテン及び北アイルランド連合王国」に変更
・
・
・
<省略>


27. 内部リンクの除去

【プログラム】

#!/usr/bin/env python
# coding:utf-8

import json
import re

temp={}

f = open('jawiki-country.json', 'r')
for i,line in enumerate(f):
        temp[i]=json.loads(line)
f.close()

for k1,v1 in temp.iteritems():
        if temp[k1]["title"]==u"イギリス":
                temp_text_arr = temp[k1]["text"].split("\n")
                break

pos_start=""
pos_end=""
for i,line in enumerate(temp_text_arr):
        if line == u"{{基礎情報 国":
                pos_start = i
        if line == "}}":
                pos_end = i
                break

tmp=[]
temp_ans ={}
last_field=""
for i in range(pos_start+1,pos_end):
        t = temp_text_arr[i]
        t = re.sub(r"\'{2,5}","",t)

        if not u"[[ファイル:" in temp_text_arr[i]:
                t = re.sub(r"\[{2}?([^\]]*)\|([^\[]*)\]{2}?",r"\1",t)
                t = re.sub(r"\[{2}?([^\|^\[^\]]*)\]{2}?",r"\1",t)
        if re.search('^\*', temp_text_arr[i]):
                temp_ans[last_field] += t
        else:
                tmp = t.lstrip("|").split(" = ")
                temp_ans[tmp[0]]=tmp[1]
                last_field = tmp[0]

for k,v in temp_ans.iteritems():
        print k,'=',v

【実行&結果】

$ sudo python 27.py

・
・
・
<省略>
・
・

以下の箇所が、内部リンクだったのが置換された後の状態

確立形態1 = イングランド王国/スコットランド王国<br />(両国とも連合法 (1707年)まで)
確立形態2 = グレートブリテン王国建国<br />(連合法 (1707年))
首都 = ロンドン
元首等肩書 = イギリスの君主
ccTLD = .uk / .gb<ref>使用は.ukに比べ圧倒的少数。</ref>
確立形態3 = グレートブリテン及びアイルランド連合王国建国<br />(連合法 (1800年))
公用語 = 英語(事実上)
首相等氏名 = デーヴィッド・キャメロン
首相等肩書 = イギリスの首相
通貨 = スターリング・ポンド (&pound;)
確立年月日4 = 1927年
国歌 = 女王陛下万歳
確立年月日1 = 927年/843年
確立年月日2 = 1707年
確立年月日3 = 1801年
国章リンク = (イギリスの国章)
元首等氏名 = エリザベス2世
標語 = {{lang|fr|Dieu et mon droit}}<br/>(フランス語:神と私の権利)
公式国名 = {{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>


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

【プログラム】

#!/usr/bin/env python
# coding:utf-8

import json
import re

temp={}

f = open('jawiki-country.json', 'r')
for i,line in enumerate(f):
        temp[i]=json.loads(line)
f.close()

for k1,v1 in temp.iteritems():
        if temp[k1]["title"]==u"イギリス":
                temp_text_arr = temp[k1]["text"].split("\n")
                break

pos_start=""
pos_end=""
for i,line in enumerate(temp_text_arr):
        if line == u"{{基礎情報 国":
                pos_start = i
        if line == "}}":
                pos_end = i
                break

tmp=[]
temp_ans ={}
last_field=""
for i in range(pos_start+1,pos_end):
        t = temp_text_arr[i]
        t = re.sub(r"\'{2,5}","",t)

        if not u"[[ファイル:" in temp_text_arr[i]:
                #内部リンク [ | ]があるものを処理
                t = re.sub(r"\[{2}?([^\]]*)\|([^\[]*)\]{2}?",r"\1",t)
                #内部リンク[[]]形式のものを削除
                t = re.sub(r"\[{2}?([^\|^\[^\]]*)\]{2}?",r"\1",t)
                #< />書式のものを削除
                t = re.sub(r"<.*/.*>","",t)
                #{*|*|*}の処理
                t = re.sub(r"\{\{.*\|.*\|(.*)\}\}",r"\1",t)

        #[[ファイル:Wiki.png|thumb|説明文]]の処理
        if (u"[[ファイル:" in t) or ("File:" in t):
                temp_val = filter(lambda w: len(w) > 0, re.split(r':|\|', t))
                t = temp_val[0].replace("[[","") + ":"  + temp_val[1]

        if re.search('^\*', temp_text_arr[i]):
                temp_ans[last_field] += t
        else:
                tmp = t.lstrip("|").split(" = ")
                temp_ans[tmp[0]]=tmp[1]
                last_field = tmp[0]

for k,v in temp_ans.iteritems():
        print k,'=',v

【実行&結果】

$ sudo python 28.py
人口値 = 63,181,775
国章リンク = (イギリスの国章)
元首等氏名 = エリザベス2世
時間帯 = ±0
標語 = Dieu et mon droit(フランス語:神と私の権利)
面積順位 = 76
公式国名 = 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(スコットランド語)
Unitet Kängdom o Great Brittain an Norlin Airlann(アルスター・スコットランド語)
注記 =
面積値 = 244,820
通貨コード = GBP
・
・
・
<省略>

正規表現むずい。


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

【プログラム】

#!/usr/bin/env python
# coding:utf-8
import json
import re
import requests

temp={}

f = open('jawiki-country.json', 'r')
for i,line in enumerate(f):
        temp[i]=json.loads(line)
f.close()

for k1,v1 in temp.iteritems():
        if temp[k1]["title"]==u"イギリス":
                temp_text_arr = temp[k1]["text"].split("\n")
                break

pos_start=""
pos_end=""
for i,line in enumerate(temp_text_arr):
        if line == u"{{基礎情報 国":
                pos_start = i
        if line == "}}":
                pos_end = i
                break

tmp=[]
temp_ans ={}
last_field=""
for i in range(pos_start+1,pos_end):
        t = temp_text_arr[i]
        t = re.sub(r"\'{2,5}","",t)

        if not u"[[ファイル:" in temp_text_arr[i]:
                #内部リンク [ | ]があるものを処理
                t = re.sub(r"\[{2}?([^\]]*)\|([^\[]*)\]{2}?",r"\1",t)
                #内部リンク[[]]形式のものを削除
                t = re.sub(r"\[{2}?([^\|^\[^\]]*)\]{2}?",r"\1",t)
                #< />書式のものを削除
                t = re.sub(r"<.*/.*>","",t)
                #{*|*|*}の処理
                t = re.sub(r"\{\{.*\|.*\|(.*)\}\}",r"\1",t)
                #*,**の処理
                t = re.sub(r"\*{1,2}","\n",t)

        #[[ファイル:Wiki.png|thumb|説明文]]の処理
        if (u"[[ファイル:" in t) or ("File:" in t):
                temp_val = filter(lambda w: len(w) > 0, re.split(r':|\|', t))
                t = temp_val[0].replace("[[","") + ":"  + temp_val[1]

        if re.search('^\*', temp_text_arr[i]):
                temp_ans[last_field] += t
        else:
                tmp = t.lstrip("|").split(" = ")
                temp_ans[tmp[0]]=tmp[1]
                last_field = tmp[0]

for k,v in temp_ans.iteritems():
        #print k,'=',v
        if u"国旗画像" in k:
                fname = v.replace(" ","_")

endpoint = "https://en.wikipedia.org/w/"
q = endpoint + "api.php?action=query&prop=imageinfo&format=json&iiprop=url&titles=File%3A" + fname

r = requests.get(q)
data = r.json()
print data['query']['pages']["23473560"]['imageinfo'][0]["descriptionurl"]

【実行&結果】
警告が出るけど、「https://en.wikipedia.org/wiki/File:Flag_of_the_United_Kingdom.svg」が抽出できているのでよしとする。

 sudo python 29.py
https://en.wikipedia.org/w/api.php?action=query&prop=imageinfo&format=json&iiprop=url&titles=File%3AFlag_of_the_United_Kingdom.svg
/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/util/ssl_.py:90: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning
https://en.wikipedia.org/wiki/File:Flag_of_the_United_Kingdom.svg