NuGetにMeCabがあった。テンションあがったので実装を試してみる。
NuGetでインストールしたら、using。
using NMeCab;
そしたら↓の感じ。
public void ana()
{
MeCabParam mPara = new MeCabParam();
//辞書ファイルがあるフォルダを指定(NuGetで入れれば勝手に入る)
mPara.DicDir = @"*****\dic\ipadic";
MeCabTagger mTagger = MeCabTagger.Create(mPara);
string sentence = "すもももももももものうち";//解析する文字列
MeCabNode node = mTagger.ParseToNode(sentence);
while (node != null)
{
if (node.CharType > 0)
{
Console.WriteLine("{0}\t{1}", node.Surface, node.Feature);
}
node = node.Next;
}
}
実行結果
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ も 助詞,係助詞,*,*,*,*,も,モ,モ もも 名詞,一般,*,*,*,*,もも,モモ,モモ の 助詞,連体化,*,*,*,*,の,ノ,ノ うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
すばらしい。前はRubyとか使ってゴニョゴニョしてたけど、いろいろできそう。
性能的には、CPU:2.9GHz(4コア),RAM:8GのWindows7で、 とあるニュース記事一本の文章を10000回解析して、51.34秒。 一回あたり、0.0051秒ってところでしょうか。
これだけだとアレなので、少し手を加える。MeCabはすばらしいんだけど、 戻りのインターフェースがCSV形式の文字列なので、いろいろ扱いにくい。 なので、結果を扱いやすくするためのクラスを下の感じで作る。 ↓のクラスの位置のプロパティは文章中の何番目に出てきたかを保持しておくために 追加してます。N-Gram解析とかで使いやすくするため。
public class MecabResult
{
//結果のリスト
public List<MecabResultItem> nodes { get; set; }
//コンストラクタ
public MecabResult(MeCabNode pnode)
{
nodes = new List<MecabResultItem>();
int itempos = 0;
while (pnode != null)
{
MecabResultItem addItem = new MecabResultItem();
if (pnode.CharType > 0)
{
addItem.表層形 = pnode.Surface;
string[] tmpStrs = pnode.Feature.Split(',');
if (tmpStrs.Length == 9)
{
addItem.品詞 = tmpStrs[0];
addItem.品詞細分類1 = tmpStrs[1];
addItem.品詞細分類2 = tmpStrs[2];
addItem.品詞細分類3 = tmpStrs[3];
addItem.活用形 = tmpStrs[4];
addItem.活用型 = tmpStrs[5];
addItem.原形 = tmpStrs[6];
addItem.読み = tmpStrs[7];
addItem.発音 = tmpStrs[8];
}
addItem.位置 = itempos;
nodes.Add(addItem);
}
itempos++;
pnode = pnode.Next;
}
}
public partial class MecabResultItem
{
public string 表層形 { get; set; }
public string 品詞 { get; set; }
public string 品詞細分類1 { get; set; }
public string 品詞細分類2 { get; set; }
public string 品詞細分類3 { get; set; }
public string 活用形 { get; set; }
public string 活用型 { get; set; }
public string 原形 { get; set; }
public string 読み { get; set; }
public string 発音 { get; set; }
public int 位置 { get; set; }
}
}
こうしておくとどーなるかと言うと、ラムダ式で検索とか出来ちゃうわけです。↓の感じ。
public void ana()
{
MeCabParam mPara = new MeCabParam();
//辞書ファイルがあるフォルダを指定(NuGetで入れれば勝手に入る)
mPara.DicDir = @"****\dic\ipadic";
MeCabTagger mTagger = MeCabTagger.Create(mPara);
string sentence = "すもももももももものうち";//解析する文字列
MeCabNode node = mTagger.ParseToNode(sentence);
MecabResult mr = new MecabResult(node);//ココで初期化
//名詞に絞って表示する
foreach(var tmp in mr.nodes.Where(n=>n.品詞 == "名詞"))
{
Console.WriteLine(tmp.表層形);
}
}