生活を良くします - 怠惰なプログラミング

生活を良くします-怠惰なプログラミング

外資系でエンジニアをやっています。便利なサービスや商品、プログラミングで作ったものなどを紹介していきます

Mac OS(Sierra) Javaでmecabを使う方法

形態素解析を行いたい

形態素解析とは

一連の文章を品詞などの最小単位に分割するのが形態素解析。テキストマイニングなどで利用可能。
形態素解析、難しそうだなと思っていたらもうすでにツールとして無料で公開されています。

『すももももものうち』では、以下のように分割されています。

f:id:what_a_day:20161029214144p:plain

このツールはmecabというもので、日本語やその他の外国語にも対応しています。
さらに自分で辞書に言葉を追加できるため、最新の言葉(ペンパイナッポーアッポーペン)も1単語というように登録でき非常に便利です。


mecabを使う方法

mecab本体の設定方法

  1. mecab-0.996.tarをダウンロードする
  2. mecab-0.996.tarを解凍する
  3. コマンドを打ち込み、mecabをインストールする


mecab-0.996.tarは MeCab: Yet Another Part-of-Speech and Morphological Analyzer
このサイトのダウンロードという項目のところからダウンロードできます。
この作業は、下記のコマンドを打ち込むことになります。mecab本体の設定は終了。

tar vzxf mecab-java-0.996.tar.gz //解凍
cd mecab-0.996.tar                       //ディレクトリに移動
./configure
make
sudo make install

mecab-ipadicの設定方法

  1. mecab-ipadic-2.7.0-***.tar.gzをダウンロードする
  2. mecab-ipadic-2.7.0-***.tar.gzを解凍する
  3. cd mecab-ipadic-2.7.0 として以下のコマンドを実行していく
今度はmecabの辞書をダウンロードします。あとで単語の追加もできます。
mecab-0.996.tarは MeCab: Yet Another Part-of-Speech and Morphological Analyzer このサイトのダウンロードという項目のところからダウンロードできます。

この作業はコマンド的には以下のようになります。

tar vzxf mecab-ipadic-2.7.0-***.tar.gz
./configure --with-charset=utf8
make
sudo make install

ここまで終了すれば、ターミナルからはmecabの使用が可能になります。

f:id:what_a_day:20161029222945p:plain

Javaからmecabを使う方法

mecab-javaのバインディング

  1. mecab-java-0.996.tar.gzをダウンロードする
  2. tar vzxf mecab-java-0.996.tar.gz で解凍する
  3. mecab-java-0.996内部のMakefileを見つける
  4. Makefileを変更する
  5. mecab-java-0.996のディレクトリでsudo makeを実行
  6. MeCab.jarとlibMeCab.soが生成される
  7. mecab-java-0.996内のtest.javaのプログラムを変更

以下ではこの内容について詳しく書いていきます

1.mecab-java-0.996.tar.gzをダウンロードする

探したところ、ここに落ちていました。

2.tar vzxf mecab-java-0.996.tar.gz で解凍する

3.mecab-java-0.996内部のMakefileを見つける

4.Makefile変更の詳細

通常のままでは、

MeCab_wrap.cxx:159:10: fatal error: 'jni.h' file not found

という表示が出てきてしまうため、必ず書き換える必要があります。Macではだいたいうまくいきました。Sierra,El Capitanで動作確認済み。
mecab-java-0.996というディレクトリの中にあるMakefileの内容を書き換えます。
変更場所は、主にINCLUDEの行、6行目です。

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX**/Library/Frameworks/JavaVM.framework/Versions/A/Headers/

MacOSXの場所は、各自のversionによって書き換えましょう。Mecab-javaの場合だけでなく、'jni.h' file not foundエラーが発生する場合は、INCLUDEを上の様に書き換えると大抵は解決します。なぜかこのファイルパスにjni.hたちがいたので確実だと思います。
ファイルを開き、以下のソースに内容を書き換えれば大丈夫です。

TARGET=MeCab
JAVAC=javac
JAVA=java
JAR=jar
CXX=c++
INCLUDE=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/

PACKAGE=org/chasen/mecab

LIBS=`mecab-config --libs`
INC=`mecab-config --cflags` -I$(INCLUDE) -I$(INCLUDE)/linux

