• 追加された行はこの色です。
  • 削除された行はこの色です。
#title(MeCabのラッパークラスを使用して形態素解析を行う)

#navi(.NETプログラミング研究)

#contents

*MeCabのラッパークラスを使用して形態素解析を行う [#y31a0c13]

前回は分かち書きの方法を紹介しましたが、今回は形態素解析を行う方法について調べてみました。

前回の繰り返しになりますが、形態素解析を行う方法として、私には次の2つしか見つけることができませんでした。

+形態素解析ツールをインストールして使う
+Webサービスを使う

形態素解析ツールには、[[KAKASHI>http://kakasi.namazu.org/]]、[[ChaSen(茶筌)>http://chasen-legacy.sourceforge.jp/]]、[[MeCab(和布蕪)>http://mecab.sourceforge.net/]]などがあります。この内MeCabについては、その機能を簡単に呼び出すことができるラッパークラスがいくつか公開されています。

Webサービスで形態素解析を行うというのは、具体的には、Yahoo! Japanの[[日本語形態素解析Webサービス>http://developer.yahoo.co.jp/webapi/jlp/ma/v1/parse.html]]を使用するということです。

今回は、MeCabのラッパークラスを実際に試してみます。

**MeCabをインストールする [#x5a99627]

まずはMeCabをインストールして使ってみましょう。「[[Browse MeCab Files on SourceForge.net>http://sourceforge.net/projects/mecab/files/]]」でダウンロードできるパッケージにはいくつかありますが、拡張子が .exe の「Binary package for MS-Windows」をダウンロードしました。ちなみに私がインストールしたバージョンは、0.98です。

このパッケージを実行すると、MeCabをインストールすることができます。インストール時に「辞書の文字コードの選択」画面が出ますが、ここでShift-JISを選択しないとラッパークラスを使用したときにうまくいかないことがあるようです。

#embed(<a href="http://www.flickr.com/photos/dobondotnet/5233378181/" title="mecab6 by DOBON.NET, on Flickr"><img src="http://farm6.static.flickr.com/5042/5233378181_d4e39d4581.jpg" width="500" height="310" alt="mecab6" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/5233378181/" title="mecab6 by DOBON.NET, on Flickr"><img src="https://farm6.static.flickr.com/5042/5233378181_d4e39d4581.jpg" width="500" height="310" alt="mecab6" /></a>)

早速MeCabを起動してみましょう。すると、DOS窓が表示されます。

#embed(<a href="http://www.flickr.com/photos/dobondotnet/5166829969/" title="mecab1 by DOBON.NET, on Flickr"><img src="http://farm5.static.flickr.com/4027/5166829969_744539eb1c.jpg" width="500" height="363" alt="mecab1" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/5166829969/" title="mecab1 by DOBON.NET, on Flickr"><img src="https://farm5.static.flickr.com/4027/5166829969_744539eb1c.jpg" width="500" height="363" alt="mecab1" /></a>)

ここに日本語の文章を打ち込み、エンターキーを押すと、形態素解析が行われ、結果が表示されます。例えば、「今日はいい天気です。」と打ち込むと、次のような結果が出力されます。

#pre{{
今日    名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
いい    形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
天気    名詞,一般,*,*,*,*,天気,テンキ,テンキ
です    助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。      記号,句点,*,*,*,*,。,。,。
EOS
}}

#embed(<a href="http://www.flickr.com/photos/dobondotnet/5167429916/" title="mecab2 by DOBON.NET, on Flickr"><img src="http://farm2.static.flickr.com/1213/5167429916_6633c0b616.jpg" width="500" height="363" alt="mecab2" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/5167429916/" title="mecab2 by DOBON.NET, on Flickr"><img src="https://farm2.static.flickr.com/1213/5167429916_6633c0b616.jpg" width="500" height="363" alt="mecab2" /></a>)

この出力フォーマットは、以下のとおりです。

#pre{{
表層形\t品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音
}}

もし、単語と単語の間にスペースを挿入した文字列(わかち書き)を出力して欲しい場合は、「-O wakat」オプションをつけてMeCabを起動します。「-O wakat」オプションをつけてMeCabを起動し、前と同じ文章を打ち込んだときは、次のように出力されます。

#pre{{
今日 は いい 天気 です 。
}}

#embed(<a href="http://www.flickr.com/photos/dobondotnet/5166830027/" title="mecab3 by DOBON.NET, on Flickr"><img src="http://farm2.static.flickr.com/1408/5166830027_cc2d3f7df5.jpg" width="500" height="363" alt="mecab3" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/5166830027/" title="mecab3 by DOBON.NET, on Flickr"><img src="https://farm2.static.flickr.com/1408/5166830027_cc2d3f7df5.jpg" width="500" height="363" alt="mecab3" /></a>)

もし読みだけを出力して欲しいのであれば、「-Oyomi」オプションを付けます。「-Oyomi」オプションを付けたときは、次のように出力されます。

#pre{{
キョウハイイテンキデス。
}}

