CaboCha

【Python】CaboChaによる構文解析の基本的な使い方

【Python】CaboChaによる構文解析の基本的な使い方

PythonでCaboChaを用いて構文解析(係り受け解析)をする方法について解説します。

構文解析とは

構文解析とは、文章を文節に分けてそれぞれの構成要素がどのような言語的な関係性を持っているかを解析することを言います。係り受け関係を解析することから係り受け解析ともいわれます。また、構文解析の過程では、形態素に分けるための形態素解析の技術も使われています。

例えば、適当なのですが以下のような文を考えてみます。

この文章では、「私は」→「実装した」、「CaboChaを」→「使って」、「Pythonで」→「実装した」というように各文節間で係り受け関係があります。構文解析では、このような関係性の分析を機械的に実行することができます。

日本語の構文解析エンジンとしてはCaboChaが有名です。CaboChaはオープンソースの構文解析エンジンで、奈良先端科学技術大学出身の工藤拓さんによって開発されているものです。形態素解析エンジンのMeCabも同様によく使用されています。

本記事では、PythonでCaboChaを使って構文解析を実行するための環境準備方法や基本的な使い方について紹介します。

形態素解析エンジンのMeCabというソフトウェアの使い方については「MeCabによる形態素解析の基本的な使い方」でまとめています。興味があれば参考にしてください。

CaboChaを使うための環境準備

CaboChaをpythonで使用できるようにするには以下のような手順で各種ソフトウェアのインストールを実施します。

  1. MeCab(32bit版)をインストールする
  2. CaboCha(32bit版)をインストールする
  3. pip install cabocha-pythonでpython環境を構築する

以下でそれぞれの手順について画面キャプチャ等を使いながら説明します。

MeCab(32bit版)をインストールする

CaboChaは、形態素解析のエンジンとして内部でMeCabを使用しています。そのため、まずは、MeCabの環境の準備が必要です。

MeCab(64bit版)は「pip install mecab-python3」とをするだけで簡単に使用することができるのですが、CaboChaは32bit版のみの対応のため、MeCab(32bit版)を個別にインストールしておく必要があります。

MeCabのダウンロード

MeCabのダウンロードは公式サイトであるこちらへアクセスしてください。ダウンロード欄の[MeCab本体]-[Binary package for MS-Windows]のダウンロードをクリックしてダウンロードしてください。

MeCabダウンロード

MeCabのインストール

ダウンロードしたexeファイルをクリックして画面に従ってインストールします。基本的に画面に従っていけばよいですが、pythonで使用するので文字コードはUTF-8を選択してください。

1.使用する言語を選択します。

MeCabインストール

2.次へをクリックします。

MeCabインストール

3.文字コードは「UTF-8」を選択し、次へをクリックします。

MeCabインストール

4.使用許諾について確認し、同意するを選択して次へをクリックします。

MeCabインストール

5.インストール先を指定します。特に変更する必要はありません。

MeCabインストール

6.プログラムグループを指定します。特に変更する必要はありません。

MeCabインストール

7.インストールをクリックします。

MeCabインストール

8.インストールが開始されます。

MeCabインストール

9.全ユーザーに実行許可を与えるか確認があるので「はい」をクリックします。

MeCabインストール

10.辞書の作成の確認が出るので「OK」をクリックします。

MeCabインストール

11.完了画面が表示されるので「完了」をクリックしてセットアップウィザードを終了します。

MeCabインストール

12.デスクトップの以下の「MeCab」アイコンが表示されればインストール完了です。

MeCabインストール

CaboCha(32bit版)をインストールする

本記事のメインとなるCaboChaのインストールを実施します。

CaboChaのダウンロード

CaboChaの公式サイトのこちらへアクセスし、以下のダウンロードリンクをクリックしてください。

CaboChaダウンロード

リンクをクリックすると、以下のようなGoogleドライブのページへ移ります。

CaboChaダウンロード

画面をスクロールして最新exeをダウンロードしてください。本記事執筆時点での最新は「cabocha-0.69.exe」でした。

CaboChaのインストール

ダウンロードしたexeをクリックして画面に従ってインストールします。基本的に画面に従っていけばよいですが、pythonで使用することを考慮して文字コードはUTF-8を選択してください。

1.使用する言語を選択します。

CaboChaインストール

2.次へをクリックします。

CaboChaインストール

3.文字コードは「UTF-8」を選択し、次へをクリックします。

CaboChaインストール

4.使用許諾を確認したうえで「同意する」を選択して、次へをクリックします。

CaboChaインストール

5.インストール先を指定します。特に変更する必要はありません。

CaboChaインストール

6.プログラムグループを指定します。特に変更する必要はありません。

