2009年7月15日

Pythonistaのための2chライブラリ"twopy"


"Beautiful Kuwait 2" by creativesam

概要

さて、実は以前からちょっと2chの文章を利用して、いろいろ弄くることができないかなぁとは思っていたんですが、残念な事に2ch用のpythonライブラリなんてマニアックなものは作っている人は誰もいない。
それじゃあ自分でなんとかしようの精神で作ってみようと。正直使う人が居るのかどうかは甚だ疑問なライブラリですが、損するわけじゃないので一応公開してみます。

というわけで、Pythonistaのための2chライブラリ"twopy"をリリースしました。
現在のところ単純なスレッド一覧の取得、スレッド上のコメント取得、コメント書き込みや新規スレッド機能に対応しておりますが、まだ完全に動作確認しているわけではないので使用は自己責任で。ちなみにライセンスはMITライセンスなんで、比較的自由に扱えると思います。改良はこれから始まる期末テストに飽きたらやると思います。

インストール方法

インストールに必要な環境は以下の通りです。
Python 2.5 or higher
2.6.2での環境で動作を確認。外部ライブラリに依存していないので、もしかしたらそれより前のヴァージョンでも動作するかもしれません。

インストール方法はCodeReposに上げておきますので、

$svn checkout http://coderepos.org/share/browser/lang/python/twopy/trunk

なりなんなりでチェックアウトしてください。

簡単な使い方

スレッド一覧の取得
import twopy
b = twopy.Board("http://takeshima.2ch.net/news4vip/")
b.retrieve()

スレッドごとのタイトル、レス数、速度(res/h)を取得することができます。
for t in b:
print u"%s (%i) %.4f" % (t.title, t.res, t.velocity)

配列のように呼び出すことも可能です。
print b[0].title
print b[0].since


スレッドの内容の取得
t = b[0]
t.retrieve()

で一番上にあるスレッドの内容を取得します。
t = twopy.Thread(b, "1247375844.dat")
t = twopy.Thread.initWithUrl("http://takeshima.2ch.net/test/read.cgi/news4vip/1247375844/")

として、datファイルあるいはURLから直接初期化することも可能です。

コメントを出力するには以下のようにループさせます。また、特定のコメントのみを取り出すこともできます。
for c in t: print c.render()
print t[1].render()

ただし、その場合の引数は実際のレス番号を指定する必要があります(0から始まるわけではない)。

コメントの抽出
特定のコメントのURLやレスポンスを抜き出すことができます。
for c in t: print c.extractResponses(returnType="comment")
for c in t: print c.extractUrls()


コメントの書き込み
特定のスレッドに対して、コメントを書き込むことができます。

t.post(name=u"", mailaddr=u"", message=u"")

ただし、2ch側の仕様により必ずしも書き込まれるとは限らず、確認が求められる場合がありますので、実際には以下のようにします。
r = t.post(name=u"", mailaddr=u"", message=u"")
if r[0] == twopy.STATUS_COOKIE: t.post(name=u"", mailaddr=u"", message=u"", hidden=r[2])

すべての確認作業を自動的に行うメソッドも存在します。

t.autopost(name=u"", mailaddr=u"", message=u"")

ただし、上2つのコードは2ch側の確認をユーザに見せることなく書き込みを行っていますので、実際にはユーザーに文章を見せてから、同意を行なわせる必要があるでしょう。

他にもスレッド作成機能などのいろいろ細々したのもありますが、それはソースコード見ればだいたい理解できると思います。行数そんな多くないですし。
もし正常に動かないなどのバグがありましたらご連絡お願いします。暇があれば対処したいと思います。それでは。

2009年7月14日

ヤスオクと人間心理、上手い商売

新感覚オークション「ヤスオク」の仕組み - いぬビーム
http://d.hatena.ne.jp/kusigahama/20090713/1247446523

とりあえず何も読まずに開いて、どういうサイトなのか考えてみてください。

ヤスオク

内容は上の記事を読んでみれば分かるとして、なかなか上手い商売を考えつくものだなぁと思います。きな臭いとか、実際にやってみたいかどうかは別として。

さて、記事では胴元にとても有利なギャンブルとあります。それじゃあどれくらい有利なギャンブルであるのか、ちょっと確かめてみることにします。

まず、初めのオークション開始価格をS0、市場価格(この場合ですとamazonの価格ですね)をSm、入札単位金額をα、入札回数をn、入札手数料をpと定義すると、主催側の儲けは以下のように定式化できます。

