2009-03-09

二月に注文していた VAIO type P が土曜日にようやく届き、ちまちまセットアップ。字ちっちぇええ! どうすんだよこれ……。

とりあえず Windows PC のお約束として、プリインストールソフトのアンインストールやらアップデートやらリカバリディスクの作成やら使うソフトのインストールやらに時間がかかるので、買ってから数日間は実践投入できない。使い始めたら感想書こう。

それにしても、昨日今日と立て続けに二度も P 使っている人を喫茶店で見かけてしまった。なんか流行りもんになっとる……。そんなだと、ちょっと外で使うのが恥ずかしいな。

ローマ字 Python モジュール

まだなんもドキュメントがないけど、機能はそんなに多くない。ヘボン式、訓令式、日本式、そしてローマ字入力式のローマ字をかなに、またかなをローマ字に変換する。各方式ごとにひとつのモジュールになっているので、import romaji.hepburn などのようにして使う。Python インタプリタの -m オプションでモジュールをスクリプトとして実行すると、標準入力の文字列を変換して標準出力に吐き出すツールとして動く。

C:¥>python -m romaji.hepburn -h
Usage: hepburn.py [options]

Options:
  -h, --help            show this help message and exit
  -f FROM_ENCODING, --from-encoding=FROM_ENCODING
                        source encoding <cp932>
  -t TO_ENCODING, --to-encoding=TO_ENCODING
                        destination encoding <cp932>
  -r, --romaji          kana to romaji

C:¥>echo watashi no namae wa nakano desu. | python -m romaji.hepburn
わたし の なまえ わ なかの です.

C:¥>echo わたし の なまえ わ なかの です. | python -m romaji.hepburn -r
watashi no namae wa nakano desu.

が、ヘボン式も訓令式も長音はアクセント記号付きになるので(おとうさん → Otōsan など)、CP932 のコマンドプロンプト上では UnicodeEncodeError が起こる。-t オプションで出力エンコードを utf-8 などにして、リダイレクトで結果を見ればよい。

やってることはただの最長一致置換ですが、変換テーブルの作成がめんどくさかった。おかしなところがあったら教えてください。

2009-02-25

なにかの購入ページだか登録ページだかで、規約に同意する必要があって、規約へのリンクをクリックすると別ウインドウで規約のページが開いた。それを読んで、元のウインドウに切り替えて「同意する」というリンクをクリック。すると……

「セッションがタイムアウトしました」

……。

規約を読む人がいるとははなから思ってないらしい。21世紀ってさあ、どんどん滑稽になってきてるよね。

MeCab の Python バインディングを Windows で使う話の続き

先日、Windows で MeCab の Python バインディングを使うインストーラを作ったけど、このライブラリで、たとえば次のようなコードを書いて、test_mecab.py foo.txt のように適当なテキストファイルを食わせると、特定の行で python.exe が落ちることがある。(Windows での話で、たとえば Leopard では落ちなかった。)

# test_mecab.py

import sys
import MeCab

t = MeCab.Tagger()

for filename in sys.argv[1:]:
    for line in open(filename):
        sys.stdout.write(t.parse(line))

落ちる時はいつも同じ行で落ちる。が、その行の内容で決まるわけではないらしい(同じ内容の行でも別の場所にあるものは問題なかったりする)。C/C++ で libmecab.dll を使った同様のプログラムを書いて実行した場合は落ちない。また Python からでも、ctypes モジュールを使って libmecab.dll の C 関数を直接呼んで同様の処理をするスクリプトなら落ちない。

MeCab_wrap.cxx のどこで落ちているかまでは追いかけたけど、よくわからない。これ以上原因を探る気力もないし、ctypes モジュールを使って自分でラッパを書いたほうがいいだろうか……。

それにしても、今までよく知らなかったけど ctypes ってすごいですね。

2009-02-22

ひらがな・カタカナを扱う Python 2.x モジュール (kana-r1345.zip)

katakana(s)
文字列 s 内のひらがなをカタカナに変換。

