2011/07/09

JavaのウェブアプリケーションフレームワークSpring Frameworkを試してみます。



SAStrutsの次に、JavaのウェブアプリケーションフレームワークSpring Frameworkを試してみます。Spring Framework 3.1を試します。SAStrutsについては、沢山の情報がありましたが、それに比べて、Spring Frameworkは日本語での情報が少ないように感じました。


SAStrutsと同様に、Eclipseプラグインを入れて、チュートリアル的なコンテンツがあれば、Spring Frameworkがどのようなものか分かると思います。しかし、SAStrutsでは、簡単に用意できた環境が、Spring Frameworkではなかなか用意できませんでした。

下記のサイトの記述を参考にSpringIDEプラグインを導入しました。

Springフレームワーク
http://w.livedoor.jp/w2u_dev/d/Spring%A5%D5%A5%EC%A1%BC%A5%E0%A5%EF%A1%BC%A5%AF

しかし、下記のエラーが出ます。
1 つ以上の必須項目が見つからないため、インストールを完了できません。
  Software being installed: SpringSource Tool Suite Runtime Error Analysis Support 2.6.0.201103161000-RELEASE (com.springsource.sts.runtimeerroranalysis.feature.group 2.6.0.201103161000-RELEASE)
  Missing requirement: SpringSource Tool Suite Runtime Error Analysis Support 2.6.0.201103161000-RELEASE (com.springsource.sts.runtimeerroranalysis.feature.group 2.6.0.201103161000-RELEASE) requires 'com.atlassian.connector.eclipse.jira.feature.group 0.0.0' but it could not be found


エラーメッセージから判断して、下記のプラグインをインストールしてみました。

http://download.eclipse.org/tools/ajdt/37/update


http://update.atlassian.com/atlassian-eclipse-plugin/e3.6/


さらに、色々調べてみると、SpringSource Tools Suite(STS)というものがあることが分かりました。エラーメッセージの中にも「SpringSource Tool Suite Runtime Error」という言葉があるので、SpringSource Tools Suite(STS)をインストールしました。

すると、SpringIDEプラグインのCoreだけはインストールすることが出来ました。

Eclipseの新規プロジェクトの選択肢の中にSpring関連のプロジェクトが用意されました。その中にSpringSource Tools Suiteもインストールされていました。


しかし、この後、チュートリアル的なコンテンツがどこにあるのかが分かりません。

Springの公式サイトにサンプルらしきものが公開されているので、これを試す方法から調べてみます。

https://src.springframework.org/svn/spring-samples/



2011/07/07

JavaのウェブアプリケーションフレームワークのSAStrutsを試してみました。



JavaのウェブアプリケーションフレームワークのSAStrutsを試してみました。


Javaのウェブアプリケーションフレームワークの比較を下記のページで教えていただきました。

Javaフレームワークの比較検討資料公開
http://d.hatena.ne.jp/t_yano/20081118/1227008018

このページの内容を拝見して、他のサイトも調べてみて、SAStruts、Spring Framework、Google Guiceなどに興味が出て来ました。どれも面白いそうです。どれも言葉ぐらいは聞いたことはありましたが、内容については、まったく知りませんでした。

この中から、まず、SAStrutsを試してます。Javaのウェブアプリケーションフレームワークとしては、Strutsはまだまだよく使われているとの情報をあちこちで見ました。SAStrutsは、Strutsを使いやすくしたものとの記述がありました。

Windows 7 で、SAStrutsの動く環境を用意します。

一番簡単に環境を用意するために、下記のパッケージを利用します。

Eclipse 3.7.0 Indigo Windows 32bit ベース / Pleiades All in One 3.7.0.v20110704
http://mergedoc.sourceforge.jp/

Eclipseが既に日本語化されていて、Tomcatも入っているので簡単です。

ダウンロードして解凍した「pleiades-e3.7-ultimate-jre_20110704」---「eclipse」フォルダの中にある「eclipse.exe」を起動します。

下記のページを参考に、eclipseにSAStrutsのプラグインをインストールします。

eclipseにSAStrutsのプラグインをインストール
http://ichitcltk.hustle.ne.jp/gudon/modules/pico_rd/index.php?content_id=2

次に、Super Agile Strutsチュートリアルの「sa-struts-tutorial-1.0.4-sp8.zip」をダウンロードします。

Super Agile Struts - Download
http://sastruts.seasar.org/download.html