Slastはオークションでの最終価格です。

逆に主催側の損失はSmだけです。これより、主催側の儲けと損失の和がちょうど0になるような入札回数n~は以下のような方程式を解けば算出できます。

これよりn~が求まったので、主催者が損しない最低限のラインである入札金額S~は以下のように求まります。

今回の場合ですとα=15、p=75、S0=0であるので、S~は

以上より、大体市場価格の17%くらいの価格を越えれば主催側は特をするわけです。言い換えれば83%オフの値段より落札価格が越えれば元がとれると。

このシステムの秀逸なところは、人間の価値関数を上手く利用している点にあります。プロスペクト理論によると、人間は損をすることを極端に嫌がります。そして殆どの場合、そのまま損失を認める選択肢を選ぶよりは、多少のリスクを背負ってでも損失を回避しようとする選択肢を選ぶわけです。今回の場合ですと15円損失して入札するというリスクを背負うわけですね。

それじゃあどうやって主催者を打ち負かせればいいのかというと実は簡単で、裏で話し合って誰も争うことなく次々と落札すればいいんです。いわゆる談合です。
ざっと利用規約を見た感じですと談合しないでくださいとは書いてありませんし、誰かやってくれないでしょうか(笑)

追記
typo ×ヤスログ ○ヤスオク
他、表記をより適切なものに修正致しました。

2009年6月17日

Ubuntu環境でのOpenCVとffmpeg


"Chris Powell Ubuntu Tattoo" by Myles Braithwaite
(全然関係ないですが、わざわざ刺青まで彫るなんてよっぽどUbuntuが好きなんですねー)

Ubuntu環境でOpenCVという、画像処理用ライブラリをインストールする際にすんごく苦労しましたので、一応書いておこうと思います。

実は、OpenCVは通常のレポジトリからapt-getでインストールすることができるのですが、それだとビデオ機能が追加されておらず、このままではビデオ機能を使うことが出来ないのです。そのためソースコードを引っ張ってきてconfigure->make->make installの流れでインストールしなければならないのかーめんどくさいなーと思って調べてみたら、どうやらそれ以前にffmpegを追加しなければならないことが判明しまして、しょうがなくffmpegを野良ビルドした後にさあインストールだという感じでmakeしたら、どうしてもcvcap_ffmpeg.cppでエラーが出て止まってしまう。悔しいのでソースコードを書き換えるなりパッチ当てるなりで努力するも、悉くエラーが出て止まってしまうので、さてどうしようか諦めようかとか思っていた最中に、この記事を発見。

Getting video i/o working with opencv and Ubuntu Jaunty (9.04)

要は

$ sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com cafc44ee7f39098ce6ec229cca70e6a9087475a0

で鍵を入手して、
/etc/apt/sources.listに

deb http://ppa.launchpad.net/gijzelaar/opencv/ubuntu jaunty main

を追記。リポジトリを追加してインストールするだけでビデオ機能が追加されたOpenCVがインストールできますよという話なのでした(*1)。同じ環境で困っている方は試しにやってみてはいかがでしょうか。

それにしても…

I was disappointed, crying, screaming, running around angry and banging my head against the wall when the video i/o functionality stopped working when I updated to the latest Ubuntu release (Jaunty).
本当に自分もそんな気分になりましたよ。本当にOpenCVのビルドには多くの人が苦労されているようで…

余談

一応そんなわけで解決はしたのですが、自分の環境では

#include "highgui.h"
CvCapture *src;
src = cvCreateFileCapture("file.avi");

のようなコードを記述しますと"test.avi"が読み込まれずsrcがNULLになってしまいます。でもなぜかPython上ですと

>>> from opencv import highgui
>>> src = highgui.cvCreateFileCapture("file.avi")
>>> src
<Swig Object of type 'CvCapture *' at 0x9904420>

となって、正常に読み込まれているんですよねー…どうせ遊びにしか使いませんし、python+ctypesの組み合わせでもいいかなとか考えるようになってきましたよ。

*1) 今までのことはすべて無視して大丈夫です。みたいな

2009年5月14日

東北大院生の自殺は決して対岸の火事じゃない


"Resume the suicide" by gfbpublez

東北大大学院生が自殺…博士論文、2年連続受け取り拒否され

東北大の理学研究科って…まんまうちの学部生が行くとこじゃないですか…
まさかこのまま順調に進めば進学するであろう大学院で自殺が起こるなんて。流石にショックです。

事件の内容はニュースに書いてある以上のことは知らないので、自分がいるキャンパスでの様子を書いていきますね。

