Source code for pyknp.knp.knp

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

from __future__ import absolute_import
from __future__ import unicode_literals

import distutils.spawn
import os
import unittest

import six

from pyknp import BList
from pyknp import Juman, JUMAN_FORMAT
from pyknp.utils.analyzer import Analyzer


[docs]class KNP(object): """ KNPを用いて構文解析を行う/KNPの解析結果を読み取るモジュール Args: command (str): KNPコマンド option (str): KNP解析オプション (詳細解析結果を出力する-tabは必須。 省略・照応解析を行う -anaphora, 格解析を行わず構文解析のみを行う -dpnd など) rcfile (str): KNP設定ファイルへのパス pattern (str): KNP出力の終端記号 jumancommand (str): JUMANコマンド jumanrcfile (str): JUMAN設定ファイルへのパス jumanpp (bool): JUMAN++を用いるかJUMANを用いるか multithreading (bool): 解析をメインスレッド以外から行う可能性があるか """
[docs] def __init__(self, command='knp', server=None, port=31000, timeout=60, option='-tab', rcfile='', pattern=r'EOS', jumancommand='jumanpp', jumanrcfile='', jumanoption='', jumanpp=True, multithreading=False, ): self.command = command self.server = server self.port = port self.timeout = timeout self.options = option.split() self.rcfile = rcfile self.pattern = pattern if server is not None: self.analyzer = Analyzer(backend='socket', timeout=timeout, server=server, port=port, socket_option='RUN -tab -normal\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) self.jumanpp = jumanpp 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 KNP command: %s" % self.command) self.juman = Juman(command=jumancommand, rcfile=jumanrcfile, option=jumanoption, jumanpp=self.jumanpp, multithreading=multithreading)
[docs] def knp(self, sentence): """ parse関数と同じ """ self.parse(sentence)
[docs] def parse(self, sentence, juman_format=JUMAN_FORMAT.DEFAULT): """ 入力された文字列に対して形態素解析と構文解析を行い、文節列オブジェクトを返す Args: sentence (str): 文を表す文字列 juman_format (JUMAN_FORMAT): Jumanのlattice出力形式 Returns: BList: 文節列オブジェクト """ assert isinstance(sentence, six.text_type) juman_lines = self.juman.juman_lines(sentence) juman_str = "%s%s" % (juman_lines, self.pattern) return self.parse_juman_result(juman_str, juman_format)
[docs] def parse_juman_result(self, juman_str, juman_format=JUMAN_FORMAT.DEFAULT): """ JUMAN出力結果に対して構文解析を行い、文節列オブジェクトを返す Args: juman_str (str): ある文に関するJUMANの出力結果 juman_format (JUMAN_FORMAT): Jumanのlattice出力形式 Returns: BList: 文節列オブジェクト """ knp_lines = self.analyzer.query(juman_str, pattern=r'^%s$' % self.pattern) return BList(knp_lines, self.pattern, juman_format)
[docs] def reparse_knp_result(self, knp_str, juman_format=JUMAN_FORMAT.DEFAULT): """ KNP出力結果に対してもう一度構文解析を行い、文節列オブジェクトを返す。 KNPのfeatureを再付与する場合などに用いる。中身はparse_juman_result関数と同じ。 Args: knp_str (str): ある文に関するKNPの出力結果 juman_format (JUMAN_FORMAT): Jumanのlattice出力形式 Returns: BList: 文節列オブジェクト """ return self.parse_juman_result(knp_str, juman_format=juman_format)
[docs] def result(self, input_str, juman_format=JUMAN_FORMAT.DEFAULT): """ ある文に関するKNP解析結果を文節列オブジェクトに変換する Args: input_str (str): ある文に関するKNPの出力結果 juman_format (JUMAN_FORMAT): Jumanのlattice出力形式 Returns: BList: 文節列オブジェクト """ return BList(input_str, self.pattern, juman_format)
class KNPTest(unittest.TestCase): def setUp(self): self.knp = KNP() def test_dpnd(self): result = self.knp.parse("赤い花が咲いた。") self.assertEqual(len(result), 3) self.assertEqual(result[0].parent.bnst_id, 1) self.assertEqual(len(result[1].children), 1) self.assertEqual(result[1].children[0].bnst_id, 0) self.assertEqual(result[1].parent.bnst_id, 2) self.assertEqual(result[2].parent, None) def test_mrph(self): result = self.knp.parse("赤い花が咲いた。") self.assertEqual( ''.join([mrph.midasi for mrph in result[0].mrph_list()]), '赤い') self.assertEqual( ''.join([mrph.midasi for mrph in result[1].mrph_list()]), '花が') self.assertEqual( ''.join([mrph.midasi for mrph in result[2].mrph_list()]), '咲いた。') def test_mrph2(self): result = self.knp.parse("エネルギーを素敵にENEOS") self.assertEqual( ''.join([mrph.midasi for mrph in result[0].mrph_list()]), 'エネルギーを') self.assertEqual( ''.join([mrph.midasi for mrph in result[1].mrph_list()]), '素敵に') self.assertEqual( ''.join([mrph.midasi for mrph in result[2].mrph_list()]), 'ENEOS') if __name__ == '__main__': unittest.main()