目次

igo-py

since 2011-09-17

もともとは Java で実装されていた形態素解析器 Igo を Python に移植したもの。

http://hideaki-t.blogspot.com/2010/11/igopython.html

https://code.launchpad.net/~hideaki-t/+junk/igo-py

https://github.com/hideaki-t/igo-python

辞書フォーマット及び解析結果は、ほぼMeCab互換とされる。

Windows で動かしてみる

bzr branch lp:~hideaki-t/+junk/igo-py

辞書はJava版を使うという話:

辞書のコンパイルのために Java 版を使う:

> "C:\Program Files (x86)\Java\jre6\bin\java" -cp igo-0.4.3.jar \
net.reduls.igo.bin.BuildDic ipadic mecab-ipadic-2.7.0-20070801 EUC-JP
### Build word trie
### Build word dictionary
### Build matrix
### Build char-category dictionary
DONE

test.py を t = igo.Tagger.Tagger('ipadic') に書き換える。カレントに ipadic ディレクトリができているという前提。

C:\work\nvda\igo-py>python test.py
こんにちは 感動詞,*,*,*,*,*,こんにちは,コンニチハ,コンニチワ 0
世界 名詞,一般,*,*,*,*,世界,セカイ,セカイ 5

もうすこし詳しく:

>>> import igo.Tagger
>>> t = igo.Tagger.Tagger('ipadic')
>>> a = t.parse(u'私の名前は中野です')
 
>>> len(a)
6
 
>>> a[0]
<igo.Tagger.Morpheme instance at 0x025193C8>
 
>>> print a[0].surface>>> print a[1].surface>>> print a[2].surface
名前
>>> print a[3].surface
は
 
>>> dir(a[0])
['__doc__', '__init__', '__module__', 'feature', 'start', 'surface']

NVDA の音声ドライバとして

nvdajp で使うことを想定して、ログビューアに「読み」を出力するだけのドライバを書いた:

#synthDrivers/dummy-igo.py
#A part of NonVisual Desktop Access (NVDA)
#Copyright (C) 2011 Takuya Nishimoto (nishimotz.com)
#This file is covered by the GNU General Public License.
#See the file COPYING for more details.
 
import synthDriverHandler
from logHandler import log
import igo.Tagger
 
class SynthDriver(synthDriverHandler.SynthDriver):
    """A dummy igo driver.
    """
    name="silence-igo"
    description=_("dummy igo driver")
 
    supportedSettings=[]
 
    @classmethod
    def check(cls):
        return True
 
    def __init__(self):
        self.tagger = igo.Tagger.Tagger('igo/ipadic')
 
    def speak(self,speechSequence):
		for item in speechSequence:
			if isinstance(item, basestring):
				textList = []
				for m in self.tagger.parse(item):
					a = m.feature.split(',')
					if len(a) >= 8: textList.append(a[8])
				text = u" ".join(textList)
				log.info(text)
			else:
				pass

import igo.Tagger は source 直下に igo を置くことに対応する。 場所を動かすと igo.* の中で初期化が失敗する。

Open JTalk の辞書を使ってみる

open-jtalk 1.04 のパッケージを取ってきて、mecab-naist-jdic を使う。

> cd C:\work\nvda\jp2011.2.h\source
> "C:\Program Files (x86)\Java\jre6\bin\java" \
  -cp c:\work\nvda\igo-py\igo-0.4.3.jar \
  net.reduls.igo.bin.BuildDic \
  igo\jtalkdic \
  c:\work\open_jtalk-1.04\mecab-naist-jdic EUC-JP 
### Build word trie
### Build word dictionary
### Build matrix
### Build char-category dictionary
DONE

コマンドプロンプトで:

>>> a = tagger.parse(u'私の名前は中野です')
>>> a[0]
<igo.Tagger.Morpheme instance at 0x025A84B8>
>>> print a[0].feature
名詞,代名詞,一般,*,*,*,,ワタシ,ワタシ,0/3,C3
>>> a = tagger.parse(u'今日はいい天気です')
>>> print a[0].feature
名詞,副詞可能,*,*,*,*,今日,キョウ,キョー,1/2,C3

これを前述の silence-igo.py で使うには init で igo/jtalkdic に変えるだけ。

JTalk igo

いまのところ「漢字だけ読み上げが欠落する」というバグがある状態。

nvdajptext/Mecab.py

before:

def Mecab_analysis(str):
	from logHandler import log
	global mecab_size
	if len(str) == 0: return [None, None]
	head = libmc.mecab_sparse_tonode(mecab, str)
	if head == None: return [None, None]
	mecab_size = 0
 
	# make array of features
	node = head
	i = 0
	while node:
		s = node[0].stat
		if s != MECAB_BOS_NODE and s != MECAB_EOS_NODE:
			c = node[0].length
			s = string_at(node[0].surface, c) + "," + string_at(node[0].feature)
			log.info(s) # for debug
			buf = create_string_buffer(s)
			dst_ptr = mecab_feature[i]
			src_ptr = byref(buf)
			memmove(dst_ptr, src_ptr, len(s)+1)
			i += 1
		node = node[0].next
		mecab_size = i
		if i > FECOUNT: return [mecab_feature, mecab_size]
	return [mecab_feature, mecab_size]

after:

# igo tagger version from here
 
import igo.Tagger
tagger = None
 
# based on Mecab_analysis()
def igo_analysis(str):
	from logHandler import log
	global tagger
	if tagger == None: tagger = igo.Tagger.Tagger('igo/jtalkdic')
	if len(str) == 0: return [None, None]
	mecab_size = 0
	i = 0
	for node in tagger.parse(str.decode('cp932')):
		a = node.feature.split(',')
		if len(a) >= 8:
			s = node.surface + "," + node.feature
			log.info(s) # for debug
			buf = create_string_buffer(s.encode('cp932'))
			dst_ptr = mecab_feature[i]
			src_ptr = byref(buf)
			memmove(dst_ptr, src_ptr, len(s)+1)
			i += 1
			mecab_size = i
			if i > FECOUNT: return [mecab_feature, mecab_size]
	return [mecab_feature, mecab_size]