まず東北大学理学部のキャンパス(青葉山キャンパス)っていうのは人里離れた山の上にあって、基本的に学生や大学院生はバスやバイクなどで通学します。5分くらい歩けば工学部のキャンパスに着くんですが、工学部に行くのはせいぜい図書館で珍しい本を借りることくらいしかないので殆ど行くことはありません。

そんな環境ですので、必然的に理学部の人間は山の上という隔離された空間の中で勉強にいそしむことになるわけです。大学院生でしたら泊まりがけの研究とかやることもあると思いますので、より環境的には隔離された状況なのかもしれません。自分はそれが嫌なので授業が終わったらさっさと山を降りて部活だのサークルだのやるようにしています。

で、今日のお昼休みでのこと。理学部の生協はいつものように理学部の学生と大学院生でごった返していたわけですが、テレビの前で学生がみんな微妙な表情で立ち止まっているんです。こんな状況は今まで見たことがなかったので、どうしたんだろうと思い自分もテレビの画面を覗き込んでみると、NHKニュースのテロップには東北大学院生自殺の文字が。
自分がこのショッキングなニュースを知ったのはこのときでした。殆どの学生もそうだと思います。風の噂ほども聞いたことがなかったので、もしかしたらその研究所には箝口令がしかれていたかもしれません。

各自テレビを見ながらいろんなを言葉を口走っています。
「勉強一筋の真面目ちゃんだったからこんなことで死にたくなるんじゃない?」とか、
「いや、自分も2年連続で受け取り拒否されたら死にたくなるかもしれない」
とかです。そのニュースが終わった後、学生たちは散らばって各自のテーブルで議論を飛ばしていました。

これは自分の異見なのですが、やはり理学部の研究室という非常に閉鎖的な環境だったからこそ起こった事件なのかなと思います。せめて他に論文を審査してくれる教授がいたのなら。合わなければ研究室を変えるという選択肢があったのなら。アカハラを行うクソ准教授を訴える場所があったのなら。こういう事態は起こらなかったかもしれません。

あーーーそれにしてもこの先どうしようーー理学部は就職先もないしーーーお先真っ暗だーーーー

2009年5月6日

はじめてのミシェル・ゴンドリー(Michel Gondry)


久しぶりに映像関係の話題をば。

映像、特にPV関係が好きな方ならば、ミシェル・ゴンドリー(Michel Gondry)という名前を知っていると思います。フランスの映像作家で、世界的に有名なプロモーション・ビデオを多数発表している方ですね。

プロモーション・ビデオっていうのは大体尺が3〜4分と短いため、必然的に独創的なアイデアとか技術力をふんだんに生かした映像を作らなければなりません。それでなんですけど、このプロモーション・ビデオというのは以下の4つのカテゴリに分けることができると個人的には思っています。

  1. 作り方も分かるし、アイデアも容易に思いつきそうなやつ
  2. アイデアはなんとかなりそうだが、作り方がどうしてもわからないやつ
  3. 作り方は容易だが、逆立ちして考えても思いつきもしないやつ
  4. 作り方も、発想も全く思いつきすらしないやつ
もちろん下に行けば行くほどすごいPVです。
大体のPV(特に日本のPV)はこの1のカテゴリに当てはまる場合が多いんですが、ミシェル・ゴンドリーの作品のほとんどすべては3か4に当てはまります。常軌を逸しすぎている。たぶん自分は薬でもキメないかぎり一生かかっても思いつきすらしない気がします。
今回はそんな不思議PVを製作しているミシェル・ゴンドリー作品の紹介です。


まずこれ。すごいPVを挙げろと言われれば秒速でこのPVが挙げられるほど有名。これに至ってはどうやって作っているのかまず分からないし、撮影も相当大変そうです。CGとアイデアの見事な融合ですね。


おなじみケミカル・ブラザーズ。ミシェル・ゴンドリーが何者か分からなくてもこのPVは知っているという人はかなり多いはず。新幹線の車窓を見ると毎回このPVを思い出します。


1999年だから10年前のはずなんですけど、現在でも十分通用するほどスタイリッシュなPV。こいつ本当に薬キメてるんじゃないかと疑いたくなるようなキ○ガイ作品です(褒め言葉)

上の3つは超がつくほど有名なので、まだ見ていない方は見ても損はしないと思います。以下は個人的に好きなミシェル・ゴンドリー作品です。といっても基本的にミシェル・ゴンドリーは外れがないので、何見ても面白いです。いやホントに。