CaboChaインストール

7.設定を確認してインストールをクリックします。

CaboChaインストール

8.インストールが開始します。

CaboChaインストール

9.全ユーザーに実行許可を与えるか確認があるので「はい」をクリックします。

CaboChaインストール

10.辞書の作成の確認が出るので「OK」をクリックします。

CaboChaインストール

11.完了画面が表示されるので「完了」をクリックしてセットアップウィザードを終了します。

CaboChaインストール

12.デスクトップの以下の「CaboCha」アイコンが表示されればインストール完了です。

CaboChaインストール

PythonでCaboChaを利用できる環境を構築する

上記でCaboChaのPCへのインストールが完了しますが、Pythonで使用できるようにするためには、以下のようにpipでモジュールをインストールする必要があります。

pip install cabocha-python

「Successfully installed cabocha-python-0.69.1」のような形でインストールが成功すればCaboChaをPythonで使用する環境構築は完了です。

【注意点】64bit Pythonに対応していない

CaboChaについては、64bitのPythonには対応していないため注意が必要です。64bit Pythonの環境でpip installを実行しようとすると以下のようなエラーとなります。

OSError: 64bit Python for Windows is not supported

この場合は、32bit版のPythonの環境をインストールして使用する必要があります。

例えばv3.9.12のダウンロードページのこちらに行くと以下のようなダウンロードリンクがありますが、32bitインストーラーを使ってダウンロードしてください。

Python 32ビット ダウンロード

PythonでのCaboChaを使用した構文解析の実装

CaboChaの基本的な使い方

以降では、PythonでCaboChaを使用した構文解析を利用する方法について簡単な例を用いて紹介します。まだ、MeCabやCaboChaをインストールしていない方は上記の環境構築の手順をご確認いただいてインストールしてから試してください。

基本的な使い方

以下の簡単な例を使ってCaboChaの基本的な使い方を見てみましょう。

import CaboCha

# CaboChaの構文解析器を生成する
cabocha = CaboCha.Parser()

# 解析対象の文字列を用意する
sample_text = '私はCaboChaを使ってPythonで構文解析を実装した。'

# 構文解析を実行する
result_tree = cabocha.parse(sample_text)

# 解析結果を表示する
print(result_tree.toString(CaboCha.FORMAT_TREE))
【実行結果】
      私は---------D
   CaboChaを-D     |
        使って-----D
        Pythonで---D
        構文解析を-D
          実装した。
EOS

CaboChaを使用するためには、まずCaboChaをimportする必要があります。

import CaboCha

その後、以下の例のようにCaboCha.Parser()で解析器をインスタンス化します。

# CaboChaの構文解析器を生成する
cabocha = CaboCha.Parser()

後は簡単です。以下の部分のように対象文字列をCaboCha.parseメソッドに渡すだけで解析結果が返却されます。

# 解析対象の文字列を用意する
sample_text = '私はCaboChaを使ってPythonで構文解析を実装した。'

# 構文解析を実行する
result_tree = cabocha.parse(sample_text)

# 解析結果を表示する
print(result_tree.toString(CaboCha.FORMAT_TREE))

解析結果を表示するには、結果に対してtoStringメソッドを実行し、引数にCaboCha.FORMAT_TREEを指定します。実行結果は、係り受け関係を示したツリー構造で表示されます。引数は後述するCaboCha.FORMAT_LATTICEのようにいくつか形式を変える方法があります。

結果の見方についてですが、Dという記号があるところがポイントで、係り先の部分を示すようになっています。この例では、「私は」「使って」「Pythonで」「構文解析を」という4つの文節が「実装した」に係っていることを意味しています。

詳細な係り受け関係の出力

上記の基本的な使い方では、全体の係り受け関係をざっと可視化するには十分でした。さらに詳細な係り受け関係を出力する場合には、出力時のフォーマットでCaboCha.FORMAT_LATTICEを指定します。

import CaboCha

# CaboChaの構文解析器を生成する
cabocha = CaboCha.Parser()

# 解析対象の文字列を用意する
sample_text = '私はCaboChaを使ってPythonで構文解析を実装した。'

# 構文解析を実行する
result_tree = cabocha.parse(sample_text)