次に、ダウンロードした「sa-struts-tutorial-1.0.4-sp8.zip」をセットアップします。

チュートリアルのセットアップ
http://ichitcltk.hustle.ne.jp/gudon/modules/pico_rd/index.php?content_id=3

「sa-struts-tutorial」プロジェクトのsrc/main/java/を展開して「tutorial.action」パッケージのIndexAction.javaを選択、 マウスの右クリックメニューより「SAStruts」→「サーバで表示」を選択します。

チュートリアルのトップページが表示されました。


プログラムも正常に動作しました。「足し算」プログラムを元に、引き算に修正してみました。



2011/07/04

地名と共に画像をアップすると、マップ上にコメント付きで画像を配置できるGoogle App Engineアプリを試してみました



地名と共に画像をアップすると、マップ上にコメント付きで画像を配置できるGoogle App Engineアプリを試してみました。

Google App Engine と Maps で作ったWebアプリのソースを公開されている方がいました。面白そうなソースなので、設置をして試してみました。このような動くサンプルを見せていただけると、とても良くGoogle App Engineの構造が分かります。感謝!

自分のアカウントでアップしてみました。Pythonの部分は1点のみ修正をしています。見栄えについては変更しました。

My Photo in Google Maps on GAE
http://vivo-map.appspot.com/maps


Pythonのソースの修正した部分について。ローカルで動作テストをすると、ジオコーディングは正常に動作するのですが、サーバ上に上げると、緯度経度の取得が出来ない現象がありました。サーバ上で何が起きているのかをステータスコードで確認をすると、「google.maps.GeocoderStatus.OVER_QUERY_LIMIT」というステータスを取得していることが分かりました。これは、「使用制限回数の上限を超えたことを示している」そうです。ローカルからのリクエストは問題なく、サーバからのリクエストで問題が起きるのが、よく分かりません。

ジオコーディングをしている下記の部分を変更してみました。
class PostPage(webapp.RequestHandler):

  def getGeometory(self, place):
    url = u"http://maps.google.com/maps/api/geocode/xml?address=%s&sensor=false" % urllib.quote(place.encode('utf8'))
    result = urlfetch.fetch(url)
    lat = 35.6895060 # 東京
    lng = 139.6917010 # 東京
    if result.status_code == 200:
      doc = xml.dom.minidom.parseString(result.content)
      if doc.getElementsByTagName('status').item(0).childNodes[0].data == "OK":
        lat = doc.getElementsByTagName('lat').item(0).childNodes[0].data
        lng = doc.getElementsByTagName('lng').item(0).childNodes[0].data

    return db.GeoPt(lat, lng)

Pythonのgooglemapsモジュールを使った検索にしてみました。内部では同じことをしているのだから、ダメかと思いましたが、サーバ上でも動作をしました。
# モジュールを追加
from googlemaps import GoogleMaps

class PostPage(webapp.RequestHandler):

  def getGeometory(self, place):
    gmaps = GoogleMaps()
    address = place.encode('utf8')
    lat, lng = gmaps.address_to_latlng(address)  

    return db.GeoPt(lat, lng)

でたらめな場所(地名/駅名/〒)の情報でも、何かしらの場所の緯度経度に変換をして地図にポイントをします。

下記の記事のソースを使わせていただきました。

Google App Engine と Maps でWebアプリ作ってみた
http://sakitake4.blogspot.com/2011/04/google-app-engine-maps-web.html?spref=tw


ありがとうございました。

2011/06/30

Google Map APIを使って、簡単に地名などから緯度、経度に変換が出来るPythonのモジュール「googlemaps」を使ってみました



Google Map APIを使って、簡単に geocoding や reverse geocoding が出来るPythonのモジュールがあります。

googlemaps 1.0.2
http://pypi.python.org/pypi/googlemaps/


ジオコーディングとは、住所や地名、駅名などの情報から、緯度・経度の座標値に変換する技術のことです。

住所から、緯度、経度への変換
> python
Python 2.5.2 [MSC v.1310 32 bit (Intel)] onwin32
>>> from googlemaps import GoogleMaps
>>> gmaps = GoogleMaps('API_Key')
>>> address = u'岡山市'
>>> lat, lng = gmaps.address_to_latlng(address)
>>> print lat, lng
34.6551456 133.9195019

