ラベル Python の投稿を表示しています。 すべての投稿を表示
ラベル Python の投稿を表示しています。 すべての投稿を表示

2010年11月24日水曜日

50音別インデックスの実装

 Aozoramazonでは、作者毎に50音別の作品名インデックスを用意してあります。青空文庫には全作者を網羅した長大な50音別作品リストがありますが、Aozoramazonでは表示するリストを小分けにする必要がありました。これは、Aozoramazonを動かしているGoogle App Engineでは、1000件を超えるエントリーを一度に取り出せないと言う制限があるためです。この制限と折り合いを付けるために、全作者ではなく作者毎の50音別リストにしました。

前準備として、作者毎に作品頭文字リストを用意します。

  • 作品情報の更新時に青空文庫の図書カードを解析して作品の読みを取得する
  • 作品読みの頭文字を、作者情報の頭文字リストに追加する。リストに存在する文字なら何もしない。
こうすると、例えば菊池寛の作者情報に作品頭文字リスト「あいきくみえむおらせしたちとわかなへやさこふて」が出来上がります。並び順に意味は無いので、ソートは行いません。

表示の際の強調の有無は、CSSのclassで区別します。考え方としては、強調のclassを与えるのではなく、非強調のclassを取り除く事で相対的にリストにある文字だけが強調されて見えるようにします。一見、逆(有効な文字を強調する)でも良いように思えますが、不要な文字が普通のリンクとして見えては都合が悪いため、不要な文字にも目立たせないためのスタイル指定が必要になります。したがって、必要な文字だけ非強調のclassを取り除く方が近道です。

まず、非強調用のCSSクラス"gapCell"を指定した50音表を用意します。(gapCellという名前に深い意味はありません。元々は文字の無いセルを目立たなくするために用意したCSSクラスでした。)
各文字のセルはUTF-8をベースにしたIDで識別できるようにしておきます。

<table class="novelInitialTable"> 
       <caption>作品名インデックス</caption> 
       <tr> 
  <td class="gapCell" id="i_e38182">
  <a href="/person?authorId=83&amp;initial=%e3%81%82">あ</a>
  </td> 
  <td class="gapCell" id="i_e38184">
  <a href="/person?authorId=83&amp;initial=%e3%81%84">い</a>
  </td> 
  <td class="gapCell" id="i_e38186">
  <a href="/person?authorId=83&amp;initial=%e3%81%86">う</a>
  </td> 
  <td class="gapCell" id="i_e38188">
  <a href="/person?authorId=83&amp;initial=%e3%81%88">え</a>
  </td> 
  <td class="gapCell" id="i_e3818a">
  <a href="/person?authorId=83&amp;initial=%e3%81%8a">お</a>
  </td> 
  <td class="gapCell">&nbsp;</td> 
  <td class="gapCell" id="i_e381af">
  <a href="/person?authorId=83&amp;initial=%e3%81%af">は</a>
  </td> 
      ...

CSSの中では、非強調用のgapCellクラスを背景に対して目立たない色で定義します。

td.gapCell a:link {
    color: gray;
}
td.gapCell a:visited {
    color: gray;
}
td.gapCell a:hover {
    color: gray;
}

ページがロードされた直後に実行されるJavaScriptで、強調したい文字のgapCellクラスを取り除きます。
非強調が解除される、すなわち、非強調に対比して強調されているように見えるようになります。

$(document).ready(function(){      
      $("#i_e38182").removeClass("gapCell");      
      $("#i_e38184").removeClass("gapCell");      
      $("#i_e3818d").removeClass("gapCell");
      ...

テンプレートの中で、指定された文字に対してのみremoveClass()するJavaScriptを出力します。テンプレートを処理すると、上のようなJavaScriptソースになります。

$(document).ready(function(){
      {% for i in initialList %}
      $("#i_{{i}}").removeClass("gapCell");
      {% endfor %}

PythonのCGIでは、作品頭文字リストをテンプレートに渡します。
HTMLで表示できるように、UTF-8を16進表記にしてエスケープ文字(\x)を取り除いた文字列のリストとして渡しています。

initialList = []
if author.initialList:
    initialList = [c.encode('utf-8').encode('string-escape').replace('\\x', '') for c in author.initialList]
template_values['initialList'] = initialList

最終的に、下のような表示になります。

2010年11月11日木曜日

青空文庫の第3第4水準漢字注記をUnicodeに置き換える

 最近はWindowsもMacもJIS X 0213の第3第4水準を表示できるようなので、Aozoramazonで表示する作者名や作品名に含まれている青空文庫の注記をUnicodeに置き換えるようにしました。

で、そのために作ったPythonの変換モジュールとテーブルを置いておきます。

 コメントに書いてありますが、テーブルの元データはProject X0213からダウンロードしました。

Pythonで漢数字をアラビア数字に変換

Aozoramazonの製作過程で漢数字をアラビア数字に変換する必要が生じて作りました。


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import re

def kansuji2arabic(text):
"""漢数字からアラビア数字への変換"""

KANNUM_PATTERN = re.compile(u'(?P<kansuji>[壱一二弐三参四五六七八九十拾百千万萬億兆〇1234567890,,\d]+)')

index = 0
while index < len(text):
matched = KANNUM_PATTERN.search(text[index:])
if matched:
kansuji = matched.group('kansuji')
startindex = matched.start('kansuji') + index
endindex = matched.end('kansuji') + index
result = 0
digit = 1
numgroup = 1
kanindex = len(kansuji)
while kanindex > 0:
c = kansuji[(kanindex - 1):kanindex]
kanindex -= 1
if c == u'〇00':
digit *= 10
elif c in u'十拾':
digit = 10
elif c == u'百':
digit = 100
elif c == u'千':
digit = 1000
elif c in u'万萬':
numgroup = 10000
digit = 1
elif c in u'億':
numgroup = 10000*10000
digit = 1
elif c in u'兆':
numgroup = 10000*10000*10000
digit = 1
elif c in u',,':
pass
else:
if c in u'壱一11':
result += digit * numgroup
elif c in u'二弐22':
result += 2 * digit * numgroup
elif c in u'三参33':
result += 3 * digit * numgroup
elif c in u'四44':
result += 4 * digit * numgroup
elif c in u'五55':
result += 5 * digit * numgroup
elif c in u'六66':
result += 6 * digit * numgroup
elif c in u'七77':
result += 7 * digit * numgroup
elif c in u'八88':
result += 8 * digit * numgroup
elif c in u'九99':
result += 9 * digit * numgroup
digit *= 10
text = u'%s%d%s' % (text[:startindex], result, text[endindex:])
index = startindex + len('%d' % (result,))
else:
break
return text

 使用例


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import kan2arabic

def main():
examples = [u'平成22年度一般会計予算は92兆2292億円',
u'平成22年度一般会計予算は92兆2,292億円',
u'平成22年度一般会計予算は92兆2,292億円']
for text in examples:
print text, '->', kan2arabic.kansuji2arabic(text)

if __name__ == '__main__':
main()


出力

平成22年度一般会計予算は92兆2292億円 -> 平成22年度1般会計予算は92229200000000円
平成22年度一般会計予算は92兆2,292億円 -> 平成22年度1般会計予算は92229200000000円
平成22年度一般会計予算は92兆2,292億円 -> 平成22年度1般会計予算は92229200000000円

2010年10月20日水曜日

Google App Engine SDKは32bit

64bitのActivePython入れても動かなかったよ。