Javaと情熱のあいだ

カステラとドーナツと珈琲

三分で作る日本語形態素解析

Java形態素解析をしようとおもったら、Senという解析システムが
あるんですが、環境構築が結構面倒なのでほかに方法がないかな〜と
考えていたら、Yahoo!に形態素解析のAPIがあるみたいなので
JDOMのサンプルにいいかもと思って、Javaでラッピングするサンプルを作る。
機能としては、文字列を渡すと形態素解析をして
ListにBeanWordを詰めて返してくれるようにする。
Mapに詰めようかなと考えたけれど、要素の指定が面倒なので廃案に。

材料は

commons-codec-1.3←URLエンコード
jdomXML解析用

MorphologicalAnalysis.java

import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.codec.net.URLCodec;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;

/**
 *
 * <HR>
 * <P>
 *  ■モジュール名 <BR>
 * <BLOCKQUOTE>
 *      MorphologicalAnalysis.java <BR>
 * </BLOCKQUOTE>
 * <P>
 *  ■クラス仕様 <BR>
 * <BLOCKQUOTE>
 *      MorphologicalAnalysisクラスは形態素解析をするクラスです。<BR>
 * </BLOCKQUOTE>
 * <P>
 * <HR>
 * <P>
 */
public class MorphologicalAnalysis {
    /**
     *  形態素解析APIURL
     */
    static final String MAURL = "http://api.jlp.yahoo.co.jp/"
        + "MAService/V1/parse?appid=auction_data&results=uniq"
        + "&uniq_filter=9&sentence=";

    /**
     *
     * 指定された文字列の形態素解析を行う。
     * @param sentence 対象文字列
     * @return 分解文字列リスト
     * @throws Exception 例外
     */
    public static List<BeanWord> execute(
            final String sentence) throws Exception {

        final URLCodec codec = new URLCodec();

        final Document doc = new SAXBuilder().build(
                new URL(MAURL + codec.encode(sentence, "UTF-8")));

        final Element root = doc.getRootElement();

        final Namespace ns = root.getNamespace();

        final List<Element> children = root.getChild("uniq_result", ns).getChild(
                "word_list", ns).getChildren("word", ns);

        final List<BeanWord> result = new ArrayList<BeanWord>();

        for (Element child : children) {
            final BeanWord word = new BeanWord();

            word.setSurface(child.getChild("surface", ns).getTextTrim());
            word.setReading(child.getChild("reading", ns).getTextTrim());
            word.setPos(child.getChild("pos", ns).getTextTrim());

            if (child.getChild("baseform", ns) != null) {
                word.setBaseform(child.getChild("baseform", ns).getTextTrim());
            }

            word.setCount(child.getChild("count", ns).getTextTrim());

            result.add(word);
        }

        return result;
    }
}

BeanWord.java

/**
 * <HR>
 * <P>
 *  ■モジュール名 <BR>
 * <BLOCKQUOTE>
 *      BeanWord.java <BR>
 * </BLOCKQUOTE>
 * <P>
 *  ■クラス仕様 <BR>
 * <BLOCKQUOTE>
 *      BeanWordクラスは形態素解析Beanクラスです。<BR>
 * </BLOCKQUOTE>
 * <P>
 * <HR>
 * <P>
 */
public class BeanWord {

    /**
     * 表記
     */
    private String surface;

    /**
     * 読みがな
     */
    private String reading;

    /**
     * 品詞
     */
    private String pos;

    /**
     * 基本形表記
     */
    private String baseform;

    /**
     * 形態素の出現数
     */
    private String count;

    public String getBaseform() {
        return baseform;
    }

    public void setBaseform(String baseform) {
        this.baseform = baseform;
    }

    public String getCount() {
        return count;
    }

    public void setCount(String count) {
        this.count = count;
    }

    public String getPos() {
        return pos;
    }

    public void setPos(String pos) {
        this.pos = pos;
    }

    public String getReading() {
        return reading;
    }

    public void setReading(String reading) {
        this.reading = reading;
    }

    public String getSurface() {
        return surface;
    }

    public void setSurface(String surface) {
        this.surface = surface;
    }


}

プロキシが設定されてる場合は、適当なとこでプロキシを設定する必要がある。

    System.setProperty("http.proxyHost", "proxy.xxx.xxx.xxx");
    System.setProperty("http.proxyPort", "8080");

文字列が長すぎると、形態素解析してくれないかも。