サンプルでは、Google MapのAPIキーを使っての説明をしていますが、Google Maps API v3からは、APIキーは不要になったので、APIキーを渡さなくても操作できます。
>>> from googlemaps import GoogleMaps
>>> gmaps = GoogleMaps()
>>> address = u'岡山市'
>>> lat, lng = gmaps.address_to_latlng(address)
>>> print lat, lng
34.6551456 133.9195019

Linux上でも同様に動きます。

$ python
Python 2.6 [GCC 3.4.4 20050721 (Red Hat 3.4.4-2)] on linux2
>>> from googlemaps import GoogleMaps
>>> gmaps = GoogleMaps()
>>> address = u'岡山市'
>>> lat, lng = gmaps.address_to_latlng(address)
>>> print lat, lng
34.6551456 133.9195019

逆(緯度、経度から住所への変換)も可能です。
>>> destination = gmaps.latlng_to_address(34.6551456,133.9195019)
>>> print destination
岡山市役所

その近辺の検索

「秋葉原周辺のWifiスポットのある喫茶店」?の検索結果の最初のもの「」Japan town acupuncture & Oriental Medicine, Inc.」がヒット
>>> local = gmaps.local_search('cafes w. free power near akihabara')
>>> print local['responseData']['results'][0]['titleNoFormatting']
Japan town acupuncture & Oriental Medicine, Inc.
「Okayama」に変ると「Ryokan Misono Kurashiki」がヒット
>>> local = gmaps.local_search('cafes w. free power near Okayama')
>>> print local['responseData']['results'][0]['titleNoFormatting']
Ryokan Misono Kurashiki
「Okayamaの近くのschool」の検索結果の4番目のもの
>>> local = gmaps.local_search('school near Okayama')
>>> print local['responseData']['results'][3]['titleNoFormatting']
フラップアップゼミ
「岡山市」に変ると「鬼ヶ島宮ノ松原キャンプ場」がヒット
>>> local = gmaps.local_search(u'school near 岡山市')
>>> print local['responseData']['results'][3]['titleNoFormatting']
鬼ヶ島宮ノ松原キャンプ場
「岡山市の近くの学校」に変ると「KLCセミナー倉敷校」がヒット
>>> local = gmaps.local_search(u'学校 near 岡山市')
>>> print local['responseData']['results'][3]['titleNoFormatting']
KLCセミナー倉敷校

2011/06/26

「RSSの中に含まれる名詞の集計表を作成する」のRSSの読み込みの不具合解消しました。



「RSSの中に含まれる名詞の集計表を作成する」のRSSの読み込みの不具合解消しました。

mecab-pythonを使って、RSSの中に含まれる名詞の集計表を作るソースを試してみました。
http://vivo-design.blogspot.com/2011/06/mecab-pythonrss.html

の続きです。


Yahooの提供するRSSであれば、問題なく読めるのですが、それ以外は、「Failed to parse feed」となる点が解消しました。修正したソースで作成した集計表です。Yahoo以外のRSSを読み込んで、集計が出来ました。私が試行錯誤していた時に追記したものが、不要なだけでした。


修正したソース

analysis_rss_feed.py
本体
#coding:utf-8
import re
import csv
import MeCab
import feedparser
from extractKeyword  import extractKeyword


#=====================
# ----- set URLs -----
#=====================

"""
# IT関連
URLs = ['http://headlines.yahoo.co.jp/rss/itmedia_ait.xml',
        'http://headlines.yahoo.co.jp/rss/bcn.xml',
        'http://headlines.yahoo.co.jp/rss/impress_c_sci.xml',
        'http://headlines.yahoo.co.jp/rss/rbb.xml',
        'http://headlines.yahoo.co.jp/rss/scan.xml']

# 雑誌関連
URLs = ['http://zasshi.news.yahoo.co.jp/rss/sspa.xml',
        'http://zasshi.news.yahoo.co.jp/rss/sasahi.xml',
        'http://zasshi.news.yahoo.co.jp/rss/shincho.xml',
        'http://zasshi.news.yahoo.co.jp/rss/sbunshun.xml',
        'http://zasshi.news.yahoo.co.jp/rss/chuokou.xml',
        'http://zasshi.news.yahoo.co.jp/rss/playboyz.xml',
        'http://zasshi.news.yahoo.co.jp/rss/gendaibiz.xml',
        'http://zasshi.news.yahoo.co.jp/rss/bshunju.xml']
"""
# 一般のニュース関連
URLs = ['http://rss.asahi.com/f/asahi_newsheadlines',
        'http://rss.rssad.jp/rss/mainichi/flash.rss',
        'http://rss.yomiuri.co.jp/rss/yol/topstories',
        'http://sankei.jp.msn.com/rss/news/points.xml',
        'http://www.jiji.com/rss/ranking.rdf',
        'http://www.kyodo.co.jp/feed/']