# 解析結果を表示する
print(result_tree.toString(CaboCha.FORMAT_LATTICE))
【実行結果】
* 0 5D 0/1 -1.524409
私	名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
* 1 2D 0/1 1.458036
CaboCha	名詞,一般,*,*,*,*,*
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
* 2 5D 0/1 -1.524409
使っ	動詞,自立,*,*,五段・ワ行促音便,連用タ接続,使う,ツカッ,ツカッ
て	助詞,接続助詞,*,*,*,*,て,テ,テ
* 3 5D 0/1 -1.524409
Python	名詞,一般,*,*,*,*,*
で	助詞,格助詞,一般,*,*,*,で,デ,デ
* 4 5D 1/2 -1.524409
構文	名詞,一般,*,*,*,*,構文,コウブン,コーブン
解析	名詞,サ変接続,*,*,*,*,解析,カイセキ,カイセキ
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
* 5 -1D 1/2 0.000000
実装	名詞,サ変接続,*,*,*,*,実装,ジッソウ,ジッソー
し	動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。	記号,句点,*,*,*,*,。,。,。
EOS

結果を見ていただくと分かりますが、形態素の情報を含んだ詳細な結果が出力結果となっていることが分かります。

構文解析結果の見方

構文解析結果の見方の詳細について説明します。まず、構文解析ではTree(全体の木構造)、Chunk(文節)、Token(形態素)という構成をしています。

解析結果の詳細を紐解いてみると以下のようになっています。

*で始まる行は各文節(chunk)を表しており、*に続く情報は以下の構成になっています。

文節番号係り先の文節番号主辞/機能辞の位置係り関係のスコア

*の下の行からは各形態素(token)を表しており、内容は以下の構成になっています。

表層形品詞品詞細分類1品詞細分類2品詞細分類3活用形活用型原形読み発音

上記の例でいうと、最初の「私は」は0番の文節で、「私」と「は」の形態素で構成されていて、5番の文節の「実装した。」に係っていることが分かります。

CaboCha解析結果の各要素を扱う

CaboChaの解析結果の各要素を扱ってプログラミングしたい場合には、解析結果の各情報を取り出す必要があります。

CaboChaの解析結果から各要素を取得するための例を以下で紹介します。

import CaboCha

# CaboChaの構文解析器を生成する
cabocha = CaboCha.Parser()

# 解析対象の文字列を用意する
sample_text = '私はCaboChaを使ってPythonで構文解析を実装した。'

# 構文解析を実行する
result_tree = cabocha.parse(sample_text)

# 個別の要素を扱う
chunk_id = 0
for i in range(result_tree.size()):
    token = result_tree.token(i)

    # 文節の先頭の場合はchunkがNoneではない
    if token.chunk is not None:
        print('===== Chunk')
        print(f'文節番号:{chunk_id}')
        print(f'係り先:{token.chunk.link}')
        print(f'主辞:{token.chunk.head_pos}')
        print(f'機能辞:{token.chunk.func_pos}')
        print(f'係り関係のスコア:{token.chunk.score}')
        chunk_id += 1

    print('----- Token')
    print(f'表層形:{token.surface}')
    print(f'形態素情報:{token.feature}')
【実行結果】
===== Chunk
文節番号:0
係り先:5
主辞:0
機能辞:1
係り関係のスコア:-1.5244090557098389
----- Token
表層形:私
形態素情報:名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
----- Token
表層形:は
形態素情報:助詞,係助詞,*,*,*,*,は,ハ,ワ
===== Chunk
文節番号:1
係り先:2
主辞:0
機能辞:1
係り関係のスコア:1.4580357074737549
----- Token
表層形:CaboCha
形態素情報:名詞,一般,*,*,*,*,*
----- Token
表層形:を
形態素情報:助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
===== Chunk
文節番号:2
係り先:5
主辞:0
機能辞:1
係り関係のスコア:-1.5244090557098389
----- Token
表層形:使っ
形態素情報:動詞,自立,*,*,五段・ワ行促音便,連用タ接続,使う,ツカッ,ツカッ
----- Token
表層形:て
形態素情報:助詞,接続助詞,*,*,*,*,て,テ,テ
===== Chunk
文節番号:3
係り先:5
主辞:0
機能辞:1
係り関係のスコア:-1.5244090557098389
----- Token
表層形:Python
形態素情報:名詞,一般,*,*,*,*,*
----- Token
表層形:で
形態素情報:助詞,格助詞,一般,*,*,*,で,デ,デ
===== Chunk
文節番号:4
係り先:5
主辞:1
機能辞:2
係り関係のスコア:-1.5244090557098389
----- Token
表層形:構文
形態素情報:名詞,一般,*,*,*,*,構文,コウブン,コーブン
----- Token
表層形:解析
形態素情報:名詞,サ変接続,*,*,*,*,解析,カイセキ,カイセキ
----- Token
表層形:を
形態素情報:助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
===== Chunk
文節番号:5
係り先:-1
主辞:1
機能辞:2
係り関係のスコア:0.0
----- Token
表層形:実装
形態素情報:名詞,サ変接続,*,*,*,*,実装,ジッソウ,ジッソー
----- Token
表層形:し
形態素情報:動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
----- Token
表層形:た
形態素情報:助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
----- Token
表層形:。
形態素情報:記号,句点,*,*,*,*,。,。,。