#embed(<a href="http://www.flickr.com/photos/dobondotnet/5167429972/" title="mecab4 by DOBON.NET, on Flickr"><img src="http://farm5.static.flickr.com/4111/5167429972_93a3191488.jpg" width="500" height="363" alt="mecab4" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/5167429972/" title="mecab4 by DOBON.NET, on Flickr"><img src="https://farm5.static.flickr.com/4111/5167429972_93a3191488.jpg" width="500" height="363" alt="mecab4" /></a>)

複数の候補を出力して欲しいのであれば、「-N#NUM」オプションを付けます(N-Best解)。候補は確からしいものから順番に出力されます。例えば3個の候補を出力するには、「-N3」というオプションを付けます。「-N3」オプションを付けたときは、次のように出力されます。

#pre{{
今日    名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
いい    形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
天気    名詞,一般,*,*,*,*,天気,テンキ,テンキ
です    助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。      記号,句点,*,*,*,*,。,。,。
EOS
今日    名詞,副詞可能,*,*,*,*,今日,コンニチ,コンニチ
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
いい    形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
天気    名詞,一般,*,*,*,*,天気,テンキ,テンキ
です    助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。      記号,句点,*,*,*,*,。,。,。
EOS
今日    名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
いい    動詞,自立,*,*,五段・ワ行促音便,連用形,いう,イイ,イイ
天気    名詞,一般,*,*,*,*,天気,テンキ,テンキ
です    助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。      記号,句点,*,*,*,*,。,。,。
EOS
}}

#embed(<a href="http://www.flickr.com/photos/dobondotnet/5171523644/" title="mecab5 by DOBON.NET, on Flickr"><img src="http://farm5.static.flickr.com/4092/5171523644_e160eb1196.jpg" width="500" height="363" alt="mecab5" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/5171523644/" title="mecab5 by DOBON.NET, on Flickr"><img src="https://farm5.static.flickr.com/4092/5171523644_e160eb1196.jpg" width="500" height="363" alt="mecab5" /></a>)

MeCabの説明は、以上としておきます。より詳しくは、MeCabに付属しているドキュメントをご覧ください。