#===============================
# ----- category selection -----
#===============================
class_num = 0
word_classes = [u'名詞',u'動詞',u'形容詞',u'副詞',u'助詞',u'助動詞']
word_class = word_classes[class_num]

#==============================
# ----- defined functions -----
#==============================
def getwordcounts(url):
    """RSSフィードのタイトルと、単語の頻度のディクショナリを返す"""
    # フィードをパースする
    d = feedparser.parse(url)
    wc={}
    
    # すべてのエントリをループする
    # RSSの種類によって,記事に相当する部分が異なることに対応する
    for e in d.entries:

        # 追加したこの部分が不要でした
        # if 'summary_detail' in e: summary = e.summary_detail
        if 'summary' in e: summary = e.summary

        elif 'description' in e: summary = e.description
        else: summary = e.link

        # 単語のリストを取り出す
        words = getwords(e.title+' '+summary)
        # extractKeywordを用いるため,単語を連結してテキスト化
        txt = ''
        for i in range(len(words)):
            txt += words[i]
        words_sub = extractKeyword(txt,word_class)
        
        for word in words_sub:
            # dict型のkeyにwordがなければ,value=0として新設
            wc.setdefault(word,0)
            wc[word] += 1
    return d.feed.title,wc

def getwords(html):
    """すべてのHTMLタグを取り除き,単語リストを返す"""

    # htmlから'<[^>]+>'を''に置き換える
    txt = re.compile(r'<[^>]+>').sub('',html)
    tagger = MeCab.Tagger('-Owakati')
    txt = txt.encode('utf-8')
    return tagger.parse(str(txt)).split(' ')
    # return tagger.parse(txt.encode('utf-8')).split(' ')
    # return tagger.parse(txt.encode('euc-jp')).split(' ')

def main():
    apcount = {}
    wordcounts = {}
    feedlist = [line for line in URLs]
    for feedurl in feedlist:
        wc = {}
        try:
            title,wc_ini = getwordcounts(feedurl)

            for w,bc in wc_ini.items():

                # csvで日本語を表示させるため,Shift_JIS化
                # この部分はエンコードをかけると、どの文字コード
                # でも、エラーになりました。
                # wc.setdefault(w.encode('sjis'),bc)

                wc.setdefault(w,bc)

            wordcounts[title] = wc

            # for word,count in wc.items():
            for word,count in wc.items():
                apcount.setdefault(word,0)
                if count>1:
                    # それぞれの単語が出現するフィードの数を数える
                    apcount[word]+=1
        except:
            # urlが認識できなければエラー表示
            print 'Failed to parse feed %s' % feedurl
    
    # でたらめな単語が存在するフィードがあることや
    # 一般的な単語の除外を考慮し,単語の出現率に敷居値を設定する
    wordlist = []
    for w,bc in apcount.items():
        frac = float(bc)/len(feedlist)
        if frac>0.1 and frac<0.5: wordlist.append(w)
    
    # csvへの書き込み用リストを生成
    header = ['Feed_name']+wordlist
    rows = []
    for blog,wc in wordcounts.items():
        # row = [blog.encode('sjis')]
        row = [blog.encode('utf-8')]
        for word in wordlist:
            if word in wc: row.append(wc[word])
            else: row.append('0')
        rows.append(row)
    
    # csvへ書き込み
    csv_writer = csv.writer(open('rss_data.csv','w'),lineterminator='\n')
    csv_writer.writerow(header)
    csv_writer.writerows(rows)    
    
if __name__ == "__main__":
    main()
修正したのは、下記の2箇所
# 一般のニュース関連
URLs = ['http://rss.asahi.com/f/asahi_newsheadlines',
        'http://rss.rssad.jp/rss/mainichi/flash.rss',
        'http://rss.yomiuri.co.jp/rss/yol/topstories',
        'http://sankei.jp.msn.com/rss/news/points.xml',
        'http://www.jiji.com/rss/ranking.rdf',
        'http://www.kyodo.co.jp/feed/']

途中略

# 追加したこの部分が不要でした
# if 'summary_detail' in e: summary = e.summary_detail
if 'summary' in e: summary = e.summary

