- 追加された行はこの色です。
- 削除された行はこの色です。
#freeze
[[python/集合知3章]]
2009/02/01からのアクセス回数 &counter;
2009/02/08からのアクセス回数 &counter;
** はじめに [#hca3206d]
pythonを使っていて感じるのは、便利だけどパッケージがマシンに依存し過ぎている
ように思われます。
例えば、スクリプトを別のマシンで動かそうとしたときに、パッケージのインストールから
はじめなくてはならないときに痛烈に感じます。
そこで、ここではjythonとjavaを使ってpythonのマシン依存部分をjavaのクラスとjythonの
スクリプトでラップしてみようと思います。
** 日本語の分かち書き [#bcf63440]
[[python/集合知3章]]と同様に、ブログに対する日本語処理からはじめます。
*** senのインストール [#l6877481]
chasenと同様の機能を持つjavaのライブラリにSenがあります。
残念ながら、maven2のパッケージとして提供されていないので、[[java.netのsenのドキュメント&ファイルページ>https://sen.dev.java.net/servlets/ProjectDocumentList?folderID=755&expandFolder=755&folderID=0]]からsen-1.2.2.1.zipをダウンロードしてください。
- ZIPファイルの解凍
ここでは、
-- ダウンロードしたファイルは、~/Downloadedディレクトリ
-- 解凍先は、~/localディレクトリ
にあるものとして説明します。
-- unzipで解凍します
#pre{{
$ cd ~/local/
$ unzip ~/Downloaded/sen-1.2.2.1.zip
$ cd sen-1.2.2.1/
}}
- 辞書の作成
つぎにantを使って辞書を作成します。
-- 辞書の作成にはperlが必要です。ここでは/usr/bin/perlを使います。
#pre{{
$ cd dic
$ ant -Dperl.bin=/usr/bin/perl
}}
- jarファイルのmaven2への登録
最後にsen.jarファイルをmaven2で利用できるようにローカルディポジトリに登録します。
#pre{{
$ cd ../lib
$ mvn install:install-file -Dfile=./sen.jar -DgroupId=sen \
-DartifactId=sen -Dversion=1.0 -Dpackaging=jar
}}
*** pythonlibの作成 [#t0a1c539]
作成したライブラリは1つのjarにまとめておくとjythonから利用するときに便利です。
ここでは、pythonlibというEclipseのプロジェクトをmaven2を使って作成します。
- プロジェクトの作成
最初にjythonlibのプロジェクトを作成します。
#pre{{
$ mvn archetype:create -DgroupId=jythonlib -DartifactId= jythonlib -Dversion=0.1
}}
- pom.xmlの編集
pom.xmlを編集して、sen.jar, common-logging.jarを使えるようにします。
以下の定義をdependenciesに追加
#pre{{
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>sen</groupId>
<artifactId>sen</artifactId>
<version>1.0</version>
</dependency>
}}
次にbuildを追加し、javaのバージョン、UTF-8の設定、jarファイルの設定、依存ライブラリのコピーをセットします。
#pre{{
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>jythonlib.Sen</mainClass>
<packageName>jythonlib</packageName>
<addClasspath>true</addClasspath>
<addExtensions>true</addExtensions>
<classpathPrefix>./lib</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
}}
この設定は、結構役に立ちますから、覚えておいた方がいいですよ。
- Eclipseプロジェクトに対応
以下のコマンドで、Eclipseの.projectと.classpthを作成します。
#pre{{
$ mvn eclipse:eclipse -DdownloadSources=true
}}
*** Senクラスの作成 [#z42e3be5]
senの形態素解析を実行し、jythonにその結果を返すクラスSen.javaを作成します。
変換部分は、
#pre{{
private String[] parts = {"形容詞", "形容動詞", "副詞", "連体詞", "名詞", "動詞"};
public List<String> sparse(String text) {
List<String> list = new ArrayList<String>();
try {
StringTagger tagger = StringTagger.getInstance();
Token[] token = tagger.analyze(text);
String term = null;
for (int i = 0; i < token.length; i++) {
// 未知語、英語の単語
if ((term = token[i].getTermInfo()) == null) {
list.add(token[i].getSurface());
}
else {
for (String part : parts) {
if (term.startsWith(part)) {
list.add(token[i].getBasicString());
break;
}
}
}
}
} catch (Exception e) {
}
return (list);
}
}}
と簡単です。
*** Jythonとjava間の日本語処理 [#x6518ada]
jythonとjavaとの日本語は、結構大変です。ここでは以下の方針で文字を渡すことに
します。
- jythonからjavaへは、UTF-8でエンコーディングされたバイト文字列を渡す
javaでの変換は以下のようになります。
#pre{{
jTxt = String(txt, "utf-8")
}}
- javaからjythonへは、unicodeにエンコーディングされた文字列を渡す
javaでの変換は以下のようになります。
#pre{{
uTxt = String(word.getBytes('utf-8'), 'iso-8859-1')
}}
sen用のsplitメソッドをsplit.pyに以下のように定義します。
#pre{{
# -*- coding: utf-8 -*-
import japanese
import codecs
import jarray
import jythonlib.Sen
import java.lang.String
from java.lang import *
parts = ["形容詞", "形容動詞", "副詞", "連体詞", "名詞", "動詞"]
parts = jarray.array([String(part, "utf-8") for part in parts], java.lang.String)
def split(txt):
jTxt = String(txt, "utf-8")
sen = jythonlib.Sen(parts)
words = sen.sparse(jTxt)
outList = []
for i in range(len(words)):
word = String(words.get(i))
outList.append(String(word.getBytes('utf-8'), 'iso-8859-1'))
return outList
}}
*** 動作確認 [#p94f14f0]
senを使った分かち書きのテストをします。
#pre{{
# -*- coding: utf-8 -*-
import japanese
import split
txt = "オリジナルのソースは、原書著者TobesのページからPCI_Code.zipと してダウンロードできます。"
print txt
words = split.split(txt)
for word in words:
print word
}}
を実行すると、
#pre{{
オリジナルのソースは、原書著者TobesのページからPCI_Code.zipと してダウンロードできます。
オリジナル
ソース
原書
著者
Tobes
ページ
PCI
_
Code
.
zip
する
ダウンロード
できる
}}
と出力されます。
chasenと比べると英語の文字も正しく処理されること、「から」が名詞ではなく正しく助詞?
として認識されています。
** コメント [#tbf261fc]
この記事は、
#vote(おもしろかった,そうでもない,わかりずらい)
皆様のご意見、ご希望をお待ちしております。
#comment_kcaptcha