**MeCabのラッパークラスを使用する [#idf8efa1]

私が調べた限りでは、現在公開されているMaCabのラッパークラスには以下のようなものがありました。

-[[MeCabSharp - Meteor Factory>http://mf3.dotpp.net/?Software%2FMeCabSharp]](v1.2, for MeCab 0.97)
-[[MeCab.NET プロジェクト日本語トップページ - SourceForge.JP>http://sourceforge.jp/projects/mecabdotnet/]](バージョン 0.0.0.3)
-[[mecab/cabocha用C#ラッパーライブラリ mutterofstar : Vector>http://www.vector.co.jp/soft/winnt/prog/se446647.html]](バージョン 0.1)

この内、MeCabSharpとMeCab.NETは、私の環境(Windows 7 32bit、Visual Studio 2010、.NET Framework 4.0)では、そのままでは正常に動作しませんでした(詳細は、後述します)。そこでまずはmutterofstarを使ってみます。

**mutterofstarを使用する [#b9314e3e]

mutterofstarは[[CaboCha>http://chasen.org/~taku/software/cabocha/]]を使った係り受け解析もできますが、ここではMeCabのみを使います。

***準備 [#o07b3dc9]

mutterofstarは現在[[Vector>http://www.vector.co.jp/soft/winnt/prog/se446647.html]]でしかダウンロードできません。残念ながら、作者様のサイトは消滅しているようです。

mutterofstarをダウンロード後、このライブラリを使用できるようにするには、以下のような準備が必要です。

+mutterofstarを使用したいプロジェクトをVisual Studioで開きます。
+mutterofstarのパッケージに含まれているmutterofstar.dllをプロジェクトの参照設定に追加します。詳しくは、「[[「○○○.dllを参照に追加します」の意味は?>http://dobon.net/vb/dotnet/help/addreference.html]]」をご覧ください。
+mutterofstarのパッケージに含まれているmutterofstar.dllをプロジェクトの参照設定に追加します。詳しくは、「[[「○○○.dllを参照に追加します」の意味は?>https://dobon.net/vb/dotnet/help/addreference.html]]」をご覧ください。
+MeCabをインストールしたフォルダのbinフォルダ内にあるlibmecab.dllを、プロジェクトのアセンブリの出力パスにコピーします。ここでは自動的に出力パスにコピーされるように、まずlibmecab.dllをプロジェクトに追加し(ファイルをドラッグして、Visual Studioのソリューションエクスプローラーのプロジェクトの位置にドロップする)、このファイルの「出力ディレクトリにコピー」プロパティを「新しい場合はコピーする」または「常にコピーする」にします。

***簡単な使い方 [#k901581a]

これで準備は整いました。早速コードを書いてみましょう。CMecabクラスのAnalyzeメソッドを呼び出すことで形態素解析が行われます。

#code(vbnet){{
'形態素解析する文章
Dim text As String = "今日はいい天気です。"

'CMecabオブジェクトの作成
Dim mecab As New mutterofstar.NLP.CMecab()
'150文字以上の文章を解析するときは、MaxLengthプロパティを変更する
'mecab.MaxLength = 1000
'解析する
If mecab.Analyze(text) Then
    '成功したときは、結果を表示する
    Console.WriteLine(mecab.ResultString)
Else
    '失敗したときは、エラーメッセージを表示する
    Console.WriteLine("エラー:" + mecab.Error)
End If

mecab.Dispose()
}}

#code(csharp){{
//形態素解析する文章
string text = "今日はいい天気です。";

//CMecabオブジェクトの作成
mutterofstar.NLP.CMecab mecab = new mutterofstar.NLP.CMecab();
//150文字以上の文章を解析するときは、MaxLengthプロパティを変更する
//mecab.MaxLength = 1000;
//解析する
if (mecab.Analyze(text))
{
    //成功したときは、結果を表示する
    Console.WriteLine(mecab.ResultString);
}
else
{
    //失敗したときは、エラーメッセージを表示する
    Console.WriteLine("エラー:" + mecab.Error);
}

mecab.Dispose();
}}

このコードを実行したときに出力される結果は、MeCabをパラメータなしで起動し、文章を打ち込んだ時に出力される結果と同じです。(ただし、改行文字は"\r\n"になるようです。)

もしパラメータを指定してMeCabを起動したときの結果を取得したいのであれば、CMecabインストラクタのパラメータにそのパラメータを渡してインスタンスを作成します。

例えば、読みを解析したいのであれば、次のように"-Oyomi"を渡します。

#code(vbnet){{
Dim text As String = "今日はいい天気です。"

'読みを解析する
Dim mecab As New mutterofstar.NLP.CMecab("-Oyomi")
If mecab.Analyze(text) Then
    Console.WriteLine(mecab.ResultString)
Else
    Console.WriteLine("エラー:" + mecab.Error)
End If

mecab.Dispose()
}}

#code(csharp){{
string text = "今日はいい天気です。";

//読みを解析する
mutterofstar.NLP.CMecab mecab = new mutterofstar.NLP.CMecab("-Oyomi");
if (mecab.Analyze(text))
{
    Console.WriteLine(mecab.ResultString);
}
else
{
    Console.WriteLine("エラー:" + mecab.Error);
}

mecab.Dispose();
}}

***出力結果を自動的に解析する [#xd0d6870]

mutterofstarの独特の機能として、MeCabの出力の結果を解析し、CSentence型に変換するものがあります。CSentenceクラスのWordListプロパティは、形態素を表すCWord型のリストです。この機能を使って、文章がどのような形態素に分けられたかを簡単に知ることができます。

CMecabクラスのAnalyzeメソッドを呼び出すときに、自動的に結果がCSentence型に変換されるようにするには、EnabledResultAnalyzeプロパティをTrueにします。すると、Analyzeメソッドを呼び出したあと、ResultプロパティにCSentenceに変換された結果が入ります。ただし、CMecabのインスタンスを作成するとき、コンストラクタにパラメータを指定することはできません。

次の例では、この方法を使って、解析結果の形態素を列挙しています。

#code(vbnet){{
Dim text As String = "今日はいい天気ですね。"
Dim mecab As New mutterofstar.NLP.CMecab()
'結果を自動的に解析する
mecab.EnabledResultAnalyze = True
If mecab.Analyze(text) Then
    For Each w As mutterofstar.NLP.CWord In mecab.Result.WordList
        Console.WriteLine("基本形:{0}", w.Basis)
        Console.WriteLine("活用形:{0}", w.InflectedForms)
        Console.WriteLine("活用型:{0}", w.InflectedType)
        Console.WriteLine("品詞-表記:{0}", w.Pos_String)
        Console.WriteLine(" 品詞:{0}", w.Pos(0))
        Console.WriteLine(" 品詞細分類1:{0}", w.Pos(1))
        Console.WriteLine(" 品詞細分類2:{0}", w.Pos(2))
        Console.WriteLine(" 品詞細分類3:{0}", w.Pos(3))
        Console.WriteLine("発音:{0}", w.Pronunciation)
        Console.WriteLine("読み:{0}", w.Read)
        Console.WriteLine("未知語か:{0}", w.Unknown)
        Console.WriteLine("表記:{0}", w.Word)

        Console.WriteLine("----------------------")
    Next
End If

mecab.Dispose()
}}

#code(csharp){{
string text = "今日はいい天気ですね。";
mutterofstar.NLP.CMecab mecab = new mutterofstar.NLP.CMecab();
//結果を自動的に解析する
mecab.EnabledResultAnalyze = true;
if (mecab.Analyze(text))
{
    foreach (mutterofstar.NLP.CWord w in mecab.Result.WordList)
    {
        Console.WriteLine("基本形:{0}", w.Basis);
        Console.WriteLine("活用形:{0}", w.InflectedForms);
        Console.WriteLine("活用型:{0}", w.InflectedType);
        Console.WriteLine("品詞-表記:{0}", w.Pos_String);
        Console.WriteLine(" 品詞:{0}", w.Pos[0]);
        Console.WriteLine(" 品詞細分類1:{0}", w.Pos[1]);
        Console.WriteLine(" 品詞細分類2:{0}", w.Pos[2]);
        Console.WriteLine(" 品詞細分類3:{0}", w.Pos[3]);
        Console.WriteLine("発音:{0}", w.Pronunciation);
        Console.WriteLine("読み:{0}", w.Read);
        Console.WriteLine("未知語か:{0}", w.Unknown);
        Console.WriteLine("表記:{0}", w.Word);

        Console.WriteLine("----------------------");
    }
}

mecab.Dispose();
}}

mutterofstarの説明は以上です。もっと知りたいという方は、mutterofstarのパッケージにドキュメントが付いていますので、そちらが参考になるかと思います。

**MeCab.NETを使用する [#i3bf59e4]

MeCab.NETは現在[[SourceForge.JP>http://sourceforge.jp/projects/mecabdotnet/]]でサンプル付きのパッケージをダウンロードできます。

前述したとおり、MeCab.NETはそのままでは使用できませんでした。まずパッケージに含まれているDLLは、どうやらMeCabがデフォルトのディレクトリ(C:\Program Files\MeCab)にインストールされていることが前提となっているようで、それ以外では使えないようでした。

パッケージに含まれているライブラリのソースではその点は変更されており、libmecab.dllはパスの通った場所にあれば大丈夫です。つまりmutterofstarの時と同じように、libmecab.dllをアセンブリの出力パスにコピーすればOKです。

しかしそれでも、私の環境では、サンプルで形態素解析を行おうとしても、System.AccessViolationExceptionという例外がスローされました。

#embed(<a href="http://www.flickr.com/photos/dobondotnet/5178441269/" title="mecabdotnet1 by DOBON.NET, on Flickr"><img src="http://farm2.static.flickr.com/1368/5178441269_de8d9132ba.jpg" width="452" height="263" alt="mecabdotnet1" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/5178441269/" title="mecabdotnet1 by DOBON.NET, on Flickr"><img src="https://farm2.static.flickr.com/1368/5178441269_de8d9132ba.jpg" width="452" height="263" alt="mecabdotnet1" /></a>)

ネットで検索してみると、この問題について、「[[C#でMecabをVista上でも動かす>http://d.hatena.ne.jp/kiichi55/20090429/1241021253]]」で解決法が紹介されています。これによると、この問題はWindows Vista以降で発生するようです。

この解決法によりコードを修正するには、_Mecabクラスの

#code(csharp){{
[DllImport("libmecab")]
private static extern string mecab_sparse_tostr(IntPtr ptrMecab, string str);
protected string _mecab_sparse_tostr(string str)
{
    return mecab_sparse_tostr(this.ptrMecab, str);
}
}}

の部分を

#code(csharp){{
[DllImport("libmecab")]
private static extern IntPtr mecab_sparse_tostr(IntPtr ptrMecab, string str);
protected string _mecab_sparse_tostr(string str)
{
    IntPtr s = mecab_sparse_tostr(this.ptrMecab, str);
    return Marshal.PtrToStringAnsi(s);
}
}}

のように書き換えます。これでVista以降でもエラーを出さずにサンプルを実行出来るようになります。

#embed(<a href="http://www.flickr.com/photos/dobondotnet/5179046700/" title="mecabdotnet2 by DOBON.NET, on Flickr"><img src="http://farm5.static.flickr.com/4153/5179046700_aa381a22b0.jpg" width="500" height="321" alt="mecabdotnet2" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/5179046700/" title="mecabdotnet2 by DOBON.NET, on Flickr"><img src="https://farm5.static.flickr.com/4153/5179046700_aa381a22b0.jpg" width="500" height="321" alt="mecabdotnet2" /></a>)

他のメソッドも同様の問題が生じると思いますので、他のメソッドも使うのであれば、同じように修正してください。

補足:上記のような修正をしても、MeCab.NETの「対象のフレームワーク」を.NET Framework 4.0にすると、「PInvokeStackImbalance が検出されました。」というMDAメッセージが表示されます。

***簡単な使い方 [#v712becb]

MeCab.NETを使用した簡単な例を示します。なおmutterofstarと違い、結果の文字列の改行文字は"\r\n"ではなく、"\n"です。

#code(vbnet){{
'形態素解析する文章
Dim text As String = "今日はいい天気です。"

'Mecabオブジェクトの作成
Dim mecab As New MecabDotNet.Mecab()
'解析する
Dim result As String = mecab.mecab_sparse_tostr(text)
'結果を表示する
Console.WriteLine(result)

mecab.Dispose()
}}

#code(csharp){{
//形態素解析する文章
string text = "今日はいい天気です。";

//Mecabオブジェクトの作成
MecabDotNet.Mecab mecab = new MecabDotNet.Mecab();
//解析する
string result = mecab.mecab_sparse_tostr(text);
//結果を表示する
Console.WriteLine(result);

mecab.Dispose();
}}

**MeCabSharpを使用する [#p8f45551]

[[MeCabSharp>http://mf3.dotpp.net/?Software%2FMeCabSharp]]は、[[SWIG>http://www.swig.org/]]を使用して自動的に出力されたC#用のバインディングを基にしたライブラリのようです。ライセンスは、MeCabと同じ、GPL、LGPL、BSDのトリプルライセンスということです。

MeCabSharpを使うには、mutterofstarの時と同じような準備が必要です。MeCabSharp.dllをプロジェクトの参照設定に追加し、libmecab.dllをプロジェクトのアセンブリの出力パスにコピーします。MeCabSharpではさらに、MeCabSharpのパッケージに入っているMeCab.dllもアセンブリの出力パスにコピーします。

***コンパイルする [#c06fb32f]

実際にMeCabSharpを使ってみたところ、Visual Studioから実行するときは普通に実行出来たのですが、ビルドして出力されるアセンブリを実行すると、例外System.AccessViolationExceptionがスローされました。そこでMeCabSharpのサイトで紹介されているコンパイルの方法を参考に自分でコンパイルしてみたところ、例外がでなくなりました。

私が行ったコンパイルの手順は以下のとおりです。

+[[Download SWIG>http://www.swig.org/download.html]]から、Windows用にすでにコンパイルされた実行ファイルが含まれるSWIGをダウンロードし(「Windows users should download ...」)、適当なフォルダに展開します(「C:\swigwin」に展開したものとします)。
+[[MeCabのダウンロードページ>http://sourceforge.net/projects/mecab/files/]]からソース(mecab-0.98.tar.gz)をダウンロードし、適当なフォルダに展開します(「C:\mecab-0.98」に展開したものとします)。
+そのフォルダ内にできるswigフォルダ(C:\mecab-0.98\swig)の中に、MeCabSharpのパッケージにあるmake.batファイルをコピーします。
+make.batの上の部分を自分の環境に合わせてテキストエディタで書き換えます。具体的には、次のような感じになります。ここではMeCabは"C:\Program Files\MeCab"にインストールしたものとしています。
#pre{{
@echo off
set swig="C:\swigwin\swig.exe"
set prefix=MeCab
set sdk=C:\Program Files\MeCab\sdk
set compiler=cl
set csc=csc
set path=%sdk%;%path%
}}
+コマンドプロンプトを起動し、make.batのあるフォルダ(C:\mecab-0.98\swig)に移動します(「cd "C:\mecab-0.98\swig"」を実行)。
+vsvars32.batを実行します(「C:\Program Files\Microsoft Visual Studio 10.0\Common7\Tools」のようなフォルダ((環境変数"VS100COMNTOOLS"に設定されている))内で見つかります)。
+コマンドプロンプトで「make mecabcxx」を実行します。すると、「C:\mecab-0.98\swig」に9つのファイル(DictionaryInfo.cs、MeCab.cs、MeCabPINVOKE.cs、MeCab_wrap.cxx、Node.cs、Path.cs、SWIGTYPE_p_p_char.cs、Tagger.cs、Token.cs)が作成されます。((make.batではswigを実行したときの出力を表示しないようにしていますが、これを表示するようにすると、Warningが幾つか出ているのが分かります。))
+コマンドプロンプトに表示される指示に従って、MeCab_wrap.cxxをテキストエディタで開き、「Tagger::create」を「createTagger」に、「MeCab::Tagger::version」を「mecab_version」に置換します。
+コマンドプロンプトで「make mecabdll」を実行します。すると、「C:\mecab-0.98\swig」に4つのファイル(MeCab_wrap.obj、MeCab.lib、MeCab.exp、MeCab.dll)が作成されます。
+コマンドプロンプトで「make mecabcsharp」を実行します。すると、「C:\mecab-0.98\swig」にMeCabSharp.dllが作成されます。
+以上で、「C:\mecab-0.98\swig」に「MeCab.dll」と「MeCabSharp.dll」が作成されているはずです。

#embed(<a href="http://www.flickr.com/photos/dobondotnet/5182241776/" title="mecabsharp1 by DOBON.NET, on Flickr"><img src="http://farm2.static.flickr.com/1412/5182241776_8774a2cbcc.jpg" width="500" height="402" alt="mecabsharp1" /></a>)
#embed(<a href="https://www.flickr.com/photos/dobondotnet/5182241776/" title="mecabsharp1 by DOBON.NET, on Flickr"><img src="https://farm2.static.flickr.com/1412/5182241776_8774a2cbcc.jpg" width="500" height="402" alt="mecabsharp1" /></a>)

***簡単な使い方 [#ha94c3a5]

このように作成されたライブラリの使い方は、MeCabのサイトにある「[[スクリプト言語のバインディング>http://mecab.sourceforge.net/bindings.html]]」が参考になります。ただし、C#に関する記述は一切ありません。

文章を解析し、結果を文字列として取得するには、Tagger.parseメソッド(または、parseToStringメソッドでも同じ)を使います。文章を解析する簡単な例を以下に示します。

#code(vbnet){{
'形態素解析する文章
Dim text As String = "今日はいい天気です。"

'Taggerオブジェクトの作成
Dim mecab As New MeCab.Tagger()
'解析する
Dim result As String = mecab.parse(text)
'結果を表示
Console.WriteLine(result)
'後始末
mecab.Dispose()
}}

#code(csharp){{
//形態素解析する文章
string text = "今日はいい天気です。";

//Taggerオブジェクトの作成
MeCab.Tagger mecab = new MeCab.Tagger();
//解析する
string result = mecab.parse(text);
//結果を表示
Console.WriteLine(result);
//後始末
mecab.Dispose();
}}

上の例では、MeCabをパラメータなしで実行した時と同じ結果を出力します(改行文字は"\n")。MeCabをパラメータを指定して実行した時と同じ結果が欲しいのであれば、Taggerのコンストラクタのパラメータにその値を指定してTaggerオブジェクトを作成します。

以下の例では、分かち書きを取得しています。

#code(vbnet){{
Dim text As String = "今日はいい天気です。"

'分かち書きを取得する
Dim mecab As New MeCab.Tagger("-O wakati")
Dim result As String = mecab.parse(text)
Console.WriteLine(result)
mecab.Dispose()
}}

#code(csharp){{
string text = "今日はいい天気です。";

//分かち書きを取得する
MeCab.Tagger mecab = new MeCab.Tagger("-O wakati");
string result = mecab.parse(text);
Console.WriteLine(result);
mecab.Dispose();
}}

***形態素を順番に取得する [#sb4b469b]

Tagger.parseToNodeメソッドを使って解析すると、Nodeオブジェクトとして、形態素の情報を取得することができます。また、Node.nextメソッドにより、次の形態素の情報を取得できます。

Nodeクラスの各プロパティの意味については、「[[スクリプト言語のバインディング>http://mecab.sourceforge.net/bindings.html]]」をご覧ください。

以下に、parseToNodeメソッドを使って、形態素の情報を順番に表示する例を示します。

#code(vbnet){{
'形態素解析する文章
Dim text As String = "今日はいい天気です。"

'Taggerオブジェクトの作成
Dim mecab As New MeCab.Tagger()
'形態素をNodeオブジェクトで取得
Dim node As MeCab.Node = mecab.parseToNode(text)
While node IsNot Nothing
    Console.WriteLine("形態素の文字列情報:{0}", node.surface)

    Console.WriteLine("CSVで表記された素性情報:{0}", node.feature)
    Dim fs As String() = node.feature.Split(","c)
    Console.WriteLine(" 品詞:{0}", fs(0))
    Console.WriteLine(" 品詞細分類1:{0}", fs(1))
    Console.WriteLine(" 品詞細分類2:{0}", fs(2))
    Console.WriteLine(" 品詞細分類3:{0}", fs(3))
    Console.WriteLine(" 活用形:{0}", fs(4))
    Console.WriteLine(" 活用型:{0}", fs(5))
    Console.WriteLine(" 原型:{0}", fs(6))
    If fs.Length > 7 Then
        Console.WriteLine(" 読み:{0}", fs(7))
        Console.WriteLine(" 発音:{0}", fs(8))
    End If
    Select Case node.stat
        Case 0
            Console.WriteLine("形態素種類:通常")
            Exit Select
        Case 1
            Console.WriteLine("形態素種類:未知語")
            Exit Select
        Case 2
            Console.WriteLine("形態素種類:文頭")
            Exit Select
        Case 3
            Console.WriteLine("形態素種類:文末")
            Exit Select
    End Select

    Console.WriteLine("累積コスト:{0}", node.cost)
    Console.WriteLine("------------------------")

    '次の形態素を取得
    node = node.[next]
End While

mecab.Dispose()
}}

#code(csharp){{
//形態素解析する文章
string text = "今日はいい天気です。";

//Taggerオブジェクトの作成
MeCab.Tagger mecab = new MeCab.Tagger();
//形態素をNodeオブジェクトで取得
MeCab.Node node = mecab.parseToNode(text);
while (node != null)
{
    Console.WriteLine("形態素の文字列情報:{0}", node.surface);

    Console.WriteLine("CSVで表記された素性情報:{0}", node.feature);
    string[] fs = node.feature.Split(',');
    Console.WriteLine(" 品詞:{0}", fs[0]);
    Console.WriteLine(" 品詞細分類1:{0}", fs[1]);
    Console.WriteLine(" 品詞細分類2:{0}", fs[2]);
    Console.WriteLine(" 品詞細分類3:{0}", fs[3]);
    Console.WriteLine(" 活用形:{0}", fs[4]);
    Console.WriteLine(" 活用型:{0}", fs[5]);
    Console.WriteLine(" 原型:{0}", fs[6]);
    if (fs.Length > 7)
    {
        Console.WriteLine(" 読み:{0}", fs[7]);
        Console.WriteLine(" 発音:{0}", fs[8]);
    }
    switch (node.stat)
    {
        case 0:
            Console.WriteLine("形態素種類:通常");
           break;
        case 1:
            Console.WriteLine("形態素種類:未知語");
            break;
        case 2:
            Console.WriteLine("形態素種類:文頭");
            break;
        case 3:
            Console.WriteLine("形態素種類:文末");
            break;
    }

    Console.WriteLine("累積コスト:{0}", node.cost);
    Console.WriteLine("------------------------");

    //次の形態素を取得
    node = node.next;
}

mecab.Dispose();
}}

上のコードを実行すると、次のように出力されます。

#pre{{
形態素の文字列情報:
CSVで表記された素性情報:BOS/EOS,*,*,*,*,*,*,*,*
 品詞:BOS/EOS
 品詞細分類1:*
 品詞細分類2:*
 品詞細分類3:*
 活用形:*
 活用型:*
 原型:*
 読み:*
 発音:*
形態素種類:文頭
累積コスト:0
------------------------
形態素の文字列情報:今日
CSVで表記された素性情報:名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
 品詞:名詞
 品詞細分類1:副詞可能
 品詞細分類2:*
 品詞細分類3:*
 活用形:*
 活用型:*
 原型:今日
 読み:キョウ
 発音:キョー
形態素種類:通常
累積コスト:3947
------------------------
形態素の文字列情報:は
CSVで表記された素性情報:助詞,係助詞,*,*,*,*,は,ハ,ワ
 品詞:助詞
 品詞細分類1:係助詞
 品詞細分類2:*
 品詞細分類3:*
 活用形:*
 活用型:*
 原型:は
 読み:ハ
 発音:ワ
形態素種類:通常
累積コスト:4822
------------------------
形態素の文字列情報:いい
CSVで表記された素性情報:形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
 品詞:形容詞
 品詞細分類1:自立
 品詞細分類2:*
 品詞細分類3:*
 活用形:形容詞・イイ
 活用型:基本形
 原型:いい
 読み:イイ
 発音:イイ
形態素種類:通常
累積コスト:7936
------------------------
形態素の文字列情報:天気
CSVで表記された素性情報:名詞,一般,*,*,*,*,天気,テンキ,テンキ
 品詞:名詞
 品詞細分類1:一般
 品詞細分類2:*
 品詞細分類3:*
 活用形:*
 活用型:*
 原型:天気
 読み:テンキ
 発音:テンキ
形態素種類:通常
累積コスト:10214
------------------------
形態素の文字列情報:です
CSVで表記された素性情報:助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
 品詞:助動詞
 品詞細分類1:*
 品詞細分類2:*
 品詞細分類3:*
 活用形:特殊・デス
 活用型:基本形
 原型:です
 読み:デス
 発音:デス
形態素種類:通常
累積コスト:11527
------------------------
形態素の文字列情報:。
CSVで表記された素性情報:記号,句点,*,*,*,*,。,。,。
 品詞:記号
 品詞細分類1:句点
 品詞細分類2:*
 品詞細分類3:*
 活用形:*
 活用型:*
 原型:。
 読み:。
 発音:。
形態素種類:通常
累積コスト:8137
------------------------
形態素の文字列情報:
CSVで表記された素性情報:BOS/EOS,*,*,*,*,*,*,*,*
 品詞:BOS/EOS
 品詞細分類1:*
 品詞細分類2:*
 品詞細分類3:*
 活用形:*
 活用型:*
 原型:*
 読み:*
 発音:*
形態素種類:文末
累積コスト:6601
------------------------
}}

このように、はじめに「文頭」という形態素が、そして最後に「文末」という特別な形態素が返されることに注意が必要です。

***複数の候補を取得する(N-Best解を取得する) [#a77f8ca3]

MeCabを"-N#NUM"パラメータを指定して実行した時のように、複数の候補を取得するには、parseNBestメソッドを使用します。

以下の例では、MeCabに「-N3」というパラメータを指定して実行した時と同じ結果を表示しています。

#code(vbnet){{
'形態素解析する文章
Dim text As String = "今日はいい天気です。"

'"-l 1"オプションを指定してTaggerオブジェクトを作成
Dim mecab As New MeCab.Tagger("-l 1")
'"-N3"と同じ結果を取得する
Console.WriteLine(mecab.parseNBest(3, text))

mecab.Dispose()
}}

#code(csharp){{
//形態素解析する文章
string text = "今日はいい天気です。";

//"-l 1"オプションを指定してTaggerオブジェクトを作成
MeCab.Tagger mecab = new MeCab.Tagger("-l 1");
//"-N3"と同じ結果を取得する
Console.WriteLine(mecab.parseNBest(3, text));

mecab.Dispose();
}}