この部分が無くても、どのRSSでも正常に動作しました。

mecab-pythonを使って、RSSの中に含まれる名詞の集計表を作るソースを試してみました。



mecab-pythonを使って、何か面白いサンプルは無いかなと探していたら、下記の記事を見つけました。

RSSフィードから単一品詞の単語別出現数を取得してみた.
http://d.hatena.ne.jp/r_e10/20110420/1303326055


面白そうなので、試してみました。今回は、自宅のサーバのPython2.6(fedoraの古いバージョン)で試します。

出来た集計表が下記のものです。

RSSの中に含まれる名詞を取り出し、その名詞の出現数を集計したCSVの表を作成するものです。


しかし、なかなか上手くいきませんでした。起こったエラーをまとめます。

エラーその1 そもそもRSSのフィードが読めない

「Failed to parse feed」というエラーが出ます。Yahooの提供するものであれば、問題なく読めるのですが、それ以外は、「Failed to parse feed」となります。各feedの構成を調べれば、解決するのかもしれませんが、現時点では、YahooのRSSだけで動作させてみます。

エラーその2 UnicodeEncodeError

色々なUnicode系のエラーが出ました。色々な対応を試しすぎて、結局、どれが有効なのか、はっきりとは分かっていません。まず、下記のサイトの記述を参考に、mecab-ipadic(辞書)のインストールをし直しました。

Python による日本語自然言語処理
http://nltk.googlecode.com/svn/trunk/doc/book-jp/ch12.html
MeCabの文字コードはデフォルトのEUC-JPからUTF-8に変更
Unix環境においては、辞書をインストールする際に、

% ./configure --with-charset=utf8
% make
% su
# make install

ソースコードの修正

analysis_rss_feed.py
本体のファイル
#coding:utf-8
import re
import csv
import MeCab
import feedparser
from extractKeyword  import extractKeyword


#=====================
# ----- set URLs -----
#=====================

"""
# IT関連
URLs = ['http://headlines.yahoo.co.jp/rss/itmedia_ait.xml',
        'http://headlines.yahoo.co.jp/rss/bcn.xml',
        'http://headlines.yahoo.co.jp/rss/impress_c_sci.xml',
        'http://headlines.yahoo.co.jp/rss/rbb.xml',
        'http://headlines.yahoo.co.jp/rss/scan.xml']
"""

# 雑誌関連
URLs = ['http://zasshi.news.yahoo.co.jp/rss/sspa.xml',
        'http://zasshi.news.yahoo.co.jp/rss/sasahi.xml',
        'http://zasshi.news.yahoo.co.jp/rss/shincho.xml',
        'http://zasshi.news.yahoo.co.jp/rss/sbunshun.xml',
        'http://zasshi.news.yahoo.co.jp/rss/chuokou.xml',
        'http://zasshi.news.yahoo.co.jp/rss/playboyz.xml',
        'http://zasshi.news.yahoo.co.jp/rss/gendaibiz.xml',
        'http://zasshi.news.yahoo.co.jp/rss/bshunju.xml']

#===============================
# ----- category selection -----
#===============================
class_num = 0
word_classes = [u'名詞',u'動詞',u'形容詞',u'副詞',u'助詞',u'助動詞']
word_class = word_classes[class_num]

#==============================
# ----- defined functions -----
#==============================
def getwordcounts(url):
    """RSSフィードのタイトルと、単語の頻度のディクショナリを返す"""
    # フィードをパースする
    d = feedparser.parse(url)
    wc={}
    
    # すべてのエントリをループする
    # RSSの種類によって,記事に相当する部分が異なることに対応する
    for e in d.entries:
        if 'summary' in e: summary = e.summary

        #  add for yahoo.co.jp_rss
        if 'summary_detail' in e: summary = e.summary_detail

        elif 'description' in e: summary = e.description
        else: summary = e.link

        # 単語のリストを取り出す
        words = getwords(e.title+' '+summary)
        # extractKeywordを用いるため,単語を連結してテキスト化
        txt = ''
        for i in range(len(words)):
            txt += words[i]
        words_sub = extractKeyword(txt,word_class)
        
        for word in words_sub:
            # dict型のkeyにwordがなければ,value=0として新設
            wc.setdefault(word,0)
            wc[word] += 1
    return d.feed.title,wc