all:
	$(CXX) -O3 -c -fpic $(TARGET)_wrap.cxx  $(INC)
	$(CXX) -shared  $(TARGET)_wrap.o -o lib$(TARGET).so $(LIBS)
	$(JAVAC) $(PACKAGE)/*.java
	$(JAVAC) test.java
	$(JAR) cfv $(TARGET).jar $(PACKAGE)/*.class

test:
	env LD_LIBRARY_PATH=. $(JAVA) test

clean:
	rm -fr *.jar *.o *.so *.class $(PACKAGE)/*.class
	
cleanall:
	rm -fr $(TARGET).java *.cxx

5.mecab-java-0.996のディレクトリでsudo makeを実行

6.MeCab.jarとlibMeCab.soが生成される

7.mecab-java-0.996内のtest.javaのプログラムの変更点

  1. test.javaを開く
  2. ファイルの内容を確認
  3. ファイルの内容を変更前 → 変更後 に書き換える

変更前のtest.java

static {
    try {
    	File f = new File("/Users/"ユーザー名"/mecab-java-0.996/libMeCab.so");
    	System.load(f.toString());
    } catch (UnsatisfiedLinkError e) {
       System.err.println("Cannot load the example native code.\nMake sure your LD_LIBRARY_PATH contains \'.\'\n" + e);
       System.exit(1);
    }
  }

変更後のtest.java

static {
    try {
    	File f = new File("/Users/"ユーザー名"/mecab-java-0.996/libMeCab.so");
    	System.load(f.toString());
    } catch (UnsatisfiedLinkError e) {
       System.err.println("Cannot load the example native code.\nMake sure your LD_LIBRARY_PATH contains \'.\'\n" + e);
       System.exit(1);
    }
  }

これでtest.javaがうまく動けば、無事に設定は終了しました。

Javaでmecabを使用するときは、libMeCab.soの場所を参照しなければいけないようです。
この部分です。

File f = new File("/Users/"ユーザー名"/mecab-java-0.996/libMeCab.so");

Javaでmecabを使ったプログラムを使うときはlibMeCab.soの場所を忘れないようなディレクトリに置いておきましょう。

IntelliJ IDEAでMecabを使用する

InttelliJ Ideaとは

統合開発環境で、ビジュアルにも機能面的にも非常に便利。慣れるとこれ無しだとストレスが溜まって仕事ができなくなるレベル。
IntelliJやEclipseに慣れすぎたあまり、普通のjavaのコンパイル方法すら忘れてしまったかの様に思われます。それくらいIntelliJは便利。無料でここまで使えるのに課金したらどうなるんだろうと考えています。
www.jetbrains.com
ここからcommunity versionをダウンロードすればO.K。Ultimate版だと課金する必要があります。

MeCab.jarをパスに入れる

Macだと、IntellIJを開いている時の上のMenu一覧にある「File ->Project Structure」を選択し次の画面を出します。
f:id:what_a_day:20161102211700p:plain
ずらっと.jarファイルが並んでいる下の方に +マークがあるかと思います。
そこの+マークを押し、「Mecab.jar」があるパスを選択、Applyボタンを押し、OKを押します。それでMecabのライブラリは使用可能です。
あとは、IntelliJでjavaのファイルを作り、以下のプログラムの様にすると実行可能になっているはずです。

import org.chasen.mecab.*;

import java.io.File;
public class mecabtest {
    static {
        try {
            File f = new File("/Users/****/Downloads/MeCab/mecab-java-0.996/libMeCab.so"); // Select libMeCab.so path
            System.load(f.toString());
        } catch (UnsatisfiedLinkError e) {
            System.err.println("Cannot load the example native code.\nMake sure your LD_LIBRARY_PATH contains \'.\'\n" + e);
            System.exit(1);
        }
    }

    public static void main(String[] argv) {
        System.out.println(MeCab.VERSION);
        Tagger tagger = new Tagger();
        String str = "太郎は二郎にこの本を渡した。";
        System.out.println(tagger.parse(str));
        Node node = tagger.parseToNode(str);
        for (; node != null; node = node.getNext()) {
            System.out.println(node.getSurface() + "\t" + node.getFeature());
        }
        System.out.println("EOS\n");

        Model model = new Model();
        Tagger tagger2 = model.createTagger();
        System.out.println(tagger2.parse(str));

        Lattice lattice = model.createLattice();
        System.out.println(str);
        lattice.set_sentence(str);
        if (tagger2.parse(lattice)) {
            System.out.println(lattice.toString());
            for (node = lattice.bos_node(); node != null; node = node.getNext()) {
                System.out.println(node.getSurface() + "\t" + node.getFeature());
            }
            System.out.println("EOS\n");
        }

        lattice.add_request_type(MeCab.MECAB_NBEST);
        lattice.set_sentence(str);
        tagger2.parse(lattice);
        for (int i = 0; i < 10; ++i) {
            if (lattice.next()) {
                System.out.println("nbest:" + i + "\n" +
                        lattice.toString());
            }
        }

    }
}

出力結果

0.996
太郎	名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
二郎	名詞,固有名詞,人名,名,*,*,二郎,ジロウ,ジロー
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ
この	連体詞,*,*,*,*,*,この,コノ,コノ
本	名詞,一般,*,*,*,*,本,ホン,ホン
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
渡し	動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。	記号,句点,*,*,*,*,。,。,。
EOS

	BOS/EOS,*,*,*,*,*,*,*,*
太郎	名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
二郎	名詞,固有名詞,人名,名,*,*,二郎,ジロウ,ジロー
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ
この	連体詞,*,*,*,*,*,この,コノ,コノ
本	名詞,一般,*,*,*,*,本,ホン,ホン
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
渡し	動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。	記号,句点,*,*,*,*,。,。,。
	BOS/EOS,*,*,*,*,*,*,*,*
EOS
.....
.....
.....