Source code for pyknp.juman.juman

# -*- encoding: utf-8 -*-

from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals

import distutils.spawn
import os
import sys
import unittest

import six

from pyknp.utils.analyzer import Analyzer
from .mlist import MList
from .morpheme import JUMAN_FORMAT


[docs]class Juman(object): """形態素解析器 JUMAN を Python から利用するためのモジュール Args: command (str): JUMANの実行コマンド option (str): JUMAN解析オプション (ラティス形式 -s, ビーム幅 --beam <int>) rcfile (str): JUMAN設定ファイルへのパス pattern (str): JUMAN出力の終端記号 jumanpp (bool): JUMAN++を用いるかJUMANを用いるか。commandを指定した場合は無視される。 """
[docs] def __init__(self, command='jumanpp', server=None, port=32000, timeout=30, option='', rcfile='', ignorepattern='', pattern=r'^EOS$', jumanpp=True, multithreading=False, ): if jumanpp or command != 'jumanpp': self.command = command self.options = option.split() else: self.command = 'juman' self.options = option.split() + ['-e2', '-B'] self.server = server self.port = port self.timeout = timeout self.rcfile = rcfile self.ignorepattern = ignorepattern self.pattern = pattern if server is not None: self.analyzer = Analyzer(backend='socket', timeout=timeout, server=server, port=port, socket_option='RUN -e2\n') else: cmds = [self.command] + self.options if self.rcfile: cmds += ['-r', self.rcfile] self.analyzer = Analyzer(backend='subprocess', multithreading=multithreading, timeout=timeout, command=cmds) if self.rcfile and not os.path.isfile(os.path.expanduser(self.rcfile)): raise Exception("Can't read rcfile (%s)!" % self.rcfile) if distutils.spawn.find_executable(self.command) is None: raise Exception("Can't find JUMAN command: %s" % self.command)
[docs] def juman_lines(self, input_str): """ 入力文字列に対して形態素解析を行い、そのJuman出力結果を返す Args: input_str (str): 文を表す文字列 Returns: str: Juman出力結果 """ if '\n' in input_str: input_str = input_str.replace('\n', '') print('Analysis is done ignoring "\\n".', file=sys.stderr) return self.analyzer.query(input_str, pattern=self.pattern)
[docs] def juman(self, input_str, juman_format=JUMAN_FORMAT.DEFAULT): """ analysis関数と同じ """ assert isinstance(input_str, six.text_type) result = MList(self.juman_lines(input_str), juman_format) return result
[docs] def analysis(self, input_str, juman_format=JUMAN_FORMAT.DEFAULT): """ 入力文字列に対して形態素解析し、その結果を MList オブジェクトとして返す Args: input_str (str): 文を表す文字列 juman_format (JUMAN_FORMAT): Jumanのlattice出力形式 Returns: MList: 形態素列オブジェクト """ return self.juman(input_str, juman_format)
[docs] def result(self, input_str, juman_format=JUMAN_FORMAT.DEFAULT): """ Juman出力結果に対して、その結果を MList オブジェクトとして返す Args: input_str (str): Juman出力結果 juman_format (JUMAN_FORMAT): Jumanのlattice出力形式 Returns: MList: 形態素列オブジェクト """ return MList(input_str, juman_format)
class JumanTest(unittest.TestCase): def setUp(self): self.jumanpp = Juman() self.juman = Juman(jumanpp=False) # JUMANPP def test_normal_jumanpp(self): test_str = "この文を解析してください。" result = self.jumanpp.analysis(test_str) self.assertEqual(len(result), 7) self.assertEqual(''.join(mrph.midasi for mrph in result), test_str) self.assertGreaterEqual(len(result.spec().split("\n")), 7) def test_nominalization_jumanpp(self): test_str = "音の響きを感じる。" result = self.jumanpp.analysis(test_str) self.assertEqual(len(result), 6) self.assertEqual(''.join(mrph.midasi for mrph in result), test_str) self.assertGreaterEqual(len(result.spec().split("\n")), 6) self.assertEqual(result[2].midasi, "響き") self.assertEqual(result[2].hinsi, "名詞") def test_whitespace_jumanpp(self): test_str = "半角 スペース" result = self.jumanpp.analysis(test_str) self.assertEqual(len(result), 3) self.assertEqual((result[1].bunrui == '空白'), True) self.assertEqual(''.join(mrph.midasi for mrph in result), test_str.replace(" ", "\ ")) self.assertGreaterEqual(len(result.spec().split("\n")), 3) def test_eos(self): test_str = "エネルギーを素敵にENEOS" result = self.jumanpp.analysis(test_str) self.assertEqual(''.join(mrph.midasi for mrph in result), test_str) def test_eos2(self): test_str = "Canon EOS 80D買った" result = self.jumanpp.analysis(test_str) self.assertEqual(''.join(mrph.midasi for mrph in result), test_str.replace(" ", "\ ")) def test_dquo(self): test_str = "\"最高\"の気分" result = self.jumanpp.analysis(test_str) self.assertEqual(''.join(mrph.midasi for mrph in result), test_str) def test_escape(self): test_str = "&lt;tag&gt;\\エス\'ケープ" result = self.jumanpp.analysis(test_str) self.assertEqual(''.join(mrph.midasi for mrph in result), test_str) def test_cr(self): test_str = "これは\rどう" result = self.jumanpp.analysis(test_str) self.assertEqual(''.join(mrph.midasi for mrph in result), test_str) # JUMAN def test_normal_juman(self): test_str = "この文を解析してください。" result = self.juman.analysis(test_str) self.assertEqual(len(result), 7) self.assertEqual(''.join(mrph.midasi for mrph in result), test_str) self.assertGreaterEqual(len(result.spec().split("\n")), 7) def test_whitespace_juman(self): test_str = "半角 スペース" result = self.juman.analysis(test_str) self.assertEqual(len(result), 4) # 半|角|\ |スペース self.assertEqual((result[2].bunrui == '空白'), True) self.assertEqual(''.join(mrph.midasi for mrph in result), test_str.replace(" ", "\ ")) self.assertGreaterEqual(len(result.spec().split("\n")), 4) if __name__ == '__main__': unittest.main()