結果は、以下のようになります。

#pre{{
今日    名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
いい    形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
天気    名詞,一般,*,*,*,*,天気,テンキ,テンキ
です    助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。      記号,句点,*,*,*,*,。,。,。
EOS
今日    名詞,副詞可能,*,*,*,*,今日,コンニチ,コンニチ
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
いい    形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
天気    名詞,一般,*,*,*,*,天気,テンキ,テンキ
です    助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。      記号,句点,*,*,*,*,。,。,。
EOS
今日    名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
いい    動詞,自立,*,*,五段・ワ行促音便,連用形,いう,イイ,イイ
天気    名詞,一般,*,*,*,*,天気,テンキ,テンキ
です    助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。      記号,句点,*,*,*,*,。,。,。
EOS
}}

または、parseNBestInitメソッドを呼び出すことにより、nextメソッドを使って解析結果を確からしいものから順番に取得することもできます。

下の例では、確からしいものから順番に結果を3つ取得しています。

#code(vbnet){{
'形態素解析する文章
Dim text As String = "今日はいい天気です。"

'"-l 1"オプションを指定してTaggerオブジェクトを作成
Dim mecab As New MeCab.Tagger("-l 1")
'確からしいものから順番に解析結果を得るための初期化をする
If mecab.parseNBestInit(text) Then
    '確からしいものから順番に3つ取得する
    For i As Integer = 0 To 2
        Console.WriteLine(mecab.[next]())
        Console.WriteLine("----------------")
    Next
