yasuokaの日記: UDPipe APIのpython3ラッパー
昨日の日記を読みながら、LINDAT/CLARINのUDPipe API向けpython3ラッパー「UDPipe2UD.py」を書いてみた。Universal Dependenciesのid、form、lemma、upos、xpos、feats、head、deprel、deps、miscを全部格納するようにしたため、ちょっと長くなってしまった。
#! /usr/bin/python3 -i
class UDPipeEntry:
def __init__(self,result):
self.result=result
if "\n" in result:
t=[]
for r in result.split("\n"):
w=UDPipeEntry(r)
if w.id>0:
t.append(w)
for i,w in enumerate(t):
w.head=w if w.head==0 else t[i+w.head-w.id]
self.tokens=t
else:
w=result.split("\t")
try:
w[0],w[6]=int(w[0]),int(w[6])
except:
w=[0]*10
self.id,self.form,self.lemma,self.upos,self.xpos,self.feats,self.head,self.deprel,self.deps,self.misc=w if len(w)==10 else [0]*10
def __repr__(self):
return self.result
def __getitem__(self,item):
return self.tokens[item]
def __len__(self):
return len(self.tokens)
def browse(self):
import webbrowser,urllib.parse
h="http://kanji.zinbun.kyoto-u.ac.jp/~yasuoka/kyodokenkyu/ud-kanbun/conllusvg/viewer.svg"
webbrowser.open(h+"#"+urllib.parse.quote(str(self)))
class UDPipe2UD:
def __init__(self,lang="ja",option="tokenizer&tagger&parser"):
self.parseURL="http://lindat.mff.cuni.cz/services/udpipe/api/process?model="+lang+"&"+option
def __call__(self,sentence):
import urllib.request,urllib.parse,json
with urllib.request.urlopen(self.parseURL+"&data="+urllib.parse.quote(sentence)) as r:
q=r.read()
return UDPipeEntry(json.loads(q)["result"])
上のプログラムを「UDPipe2UD.py」に保存したら、とりあえず「望遠鏡で泳ぐ彼女を見た」をUDPipe2UDで係り受け解析してみよう。
% python3 -i UDPipe2UD.py
>>> ja=UDPipe2UD(lang="ja")
>>> s=ja("望遠鏡で泳ぐ彼女を見た")
>>> s.browse()
>>> print(s)
# newdoc
# newpar
# sent_id = 1
# text = 望遠鏡で泳ぐ彼女を見た
1 望遠鏡 望遠鏡 NOUN NN _ 3 obl _ SpaceAfter=No
2 で で ADP PS _ 1 case _ SpaceAfter=No
3 泳ぐ 泳ぐ VERB VV _ 4 acl _ SpaceAfter=No
4 彼女 彼女 PRON NP _ 6 obj _ SpaceAfter=No
5 を を ADP PS _ 4 case _ SpaceAfter=No
6 見 見る VERB VV _ 0 root _ SpaceAfter=No
7 た た AUX AV _ 6 aux _ SpaceAfter=No
うまく行けば、こんな感じのブラウザが立ち上がってきて、↑のUniversal Dependenciesが出力される。本来「望遠鏡←obl─見」となるべきところ、この出力結果では「望遠鏡←obl─泳ぐ」となってしまっているが、現時点ではUDPipeの解析性能が足りない、ということだろう。
>>> print(s[0])
1 望遠鏡 望遠鏡 NOUN NN _ 3 obl _ SpaceAfter=No
>>> print(s[0].lemma)
望遠鏡
>>> print(s[2])
3 泳ぐ 泳ぐ VERB VV _ 4 acl _ SpaceAfter=No
>>> print(s[2].upos)
VERB
>>> print(s[2].head)
4 彼女 彼女 PRON NP _ 6 obj _ SpaceAfter=No
>>> print(s[2].head.head)
6 見 見る VERB VV _ 0 root _ SpaceAfter=No
なお、この「UDPipe2UD.py」は、他の言語にも対応している。英語なら
>>> en=UDPipe2UD(lang="en")
>>> s=en("He sat down with smiling face")
>>> s.browse()
>>> print(s)
で、古典中国語(漢文)なら
>>> lzh=UDPipe2UD(lang="lzh",option="tokenizer=presegmented&tagger&parser")
>>> s=lzh("不入虎穴不得虎子")
>>> s.browse()
>>> print(s)
で、それぞれ動作するはずである。ぜひ試してみてほしい。
UDPipe APIのpython3ラッパー More ログイン