技術的にはそこまで大変そうではないですが、まず思いつかないです。シンプソンズのアニメでパロディされたほど有名な作品。


CG技術がなくてもアイデアがあれば十分面白い作品は作れるという好例。1997年の作品です。


きがくるっとる。一体これを作成するのにどれくらいの時間がかかってるんでしょうか…
(実際はCGも利用しているらしいですけれど)

2009年4月25日

大学3年の理系が行った、Ubuntu 9.04 Jaunty Jackalopeのアップグレードとメンテナンス



4月から大学3年生になりました。授業の内容が本格的になってきて、しかも事故によってまだ取得できていない前のセメスターの単位があったりとかで、結構大変です。

さて、4/23にUbuntuの新しいヴァージョン9.04 Jaunty Jackalope(軽快なツノウサギ)が発表され、その次の日には日本語版のRemix CDがダウンロードできるようになりましたので、いままで使っていた8.10から9.04にアップグレードすることにしました。その際に、8.10でいろいろアプリケーションやライブラリをインストールしたことによる不都合を起こしていたので、心機一転して一旦パーティションを初期化した後にクリーンインストールを行うという手法をとりました。
9.04が発表されたときは結構盛り上がるかなと思ったんですが、あんまりそのことをブログで書いている人が少なかったので、今回は自分が行ったアップデート作業を書いていきたいと思います。

Ubuntuの環境整理

1.VGAドライバのインストール
これは自動的にUbuntu側が認識してインストールを促してくれるので、特に悩む必要はないです。インストールしたら再起動して、ドライバが正常にインストールされているかを確認します。

2.アップデート・マネージャでアップデートのインストール
今回の場合、9.04の発表直後だったので何もありませんでしたが、通常はここでアップデートを行ってシステムの内容を最新に保ちます。

3.「日本語環境セットアップ・ヘルパ」を使用して日本語環境を整える
インストールしたいソフトを選択して、インストールを行います。Flashのプラグイン、Adobe Reader日本語版、IPAモナーフォントは結構お世話になるので、入れておいた方がいいかもしれません。

4.システムのフォントをIPAモナーフォントからVLゴシックに変更
3.でIPAモナーフォントをインストールするとシステムのフォントが自動的にIPAモナーフォントに変更されてしまいます。これを元のVLゴシックに戻すためにはターミナルを立ち上げて
$ sudo gedit /etc/fonts/conf.d/69-language-selector-ja-jp.conf
と入力。sans-serifとmonospaceの欄を

<edit name="family" mode="prepend" binding="strong">
<string>VL Gothic</string>
<string>IPAMonaGothic</string>
<string>IPAGothic</string>
<string>Sazanami Gothic</string>
<string>Kochi Gothic</string>
</edit>

のようにVL Gothicを先頭にもっていく。保存するとシステムのフォントとしてVLゴシックが使われるようになります。

5.システムの警告音をミュートにする
キーボードの打ち間違えでシステムのビープ音がいちいち鳴るのはとっても鬱々しいので、鳴らないように変更します。ターミナルを立ち上げて
$ sudo rmmod pcspkr
を入力。再起動後も鳴らないようにするには
$ sudo gedit /etc/modprobe.d/blacklist.conf
を入力。末尾に
blacklist pcspkr
を加えて保存します。

6.ホームフォルダの各フォルダを英語表記に直す
日本語でもいいんですが、ターミナルを使うといちいち日本語でフォルダを指定するのがめんどくさいので、英語表記に直します。ターミナル上から
$ LANG=C xdg-user-dirs-gtk-update
で英語表記に変更されます。再起動後はこの名前でいいのか聞かれるので、べつにいいよという感じのボタン(どんなんだったか忘れた)を押して英語表記のままにします。

以下の内容は各種ソフトやライブラリのインストールです。この操作はSynaptic上でも行えます。

7.各種コーデックのインストール、メディア環境を整える
各種コーデックをインストールして、メディア環境を整えます。ターミナル上から
$ sudo apt-get install ubuntu-restricted-extras
でインストールを行います。
ついでに動画鑑賞の定番であるvlcもインストール。
$ sudo apt-get install vlc
で簡単にインストールが行えます。

8.Nautilusの拡張
sudo apt-get install nautilus-gksu nautilus-open-terminal