End If

mecab.Dispose()
}}

#code(csharp){{
//形態素解析する文章
string text = "今日はいい天気です。";

//"-l 1"オプションを指定してTaggerオブジェクトを作成
MeCab.Tagger mecab = new MeCab.Tagger("-l 1");
//確からしいものから順番に解析結果を得るための初期化をする
if (mecab.parseNBestInit(text))
{
    //確からしいものから順番に3つ取得する
    for (int i = 0; i < 3; i++)
    {
        Console.WriteLine(mecab.next());
        Console.WriteLine("----------------");
    }
}

mecab.Dispose();
}}

結果は、以下のようになります。

#pre{{
今日    名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
いい    形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
天気    名詞,一般,*,*,*,*,天気,テンキ,テンキ
です    助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。      記号,句点,*,*,*,*,。,。,。
EOS

----------------
今日    名詞,副詞可能,*,*,*,*,今日,コンニチ,コンニチ
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
いい    形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
天気    名詞,一般,*,*,*,*,天気,テンキ,テンキ
です    助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。      記号,句点,*,*,*,*,。,。,。
EOS

----------------
今日    名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は      助詞,係助詞,*,*,*,*,は,ハ,ワ
いい    動詞,自立,*,*,五段・ワ行促音便,連用形,いう,イイ,イイ
天気    名詞,一般,*,*,*,*,天気,テンキ,テンキ
です    助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。      記号,句点,*,*,*,*,。,。,。
EOS