以降で各部分について内容を説明します。

解析結果内の各要素を扱うためには、解析結果のサイズ分だけforで処理を回します。ここで、sizeメソッドを使っていますが、これは形態素(token)の数になります。文節番号に該当する情報はなさそうなため、個別にchunk_idという変数で管理しています。

chunk_id = 0
for i in range(result_tree.size()):
    token = result_tree.token(i)

文節であるかどうかは、取り出したtokenにchunkがあるかどうかで確認します。各文節の最初のtokenにはchunkを持っており、それ以外の形態素ではNoneになっています。文節情報を含んでいるtokenからは以下のように各情報を取り出すことができます。

    # 文節の先頭の場合はchunkがNoneではない
    if token.chunk is not None:
        print('===== Chunk')
        print(f'文節番号:{chunk_id}')
        print(f'係り先:{token.chunk.link}')
        print(f'主辞:{token.chunk.head_pos}')
        print(f'機能辞:{token.chunk.func_pos}')
        print(f'係り関係のスコア:{token.chunk.score}')
        chunk_id += 1

上記のようにtoken.chunkのプロパティとして係り先(link)、主辞(head_pos)、機能辞(func_pos)、係り関係のスコア(score)を取得できます。

tokenは形態素情報のため以下の部分に示すように情報を持っています。

    print('----- Token')
    print(f'表層形:{token.surface}')
    print(f'形態素情報:{token.feature}')

文に現れるそのままの形である表層形はtoken.surfaceに、形態素情報はtoken.featureにカンマ(,)区切りの文字列として取得できます。形態素情報を個々に扱いたい場合は、token.feature.split(‘,’)のような形でリストに分割して扱うとよいでしょう。

上記のように各要素を取得して扱うことができます。

【参考】インストール時にはまってしまったこと

CaboCha.Parse()で原因不明の終了コードで終了

発生時の手順とエラー内容

私は最初インストールするときに、以下の流れで実施してうまくいかずにはまってしまったことがありますので、その時の内容を記載しておきます。

最初以下の手順でCaboChaを利用しようと進めました。

  1. CaboChaをインストール
  2. pip install python-cabochaを実行
  3. プログラム実行時にMeCabがインストールされていないことに気づく
  4. MeCabをインストール

手順3のところは、プログラム実行時に以下のようなエラーが出て、MeCabが使えていないということに気づきました。

morph.cpp(48) [g_mecab_handle != 0] LoadLibrary("libmecab.dll") failed

その後、上記でも説明したMeCabインストール手順でMeCabをインストールしたのですが、今度はCaboCha.Parser()のinitでなにも実行されず、プロセスが止まってしまうような事象が起きました。

プロセスは終了コード -1073741819 (0xC0000005) で終了しました

正直色々調べても何が原因かよく分かりませんでした。

【解決策】

上記問題は、MeCabとCaboChaを再インストールすることで解決しました。

やったことは簡単で一度Mecab、CaboChaをコントロールパネルの「プログラムのアンインストール」から削除します。その後、「MeCab」→「CaboCha」の順でインストールを実施しました。このように再インストールを実施しただけで、これまで出ていたエラーが発生することなく実行することができました。

正確なところの原因究明はできませんでしたが、どうやらCaboCha→MeCabの順でインストールしていたことで何かしら問題が発生してしまっていたのかと思います。

同じようなケースで必ずしも再インストールが解決策になるかは分かりませんが、もし私と同じようにCaboCha→MeCabとインストールしてうまくいかなかった人は、一回アンインストールして、MeCab→CaboChaの順で再インストールしたらうまくいくかもしれません。参考にしていただければと思います。

まとめ

PythonでCaboChaを使って構文解析を実行するための環境準備方法と簡単な実行例を紹介しました。

構文解析ができると文自体の構造が分かるようになるため、どういったイベントが発生したのかを文章から把握するといったことができるようになり面白いかと思います。まず、構文解析を試してみたいという場合は、今回ご紹介した例を参考に一度使って試してみてください。

Note

CaboChaの公式ページはこちらを参考にしてください。
MeCabの公式ページはこちらを参考にしてください。

PythonでのCaboChaの使い方に関する公式なドキュメントがあればよいと思うのですが、公式なドキュメントは私が調べた限りではなさそうでした。本記事は、元となるCプログラムの構成やその他のWebページ情報などから使い方を整理していますので、一部誤りが含まれる可能性がある点はご注意ください。