>>> print kana.katakana(u'あいうえお')
アイウエオ
hiragana(s)
文字列 s 内のカタカナをひらがなに変換。

>>> print kana.hiragana(u'アイウエオ')
あいうえお
hankaku(s)
文字列 s 内の全角文字を半角文字に変換。

>>> print kana.hankaku(u'パンダ')
パンダ
zenkaku(s)
文字列 s 内の半角文字を全角文字に変換。

>>> print kana.zenkaku(u'パンダ')
パンダ
upper(s)
文字列 s 内の小書きのかなを非小書きのかなに変換。

>>> print kana.upper(u'キャッツアイ')
キヤツツアイ
lower(s)
文字列 s 内のかなを小書きのかなに変換。

>>> print kana.lower(u'キヤツツアイ')
キャッッァィ

(「キャッツアイ」になると思った人、残念でした!)

voiced(s)
文字列 s 内の清音かなを濁音がなに変換。

>>> print kana.voiced(u'カンタム')
ガンダム
unvoiced(s)
文字列 s 内の濁音がなを清音かなに変換。

>>> print kana.unvoiced(u'ジャイアン')
シャイアン
semivoiced(s)
文字列 s 内の清音かなを半濁音がなに変換。

>>> print kana.semivoiced(u'あさごはん')
あさごぱん
row(c)
かな文字 c の五十音表での行を返す。

>>> print kana.row(u'つ')
た
col(c)
かな文字 c の五十音表での段を返す。

>>> print kana.col(u'つ')
う
normalize(s)
かなを辞書順にソートするために文字列 s を正規化する。sort 関数の key 引数に渡して使うことを想定しています。

>>> print kana.normalize(u'インターネット')
インタアネット
>>> print kana.normalize(u'金子みすゞ')
金子みすず

バグなどあったらご報告ください。

さて、あと何か必要そうなのある?

2009-02-19

漢字かな交じりの文字列と、その読みが与えられたときに、漢字とその部分の読みがなとをプログラム上で対応させる方法の私的メモ。限定的すぎる話でごめん。

「漢字かな交じり」という文字列に対して「かんじかなまじり」という読みがなが与えられたとする。これを、

漢字
かんじ

のように、対応づけたい。楽をするために正規表現を使います。

import re

word = u'漢字かな交じり'
reading = u'かんじかなまじり'

まず、かな文字のテーブルを用意する。

kana_letters = u'あいうえおかきくけこ...'

続いて、以下のような正規表現を構築する。

rx_word = re.compile('([^%s]+|.)' % kana_letters)

これは、「かな文字以外の任意の文字の連続、またはかな1文字」を表している。この正規表現にマッチする単位で文字列を区切っていく。

L = rx_word.findall(word)

ここで L[u'漢字', u'か', u'な', u'交', u'じ', u'り'] になっている。この単位で、今度は読みがなにマッチさせる正規表現を作る。

tokens = []
for term in L:
    if term in kana_letters:
        tokens.append('(%s)' % term)
    else:
        tokens.append('(.+)')
re_reading = '^%s$' % ''.join(tokens)
rx_reading = re.compile(re_reading)

分割された文字列がかな文字であればそれをそのまま、かなでなければ '.+' のパターンを割り当てて、それを連結する。re_readingu'^(.+)(か)(な)(.+)(じ)(り)$' になっている。あとはお察しの通りこれを読みがな文字列である reading にマッチさせる。

m = rx_reading.match(reading)
if m:
    for term, term_reading in zip(L, m.groups()):
        print term, '-', term_reading

re_reading の各パターンを括弧でくくっておいたので、m.groups() でマッチ部分をリストとして取り出せる。この数は L に一致してるはずなので、zip 関数で双方をセットにしてひとつずつ取り出せる。

結果。

漢字 - かんじ
か - か
な - な
交 - ま
じ - じ
り - り

基本は以上。表記揺れとかカタカナ対応とか各漢字ごとの読みの推測などをやろうとすると他にも工夫が要るけど、骨子は同じ。

2009-01-19

いろいろお話ししたいことはあるけれども近頃あまり調子がよくないのでうまく書けない。