9.日本語のLaTeX環境を整える
理系必須のLaTeX環境を整えます。「Ubuntu 8.10 Intrepid Ibex で 日本語 LaTeX 環境を整えてみよう」を参考にインストールを行います。
ついでにLaTeXのコンパイルが劇的に楽になるOMake(参考:OMake つかって LaTeX コンパイルしたら簡単すぎて身長が5cm伸びた)も同時にインストール。
$ sudo apt-get install omake
とっても簡単ですね。

10.各種計算ソフトのインストール
個人的によく使うライブラリやソフトをインストールします。
$ sudo apt-get install python-scipy python-matplotlib wxmaxima gnuplot r-base

所要時間にして約2時間。結構早く終わりました。Windowsだとあと2,3時間はかかるかもしれません。

まとめ

Ubuntuは初心者に優しいとかコマンド入力しなくてもいいとか言われていますがそれは全くの嘘で、ちょっとこみいったことをしようとすると依然としてターミナル上からの操作が必要とされます。
でも慣れればwindowsよりも保守管理がしやすいのは確か(apt-getで一括してすべてのソフトのアップグレード、インストール、アンインストールが行える)ですし、なにより理系がよく使うgnuplotやRが楽にインストールできるところがうれしいです。操作性もwindows上でインストールするよりたぶん数倍使いやすいと思うので、理系の方はUbuntuを試してみるという選択肢もありだと思います(べつにFedoraでもいいと思うけど)。

2009年4月12日

辞書と組み合わせと再帰関数


Photo by joka2000, Double-flowered Cherry Blossoms

辞書が与えられて、そのキーと値の群の中でタプルやリストを持っている値を、任意の値で組み合わせたリストを返すという処理はどう実装すべきか悩んでいました。
言葉にすると難しく聞こえますが、要は
{"a":(1,2), "b":4, "c":(3,4)}という辞書が与えられた場合、返すリストは
[{"a":1, "b":4, "c":3},
{"a":1, "b":4, "c":4},
{"a":2, "b":4, "c":3},
{"a":2, "b":4, "c":4}]
となるわけです。

通常の行列のような処理は単純にループを2回回せばいいわけですが、今回の問題の場合ループ回数は変動するわけで、単純にループを回すわけにはいかない。どうすればいいのかちょっと考えて見たら、再帰関数を使えば案外スマートに実装できそうな気がしたので、実際にやってみました。


from copy import copy

def makeKwargsList(kwargs, exceptions=[]):
"""
タプルやリストを含んだ辞書から、それらの値を含む任意の組み合わせを
すべてリストとして返します.
例:
kwargs = {"a":(1,2), "b":3, "c":(True,False), "d":(1,2)}
exceptions = "d"の場合、返される辞書のリストは、
[{"a":1, "b":3, "c":True, "d":(1,2)},
{"a":1, "b":3, "c":False, "d":(1,2)},
{"a":2, "b":3, "c":True, "d":(1,2)},
{"a":2, "b":3, "c":False, "d":(1,2)}] となります.

kwargs : タプルやリストを含んだ辞書
exceptions : 組み合わせとして出力してほしくないキーのリスト
"""
if type(kwargs) != dict: raise TypeError
# キーワードの抽出
kwdict = {}
base = {}
for (key, value) in kwargs.items():
if (type(value) == list or type(value) == tuple) and \
(key not in exceptions):
kwdict[key] = value
else: base[key] = value
# key, kw の分離
keys = kwdict.keys()
values = kwdict.values()
kwargs_list = []
__makeKw(values, [], kwargs_list)
# 結合
r = [dict(zip(base.keys() + keys, base.values() + ag)) for ag in kwargs_list]
return r

def __makeKw(kwlist=[], base=[], kwargs_list=[]):
argslist = kwlist[0]
if len(kwlist) > 1:
newKwlist = kwlist[1:]
for kw in argslist:
new_base = copy(base)
new_base.append(kw)
__makeKw(newKwlist, new_base, kwargs_list)
else:
for kw in argslist:
new_base = copy(base)
new_base.append(kw)
kwargs_list.append(new_base)

__makeKw()が再帰関数で、この場合[(1,2),(3,4)]のリストから、[[1,3], [1,4], [2,3], [2,4]]をkwargs_listに代入させていく関数となっています。

本来のプログラマがどうやってこのようなアルゴリズムを組んでいるのかは残念ながら勉強不足で分かりませんが、とりあえずきちんと動作しますし、そこまで速度が重要となるような処理ではないですので(せいぜい100〜10000程度)、べつにこれでいいかなと。

それにしても、1年前は思いつかずに挫折していたであろうアルゴリズムが実際に組めるようになってくると、ちょっと成長している感がありますね。