----------------
}}

***エラー処理 [#jd0131a4]

MeCab.Taggerのコンストラクタや、解析でエラーが発生したときは、ApplicationExceptionがスローされるようです。

**次回予告 [#j7365965]

今回は以上です。ここで紹介した以外に良い方法(あるいは良いライブラリ)をご存じの方は、ぜひお知らせください。

次回は、Yahoo! Japanの日本語形態素解析Webサービスを使ってみようかなと考えています。

**コメント [#y3456878]
- mutterofstarの作者です.ふと思い出して検索してみたら,ここの記事が引っ掛かりました.まさか,DOBON!さんに紹介してもらえているとは驚きました. -- ほしつぶ &new{2011-02-08 (火) 14:50:01};
- 作者様ご自身からコメントをいただき、とてもうれしいです。勝手に紹介してしまい、申し訳ありませんでした。mutterofstarはVectorで公開されているのはVer.0.1ですが、Webで検索したところ、後続のnekkoというものが公開されていたと知りました。もし可能でしたら、サイトの復活と、最新バージョンの再公開をぜひお願いしたいです。わがままを言って済みません。 -- [[どぼん!]] &new{2011-02-09 (水) 03:59:23};
- mutterofstarは,ホスティング先の都合で公開サイトがつぶれて,放置していました.確かにnekkoという後継もありましたが,現在はさらにその後継があります.手軽さはそのままに,仕様変更をけっこう行いまして,資料を準備後,1〜2か月以内に公開予定です.その際は,ここでまた,報告させて頂きます. -- ほしつぶ &new{2011-02-09 (水) 16:09:31};
- お返事ありがとうございました。復活された時は、ぜひ教えてください。楽しみにしています。 -- [[どぼん!]] &new{2011-02-10 (木) 01:57:23};
- こちらかな? 自然言語処理支援ライブラリ saezuri lite http://www.vector.co.jp/soft/winnt/prog/se495669.html --  &new{2012-05-22 (火) 20:35:21};

#comment

//これより下は編集しないでください
#pageinfo([[:Category/.NET]] [[:Category/ASP.NET]],2010-12-06 (月) 01:54:24,DOBON!,2010-12-06 (月) 01:54:24,DOBON!)

[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]