ふにゃるんv2

もとは、http://d.hatena.ne.jp/Wacky/

habu(Plagger for Python?)を使ってみた

え〜、すんません。
今回は、ネタがネタだけに、取り扱い注意ください。(特に最後の方)


実は、本音でやりたかったのは、

  • 自分は、いつもRSSを使って、色んな興味のある箇所をチェックしてます。(それで、Plaggerも使ってます)
  • けど、前々から気に食わなかった事の一つに、「英文が まともに読めないので、英語のRSSをチェックできない」ってのがありました。
  • 機械翻訳サービスとRSSデータを組み合わせたら、英語のRSSもチェックできるのになぁ。
  • PlaggerPerlで出来ているんで、よく判らない。なので、勉強がてらhabuさんを使ってみた。

という事です。


で、最初に結論から言いますと、

  • 英文RSS機械翻訳和文RSSは出来ます。
  • けど、どうみてもDOM行為スレスレです。なので、今回のネタは、サンプルとして見てください。
  • 将来、どこかのRSSフィードをしてくれる会社と機械翻訳サイトが提携して、英語サイトに対して英和データをキャッシュ&RSS配布するサービスが登場するのを、絶望しながら期待しましょう。
    「この翻訳文は、xxxの技術を使っています」ってな感じで広告してもらって…のは、虫が良すぎるかなぁ。
  • あるいは、カスタマイズできる、オフラインな機械翻訳ソフトを使いましょう。

という事です。

habuって何だ?

一言で言うと、Plagger for Pythonって感じです。

開発は、Days of Lirisさんです。


Windows上にPlaggerやhabuを入れて動かしてみての感想は、

  • Plaggerは高機能。けど、アップデート怖いっす。すごい数のライブラリを入れないといけないんですよね。
    (まぁ、普段Perlを使ってないんで、問題が起きた時、どう対処すりゃいいか判んないのが大きいんですけど)
  • habuは基本を押さえた感じ。けど、ライブラリの数が少ないので、そんなにアップデートは怖くない。

です。

habuをインストールして使ってみる

インストールと使い方は、上に挙げたMYCOMWikiの記事で十分です。


私の場合は、Subversionを使って、コードをダウンロードし、

$ svn checkout http://svn.sourceforge.jp/svnroot/pyhabu/trunk habu

ライブラリをポチポチダウンロードしては、動作させてみてました。


動かした際、何のライブラリが足りないか、エラーメッセージが出るので、上記記事で紹介のあるライブラリのURLからゲットすれば良いです。

F:\Wacky\Test\python\habu\habu>python runhabu.py
Traceback (most recent call last):
  File "runhabu.py", line 1, in ?
    from twisted.internet import reactor, defer
ImportError: No module named twisted.internet ← Twistedが足りないって言ってる

Windowsで動かす場合は、配布されているのが、セットアップ形式のexeタイプばっかりなので、ダウンロードしてダブルクリック&インストールを繰り返せばOKです。
SQLObjectだけは、easy_installを使いますが、それもWeb siteにインストール方法が事例と一緒に掲載されているので簡単です。


実行はとにかく、habuフォルダ上でコマンドプロンプトを起動して、"python runhabu.py"すれば良いです。
うまく行けば、以下のように出力され、

F:\Wacky\Test\python\habu\habu>python runhabu.py
2008/01/01 16:07 +0900 [-] Log opened.
2008/01/01 16:07 +0900 [-] Started habu with Task Mode
2008/01/01 16:07 +0900 [-] habu.webutils.getPage : http://dev.ariel-networks.com
/Members/blog_update/RSS
2008/01/01 16:07 +0900 [-] Starting factory <HTTPClientFactory: http://dev.ariel
-networks.com/Members/blog_update/RSS>
2008/01/01 16:07 +0900 [-] habu.webutils.getPage : http://www.liris.org/blog/RSS

2008/01/01 16:07 +0900 [-] Starting factory <HTTPClientFactory: http://www.liris
.org/blog/RSS>
2008/01/01 16:07 +0900 [HTTPPageGetter,client] Stopping factory <HTTPClientFacto
ry: http://www.liris.org/blog/RSS>
2008/01/01 16:07 +0900 [HTTPPageGetter,client] Thread Joined
2008/01/01 16:07 +0900 [-] Stopping reactor
2008/01/01 16:07 +0900 [HTTPPageGetter,client] Stopping factory <HTTPClientFacto
ry: http://dev.ariel-networks.com/Members/blog_update/RSS>
2008/01/01 16:07 +0900 [-] Main loop terminated.

同じフォルダに、"out.rss"ファイルが出来上がります。

カスタマイズする

実は、先ほどの"python runhabu.py"というのは、"python runhabu.py habu.cfg"しているのと同じでして、habuは、"habu.cfg"に記述されている設定内容を読み込んで動いていたんです。
なので、オリジナルな設定ファイル、例えば"test.cfg"を作って動かしたいなら、"python runhabu.py test.cfg"とすれば良いです。

設定ファイルの記述方法は、Wikiページに記述されているので、それを参考にすれば良いです。
Plaggerで記述した事があるなら、そんなに難しくありません。

実は、よく理解してないのが、pipelineセクションの説明にある、"一つのプロセス内で複数の加工方法を同時並行で処理できます"って説明でして、これってスレッドを叩き起こして、「データ」を「指定された加工方法」順に繋いでいるってイメージかな?と思ってます。