解説を書くのは難しい

リンクはしないけど、最近載った @IT の XHTML 解説記事がひどい。いや、記事の正確性とか、そういうのは置いといて(そっちも怪しそうだけど)、そもそもまともな日本語の文章になってない。

導入。

文書構造を表現するXHTMLタグを大まかに分類し、分類したタグをXHTMLの“要素”として、1つずつ紹介していきます。

これらの要素類はXHTMLの骨格(枠)となる部分を形成していくために使われる、XHTMLタグの記述(=マークアップ)を行ううえで基礎となる要素類です。

htmlタグが一番の外側(先祖)となり、その内側(子)に上からhead要素、body要素といった順番でマークアップされます。

html 要素。

htmlのそれぞれの要素はhtml要素を頂点とする階層構造になっています。

その中でhtml要素は最も基礎となる要素で、そのほかの要素はすべてがhtml要素の子や子孫(※)となる関係性になります。

なお、htmlファイルを作成するときにまず記述するべきタグの1つで、その直接の子(1つ内側)としてbody要素とhead要素が記述されます。

body 要素。

body要素の内側に記述された要素が、ブラウザ画面上にレンダリングされるようになります。

視覚的に確認できる部分であり、この内側にdiv要素を使ってワイヤーフレームとなるブロックをマークアップしています。

これは並びが構文上間違ってないというだけの単語の羅列だぜ。マルコフ君

こうした記事をでたらめとか意味不明とかいって叩くのは簡単だけど、それではどうしてこうなってしまったのかを考えてみる。

この記事のなにが問題かというと、ひとつはこの記事の著者が、解説とは「ある知識について、それを知らない人に、その人が知っている範囲の知識で語ること」なんだという点を理解してないという点にあると思う。「自分が知っていることを書けばそれが誰かの役に立つ記事になる」などと思っていてはまともなドキュメントにはならない。

この記事は導入に「文書構造を表現するXHTMLタグの正しいマークアップ方法のリファレンスをスタートします」と書いてある(というかこれしか書いてない)。この文は、XHTML やマークアップがどういうものかわかっている人にとってはとりたてて意味がなく、それについて知らない、つまりこの記事の対象となる人々にとっては理解できない。いってみれば「この文は日本語です」と書かれている看板のようなものだ。上に引用した文章についても同様のことがいえる(その上たちの悪いことに「要素類」とか「ワイヤーフレーム」とか、あやしい勝手用語を交ぜている)。そのことについて知らない人にとっても意味をなす言葉で語らなければいけない。

もうひとつは、読み手にとって新情報が出てくるまでの「ストーリー」が用意されていないという点。コンテキストといってもいいと思うんだけど。この記事は「リファレンス」と銘打っているけど、それはひとつには著者に解説をうまく進めるための「ストーリー作り」ができないことの「言い訳」として、そうなっているのではないかと思われるふしがある。なにかの解説記事を書いたことがある人ならだれでも、本題に持っていくまでのこの「ストーリー作り」の難しさを知っているはず。

だけどこれは重要で、教える側が教わる側の言葉で語り、なおかつ両者がストーリー(コンテキスト)を共有しているとき、はじめて教わる側にとって解説が「意味のある」ものに聞こえてくるものだと僕は思う。これができていない記事は、よくわからないまま読み進め、最後まで読んで初めて「自分が知りたいことじゃなかった」と読者が気づくような代物になってしまう。「○○について話をします。みなさんはこんなことを知っていて、こんなことをしてますよね? ではこれについてはどうですか? よくわからないんじゃないですか? ここでは今からそれについて解説したいと思いますね」というようなイントロダクションがあれば、読者はその記事が自分の求めているものかどうかがすぐにわかる。

なんか昔 WZ のマクロ入門書いた時のことを思い出す。あのときも言葉は違うけど、似たようなことを言ってたような気がする。

さてこういった記事を書く人々も今では自分より年下だ。あるいは僕も昔はこんなだったのかもしれない。どうかな。

でも文章は練習すればうまくなるからね。