FrontPage

2009/02/01からのアクセス回数 6655

はじめに

集合知の3章(一部欠損)をGoogleのブック検索 から閲覧することができます。

また、なぜか原書のPDF がアップされています。

オリジナルのソースは、原書著者TobesのページからPCI_Code.zipと してダウンロードできます。

日本語の分かち書き

ブロガーのフィードの単語を処理するには、日本語の形態素解析を行う必要があり、 まずはchasenを使うことにします。

chasenのインストール

chasenは、MacPortを使って

$ sudo port install chasen

でインストールしました。

python_chasenで、Shift_JISと想定しているため、/opt/local/etc/chasenrcをchasenrc-Shift_JISの内容で 上書きします。

$ cd /opt/local/etc
$ cp chasenrc-Shift_JIS chasenrc

chasenの起動オプション

  • chasen -i s

を指定します。*1

動作確認のため、1.txtというファイル(文字コードはShift_JIS)に

オリジナルのソースは、原書著者TobesのページからPCI_Code.zipと してダウンロードできます。

を入れ、chasenを実行

$ chasen -i s <1.txt >1.out

とすると1.outには、以下のような出力がでます。

オリジナル	オリジナル	オリジナル	名詞-一般		
の	ノ	の	助詞-連体化		
ソース	ソース	ソース	名詞-一般		
は	ハ	は	助詞-係助詞		
、	、	、	記号-読点		
原書	ゲンショ	原書	名詞-一般		
著者	チョシャ	著者	名詞-一般		
T	ティー	T	記号-アルファベット		
o	オー	o	記号-アルファベット		
... 途中省略 ...		
でき	デキ	できる	動詞-自立	一段	連用形
ます	マス	ます	助動詞	特殊・マス	基本形
。	。	。	記号-句点		
EOS

画面に表示するには、nkfでシステムの文字コードに変換します。

  • Leopardでは、UTF-8なので、nkf -w
  • Tigerでは、Shift_JISなので、nkf -s

を指定します。

$ chasen -i s <1.txt | nkf -w

python_chasenのインストール

python_chasen-0.2を使ってPythonからchasenを使います。ダウンロードして、~/localに展開します。

$ cd local
$ tar xzvf python_chasen-0.2.tar.gz
$ cd python_chasen

Tigetでは、-i sオプションが必要なので、chasen.cを変更します。52行を

char *opt[] = { "chasen", "-i", "s", NULL};

とします。

次に、以下の手順でbuild, installをします。

$ python setup.py build_ext --include-dirs=/opt/local/include --library-dirs=/opt/local/lib/
$ sudo python setup.py install

分かち書き処理(split.py)

準備ができたので、分かち書き処理を行うsplit.pyを作成します。 日本語の処理をスムーズに行うために以下のPythonスクリプトはすべてUTF-8でencodeされたファイルに記述し、先頭に以下のコードを追加します。

# -*- coding: utf-8 -*-
import japanese

japanese.pyは、

import sys
import codecs
# if you use the jython, comment out next line.
sys.stdout = codecs.getwriter('utf_8')(sys.stdout)

分かち書き処理では、

  • 形容詞、形容動詞、副詞、連体詞、名詞、動詞、未知語 のオリジナル形を単語とするようにします。

split.pyは、以下のようになります。

# -*- coding: utf-8 -*-
import japanese
import re
from chasen import sparse

def split(txt):
    text = sparse(txt.encode('shift_jis', 'replace')).decode('shift_jis', 'replace')
    ret = []
    lines = text.splitlines()
    parts = [u'^形容詞.*', u'^形容動詞.*', u'^副詞.*', u'^連体詞.*', u'^名詞.*', u'^動詞.*', u'^未知語.*']
    for line in lines:
        words = line.split('\t')
        if len(words) >= 4:
           if len(words[2]) > 0:
               surface = words[2]
           else:
               surface = words[0] 
           feature = words[3]
           for part in parts:
                pat = re.compile(part)
                if pat.match(feature):
                    ret.append(surface)     
    return ret

# テスト用のコード
txt = 'オリジナルのソースは、原書著者TobesのページからPCI_Code.zipと してダウンロードできます。'
for word in split(txt):
    print word