プラグインは、subscription / filter / publisher の3カテゴリに分かれてまして、

  • 入力 : subscription
  • 変換 : filter
  • 出力 : publisher

って捉え方でOKかな?と思います。


プラグインは、全て同じような構造になってまして、例えば何もしないプラグインは、どうも↓こんなのでOKっぽいです。

class Hoge(object):
    def __init__(self, config, environ):
        pass

    def execute(self, content):
        return content

def create(config, environ):
    return Hoge(config, environ)


プラグインを作る場合、Pythonデバッガ(pdb)モジュールを突っ込んで、一旦動作を止めて内部の動きを観測するのが、理解の早道だと思います。
例えば、↓こんな風に。

import pdb   # 追加

class Hoge(object):
    def __init__(self, config, environ):
        pass

    def execute(self, content):
        pdb.set_trace()   # 追加
        return content

def create(config, environ):
    return Hoge(config, environ)

実行すると、"pdb.set_trace()"の箇所で停止するので、内部を観測すれば良いでしょう。
以下は、execute呼び出しで一旦停止させ、content引数の内部情報を観測している様子です。

F:\Wacky\Test\python\habu\habu>python runhabu.py test2.cfg
2008/01/02 18:02 +0900 [-] Log opened.
2008/01/02 18:02 +0900 [-] loading modules...
2008/01/02 18:02 +0900 [-] done to preload module.
2008/01/02 18:02 +0900 [-] Started habu with Task Mode
2008/01/02 18:02 +0900 [-] Start Line : rss_fetcher
2008/01/02 18:02 +0900 [-] Remaining Context Num : 2
2008/01/02 18:02 +0900 [-] Get executeCallback : rss_fetcher
2008/01/02 18:02 +0900 [-] Event Fired : 3
2008/01/02 18:02 +0900 [-] remaining context num : 1
2008/01/02 18:02 +0900 [-] Remaining Context Num : 2
2008/01/02 18:02 +0900 [-] > f:\wacky\test\python\habu\habu\habu\filter\hoge.py(
9)execute()
2008/01/02 18:02 +0900 [-] -> return content
dir(content)
2008/01/02 18:04 +0900 [-] (Pdb) ['__class__', '__cmp__', '__contains__', '__del
attr__', '__delitem__', '__dict__', '__doc__', '__eq__', '__ge__', '__getattr__'
, '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__
', '__le__', '__len__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__
', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__slotnames__', '
__str__', '__weakref__', 'clear', 'copy', 'fromkeys', 'get', 'has_key', 'items',
 'iteritems', 'iterkeys', 'itervalues', 'keymap', 'keys', 'pop', 'popitem', 'set
default', 'update', 'values']
content.keys()
2008/01/02 18:04 +0900 [-] (Pdb) ['feed', 'encoding', 'bozo', 'version', 'namesp
aces', 'entries']
content["entries"].keys()
2008/01/02 18:04 +0900 [-] (Pdb) *** AttributeError: 'list' object has no attrib
ute 'keys'
len(content["entries"])
2008/01/02 18:05 +0900 [-] (Pdb) 25
content["entries"][0].keys()
2008/01/02 18:05 +0900 [-] (Pdb) ['updated', 'subtitle', 'updated_parsed', 'publ
ished_parsed', 'title', 'feedburner_origlink', 'author', 'links', 'content', 'ti
tle_detail', 'link', 'published', 'author_detail', 'id']
content["entries"][0]["title"]
2008/01/02 18:05 +0900 [-] (Pdb) u'TotT: Avoiding friend Twister in C++'

構造を観測すると判りますが、連想配列とリストの組み合わせで出来ています。
これなら、プラグインを作るのも、結構簡単ぽいです。

機械翻訳プラグインを使って、英文RSS和文変換する

コードは、勝手ながら、以下に投稿させてもらいました。
(Days of Lirisさん、勝手に使わさせてもらいました。済みません)


内容としては、trans2text.pyプラグインから、MachineTrans.pyモジュールを読み込み、英文データを機械翻訳にかけ、和文データを取得して、テキストファイルに落とす代物です。
まぁ、詳細は、投稿先を読んでください。


機械翻訳するMachineTrans.pyモジュールは、以下のように動きます。

  1. MachineTransクラスを生成する(引数use_siteに、文字列を渡すと、どこの機械翻訳を使うか指定できる)
  2. get_transメソッドに、英文データを渡すと、機械翻訳サイトに行って、和文データを受け取り返す


機械翻訳サイトでのデータの受け渡しには、SleipnirのCOMインタフェースを制御しています。
IEのCOMインタフェースより、ドキュメントの読み取り完了の判定が楽だったのと、セキュリティ制御が楽だったのが、その理由です。OnAmbientPropertyを操作して云々なんて、面倒で面倒で。
コードはActiveX(COM)&Pythonパワー全開なので、159行程度です。無駄な部分多いですが、オッpy初心者って事で勘弁して下さい。

まとめ

恒例のまとめ〜。

  • habuは、基本がまとまっており、インストール&使用が簡単です。
  • プラグイン開発も、見ての通り、簡単に作れます。
  • 機械翻訳プラグインは、サンプルとしてのみ参照するだけにして下さい。お願いします。