def getwords(html):
    """すべてのHTMLタグを取り除き,単語リストを返す"""

    # htmlから'<[^>]+>'を''に置き換える
    txt = re.compile(r'<[^>]+>').sub('',html)
    tagger = MeCab.Tagger('-Owakati')
    txt = txt.encode('utf-8')
    return tagger.parse(str(txt)).split(' ')

def main():
    apcount = {}
    wordcounts = {}
    feedlist = [line for line in URLs]
    for feedurl in feedlist:
        wc = {}
        try:
            title,wc_ini = getwordcounts(feedurl)

            for w,bc in wc_ini.items():

                # csvで日本語を表示させるため,Shift_JIS化
                # この部分はエンコードをかけると、どの文字コード
                # でも、エラーになりました。
                # wc.setdefault(w.encode('sjis'),bc)

                wc.setdefault(w,bc)

            wordcounts[title] = wc

            # for word,count in wc.items():
            for word,count in wc.items():
                apcount.setdefault(word,0)
                if count>1:
                    # それぞれの単語が出現するフィードの数を数える
                    apcount[word]+=1
        except:
            # urlが認識できなければエラー表示
            print 'Failed to parse feed %s' % feedurl
    
    # でたらめな単語が存在するフィードがあることや
    # 一般的な単語の除外を考慮し,単語の出現率に敷居値を設定する
    wordlist = []
    for w,bc in apcount.items():
        frac = float(bc)/len(feedlist)
        if frac>0.1 and frac<0.5: wordlist.append(w)
    
    # csvへの書き込み用リストを生成
    header = ['Feed_name']+wordlist
    rows = []
    for blog,wc in wordcounts.items():
        # row = [blog.encode('sjis')]
        row = [blog.encode('utf-8')]
        for word in wordlist:
            if word in wc: row.append(wc[word])
            else: row.append('0')
        rows.append(row)
    
    # csvへ書き込み
    csv_writer = csv.writer(open('rss_data.csv','w'),lineterminator='\n')
    csv_writer.writerow(header)
    csv_writer.writerows(rows)    
    
if __name__ == "__main__":
    main()
修正したのは、下記の3箇所
#  add for yahoo.co.jp_rss
if 'summary_detail' in e: summary = e.summary_detail

# wc.setdefault(w.encode('sjis'),bc)
wc.setdefault(w,bc)

# row = [blog.encode('sjis')]
row = [blog.encode('utf-8')]
extractKeyword.py テキストを形態素解析して、名詞のみのリストを返すためファイル
#coding:utf-8
import MeCab

#=====================
# ----- set text -----
#=====================
test_txt = u'PythonからMeCabの形態素解析機能を使ってみました。'

#===============================
# ----- category selection -----
#===============================
class_num = 0
word_classes = [u'名詞',u'動詞',u'形容詞',u'副詞',u'助詞',u'助動詞']
word_class = word_classes[class_num]

#==============================
# ----- defined functions -----
#==============================

def extractKeyword(text,word_class):
    """textを形態素解析して、名詞のみのリストを返す"""
    
    tagger = MeCab.Tagger('-Ochasen')
    # node = tagger.parseToNode(text.encode('utf-8'))
    node = tagger.parseToNode(text)
    keywords = []
    while node:
        # if node.feature.split(",")[0] == word_class:
        if node.feature.split(",")[0] == word_class.encode('utf-8'):
            keywords.append(node.surface)
        node = node.next
    return keywords

def main():
    keywords = extractKeyword(test_txt)
    for w in keywords:
        print w,

if __name__ == "__main__":
    main()
修正したのは、下記の2箇所
# node = tagger.parseToNode(text.encode('utf-8'))
node = tagger.parseToNode(text)

# if node.feature.split(",")[0] == word_class:
if node.feature.split(",")[0] == word_class.encode('utf-8'):

2011/06/22

MeCab(オープンソース形態素解析エンジン)のPythonのバインディングをインストールしてみました。



MeCabとは、オープンソース形態素解析エンジンです。形態素解析とは、自然言語で書かれた文を、形態素(言語で意味を持つ最小単位)に分割する技術のこと。MeCabは、いくつかある形態素解析エンジンのひとつです。

MeCab (和布蕪)とは
http://mecab.sourceforge.net/


MeCabのスクリプト言語バインディングより、Pythonによるバインディング「mecab-python」をインストールしてみました。

MeCabのスクリプト言語のバインディング
http://mecab.sourceforge.net/bindings.html

さくらのVPSにインストールしてみました。

