京都大学コーパスのパーズ
コードを見る限り cabocha -f1 としたときの出力の解析みたいだけど、あれは CaboCha 特有のフォーマットじゃなくて京都大学コーパス由来のフォーマットだと思います!
で、ちょっと真面目に解析するように書き直してみた。
- やっていることは analyze じゃなくて parse だと思うので関数名を変更
- dictionary じゃなくてちゃんとオブジェクトに入れる
- 文字列では対象が大きいときに何かと不便なので、適当に iterable なオブジェクトを受け取るように。
- file object でも list でも tuple でも generator でも何でも可。
#!/usr/bin/env python import sys class Token(object): __slots__ = 'surface read base pos ctype cform ne'.split(' ') def __init__(self, **kwd): for name, value in kwd.iteritems(): if name in self.__slots__: setattr(self, name, value) else: raise KeyError() def __str__(self): return '\t'.join(getattr(self, name) for name in self.__slots__) class Chunk(object): __slots__ = 'id link rel score head func tokens'.split(' ') def __init__(self, **kwd): self.tokens = [] for name, value in kwd.iteritems(): if name in self.__slots__: setattr(self, name, value) else: raise KeyError() def __str__(self): s = '* %d %d%s %s/%s %f\n' % \ (self.id, self.link, self.rel, self.head, self.func, self.score) for token in self.tokens: s += str(token) s += '\n' return s class Tree(object): __slots__ = ['chunks'] def __init__(self, chunks): self.chunks = chunks def __str__(self): s = '' for chunk in self.chunks: s += str(chunk) s += 'EOS\n' return s def parse(source): chunks = [] current_chunk = None for line in source: line = line.rstrip('\r\n') if len(line) == 0 or line.startswith('#'): continue if line == 'EOS': # end of sentence yield Tree(chunks) chunks = [] elif line.startswith('* '): # start of chunk (cid, link_rel, head_func, score) = line[2:].split(' ') cid = int(cid) link = int(link_rel[:-1]) rel = link_rel[-1] head_func = head_func.split('/') head = int(head_func[0]) func = int(head_func[1]) score = float(score) current_chunk = Chunk(id = cid, link = link, rel = rel, head = head, func = func, score = score) chunks.append(current_chunk) else: # token (surface, read, base, pos, ctype, cform, ne) = line.split('\t') token = Token(surface = surface, read = read, base = base, pos = pos, ctype = ctype, cform = cform, ne = ne) current_chunk.tokens.append(token) if __name__ == '__main__': import fileinput import locale import optparse default_encoding = locale.getpreferredencoding() parser = optparse.OptionParser() parser.add_option('-i', '--input', dest='input_encoding', metavar='INPUT_ENCODING', default=default_encoding) parser.add_option('-o', '--output', dest='output_encoding', metavar='OUTPUT_ENCODING', default=default_encoding) (options, args) = parser.parse_args() source = (line.decode(options.input_encoding) for line in fileinput.input(args)) for tree in parse(source): for chunk in tree.chunks: for token in chunk.tokens: print token.surface.encode(options.output_encoding)