chasenのsparseに渡すときに、コードをshift_jisにencodeし、戻り値は、shift_jisからdecodeとして処理します。

未知語の場合、オリジナル形がないので、surfaceは単語そのものとしました。

テスト用のコードを実行すると以下の出力がでます。

オリジナル
ソース
原書
著者
ページ
から
する
ダウンロード
できる

英語の単語がすべて消えていることにお気づきでしょうか。 これは、chasenを使った場合の欠点ですが、後述する方法にこの問題を回避しました。

フィードを探す

ブログのフィードとして、多岐にわたる有名人のブログを見つけるのに苦労しました。 有名人のブログ一覧から有名人の フィードを使わせてもらいました。

単語切りの修正

getwordは、オリジナルのままでは、日本語を処理できないので、以下のように修正しました。

# -*- coding: utf-8 -*-
import japanese
import feedparser
import re
from split import split

def getwords(html):
    ret = []
    txt=re.compile(r'<[^>]+>').sub('',html)
    # Split words by all non-alpha characters
    words=re.compile(r'[^A-Z^a-z]+').split(txt)
    ret = [word.lower() for word in words if word!='']
    txt = re.compile(r'[A-Za-z0-9,;:.!@#$%^&*()+|~/?]+').sub('', txt)
    return ret + split(txt)
  • 最初に英語の単語のみを切り出し、
  • 日本語の単語を切り出したリストを追加

します。

これに、getwordcounts, feedlistの処理、 wordlistの処理を追加し、test_ch3-1.pyとしました。

以下に「フィードの単語を数える」に使用したファイルをリストアップします。

フィード中の単語集計結果

test_ch3-1.pyの結果には、1カ所問題があります。 原因は定かではありませんが、先頭にフィードタイトルが空文字のページがあるのです。 これを除いたファイルをfileblogdata1.txtとして使用します。

デンドログラムを描く

次にデンドログラムを表示する部分ですが、ここも日本語の文字化けが発生しました。

そこで、以下の処理を先頭に追加します。

# -*- coding: utf-8 -*-
import japanese
from PIL import Image,ImageDraw,ImageFont

font = ImageFont.truetype('/Users/take/Library/Fonts/MS Mincho.ttf', 14)

これで、日本語を処理するfontがセットされますので、drawnodeのテキスト表示を 以下のように修正します。

  • PILは、UTF-8の日本語を処理できないので、unicodeに変換します。
  • draw.textにfont=fontを渡して呼び出します。
    # If this is an endpoint, draw the item label
    utxt = unicode(labels[clust.id],'utf-8')
    draw.text((x+5,y-7),utxt,(0,0,0),font=font)

また、私の環境の問題でjpegで画像を保存できなかったので、PNGで処理するように変更 しました。

最終のソースは、filetest_ch3-2.pyです。

描画結果

作成されたデンドグラムは、以下の通りです。*2

blogclust_small.jpg

意図したわけではありませんが、お堅いページが

お堅いページ.jpg

とアイドル系のページ

アイドル系.jpg

に別れています。うまくいったのかと思ったら、アイドル系は同じサイトのブログなので、「著作権保護のため、記事の一部のみ表示されております。」が強調されているみたです。残念!

コメント

この記事は、

選択肢 投票
おもしろかった 4  
そうでもない 0  
わかりずらい 0  

皆様のご意見、ご希望をお待ちしております。

  • chasenの文字コードは、/opt/local/etc/chasenrcで指定することを追記した。 -- 竹本 浩? 2009-03-25 (水) 17:38:47

(Input image string)


*1 Tigerでは、実行結果が文字化けで表示されます
*2 オリジナルサイズは、blogclust.jpgです。

添付ファイル: fileアイドル系.jpg 589件 [詳細] fileお堅いページ.jpg 593件 [詳細] fileblogclust_small.jpg 708件 [詳細] fileblogclust.jpg 310件 [詳細] filetest_ch3-2.py 837件 [詳細] fileblogdata1.txt 631件 [詳細] filefeedlist.txt 1307件 [詳細] filetest_ch3-1.py 667件 [詳細] filesplit.py 628件 [詳細] filejapanese.py 615件 [詳細]

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2016-02-10 (水) 22:19:15 (409d)
SmartDoc