mecabのインストール
$ wget http://sourceforge.net/projects/mecab/files/mecab/0.98/mecab-0.98.tar.gz
$ tar vxzf mecab-0.98.tar.gz
$ cd mecab-0.98.tar.gz
$ ./configure
$ make
$ sudo make install

mecab-ipadic(辞書)のインストール
$ wget http://sourceforge.net/projects/mecab/files/mecab-ipadic/2.7.0-20070801/mecab-ipadic-2.7.0-20070801.tar.gz
$ tar vxzf mecab-ipadic-2.7.0-20070801.tar.gz
$ cd mecab-ipadic-2.7.0-20070801
$ ./configure
$ make
$ sudo make install

mecab-pythonのインストール
$ wget http://sourceforge.net/projects/mecab/files/mecab-python/0.98/mecab-python-0.98.tar.gz
$ tar vxzf mecab-python-0.98.tar.gz
$ cd mecab-python-0.98
$ python setup.py build
$ su
# python setup.py install

Pythonでの確認 import MeCabでエラーが出ます
$ python
Python 2.4.3 (#1, May  5 2011, 16:39:10)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import MeCab
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "MeCab.py", line 25, in <module>
    _MeCab = swig_import_helper()
  File "MeCab.py", line 17, in swig_import_helper
    import _MeCab
ImportError: libmecab.so.1: cannot open shared object file: No such file or directory

共有モジュールを認識してないので、認識させます
$ sudo vi /etc/ld.so.conf
/usr/local/lib を追加
$ sudo /sbin/ldconfig

再度pythonでの確認
$ python
Python 2.4.3 (#1, May  5 2011, 16:39:10)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-50)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import MeCab
>>> m = MeCab.Tagger()
>>> print m.parse("また企業公式ページの「いいね!」を押したことがある人に、ページを見た後その企業に対して何かアクションをとったかどうかを聞いたところ")
また    接続詞,*,*,*,*,*,また,マタ,マタ
企業    名詞,一般,*,*,*,*,企業,キギョウ,キギョー
公式    名詞,形容動詞語幹,*,*,*,*,公式,コウシキ,コーシキ
ページ  名詞,一般,*,*,*,*,ページ,ページ,ページ
の      助詞,連体化,*,*,*,*,の,ノ,ノ
「      記号,括弧開,*,*,*,*,「,「,「
いい    形容詞,自立,*,*,形容詞・イイ,基本形,いい,イイ,イイ
ね      助詞,終助詞,*,*,*,*,ね,ネ,ネ
!      記号,一般,*,*,*,*,!,!,!
」      記号,括弧閉,*,*,*,*,」,」,」
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
押し    動詞,自立,*,*,五段・サ行,連用形,押す,オシ,オシ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
こと    名詞,非自立,一般,*,*,*,こと,コト,コト
が      助詞,格助詞,一般,*,*,*,が,ガ,ガ
ある    動詞,自立,*,*,五段・ラ行,基本形,ある,アル,アル
人      名詞,一般,*,*,*,*,人,ヒト,ヒト
に      助詞,格助詞,一般,*,*,*,に,ニ,ニ
、      記号,読点,*,*,*,*,、,、,、
ページ  名詞,一般,*,*,*,*,ページ,ページ,ページ
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
見      動詞,自立,*,*,一段,連用形,見る,ミ,ミ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
後      名詞,非自立,副詞可能,*,*,*,後,ノチ,ノチ
その    連体詞,*,*,*,*,*,その,ソノ,ソノ
企業    名詞,一般,*,*,*,*,企業,キギョウ,キギョー
に対して        助詞,格助詞,連語,*,*,*,に対して,ニタイシテ,ニタイシテ
何      名詞,代名詞,一般,*,*,*,何,ナニ,ナニ
か      助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ
アクション      名詞,一般,*,*,*,*,アクション,アクション,アクション
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
とっ    動詞,自立,*,*,五段・ラ行,連用タ接続,とる,トッ,トッ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
か      助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ
どう    副詞,助詞類接続,*,*,*,*,どう,ドウ,ドー
か      助詞,副助詞/並立助詞/終助詞,*,*,*,*,か,カ,カ
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
聞い    動詞,自立,*,*,五段・カ行イ音便,連用タ接続,聞く,キイ,キイ
た      助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
ところ  名詞,非自立,副詞可能,*,*,*,ところ,トコロ,トコロ
EOS

形態素解析が出来ました。

人気の投稿 (過去 30 日間)