Main Contents
2008年04月06日
日本人の平均余命と死亡率
「日本人の平均余命と死亡率」というページを公開しました。
年齢と性別を入力すると、
- 統計的にどれくらいの余命がありそうなのか
- 将来のある年齢までの死亡率はどれくらいなのか
を表示します。
データは厚生労働省:日本人の平均余命 平成18年簡易生命表から抜粋しています。「平均余命」についてはこの生命表の値をそのまま、特定の年齢までの死亡率については、入力年齢での生存人口=A、将来の年齢での生存人口=Bとして、(A-B)/A で算出しています(これが本当に正しい方法なのかは調べていません)。
試しに自分の場合、30歳・男性では以下のようになります。平均余命はあと50年弱、つまり平均的には80歳近くまで生きられるようですが、75歳になるまでには1/4以上の確率で亡くなってしまうようです。85歳に至っては、生存率のほうが低い、というのが事実のようです。
これは過去の実績からなる統計値なので、自分(特定の個人)の平均余命や死亡率がこの通りというわけではありません。また、将来の環境変化によっても変わってきます。それでも集団として見たときに、自分や自分と同い年の友人の4人にひとりがあと45年以内に亡くなってしまい、その10年後には今の半数以下になってしまう、という事実にはなかなか厳しいものがあります。
これまでは、自分の人生にあとどれくらいの時間が残されているのかということは考えてこなかったのですが、実際に数字を見て、残りの人生でいったい何ができるのか、何をすべきなのか、正直なところ考えさせられてしまいました。
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 22:35
- in Python
2008年03月23日
日本語の文章校正支援ツールをリリース
Yahoo! Japan が提供する校正支援APIを利用して、文書校正支援ツールを作ってみました。
「はるか彼方に小形飛行機が見える。」という文を校正してみると、こんな感じになります。
ブログ書きのお供にどうでしょうか。
校正すべき箇所と、言い換え候補はYahooの校正支援APIからの情報をそのまま使っているのですが、実際に使ってみるとちょっと苦しいところがあるようです。
たとえば、「遙か」に対して返ってくる「言い換え候補文字列」が「●か」になっているとか、「他の」に対しては「ほかの(「たの」と読む場合は漢字表記可)」が返ってくるとかいうケースです。これらの修正候補をそのまま指摘箇所に埋め込んでしまうと、文章としてはおかしくなってしまいます。「●か」とか「(「たの」と読む場合は漢字表記可)」という部分は本来言いかえ候補の一部ではなく、指摘に関する説明事項なのですが、「本来の言い換え候補」と「説明事項」がごっちゃになって「言い換え候補」として返ってきてしまっているようです。
校正支援APIを提供している意図は、「他のプログラムに校正支援機能を付けられるように」ということだと思うのですが、どこまでが「言い換え候補」なのかよくわからない情報が返ってくる、という状態だと、「言い換え候補を横目で見ながらユーザーにその言い換え候補を手入力させる」というレベルのものしか作れないことになるのではないでしょうか。あるいはそのレベルでしか提供をしない、というのが狙いなのかもしれませんが、改善を希望したいところではあります。
プログラム内部では、校正支援APIを呼び出すために、拙作のPythonライブラリYAPIを使っています。興味があればどうぞ。今回使ったのは、今のところまだ公開していないリビジョン 0.3.1です。これもいずれ公開します。
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 16:31
- in Python
2008年03月22日
YAPI-0.3 校正支援、ローカルサーチ、トピックスへの対応を追加
Yahoo! Japan の Web API を Python から利用するためのライブラリ、YAPI-0.3 をリリースします。
(YAPI-0.2はこちらから:kh.log - Yahoo! Japan の Webサービス用 Pythonライブラリ)
これまでの検索(Web、画像、動画、関連検索ワード)と形態素解析サービスに加えて、新たに校正支援、ローカルサーチ、トピックスへの対応を追加しました。
APIのパラメータ詳細についてはYahoo!デベロッパーネットワークを参照してください。
以下、READMEより:
== YAPI ==
This is a module package to make use of the Web API
provided by Yahoo! Japan Developer Center.
Currently supported API:
Search (Web, Image, Video, WebUnit)
MAService
KouseiService
Topics
LocalSearch
== Install ==
python setup.py install
== Synopsis ==
>>> from YAPI import *
>>> APPID='Your Application ID Here.'
>>>
>>> ma = MAService(APPID)
>>> d = ma.call(sentence=u'すもももももももものうち'
output_coding='utf-8')
>>>
>>> d
<YAPI.Response.MAServiceResponse object at 0x309547f0>
>>>
>>> if not d.is_error:
>>> for w in
>>> d.response['ResultSet']['ma_result']['word_list']['word']:
... print '\t'.join((w['surface'], w['reading'], w['pos']))
...
すもも すもも 名詞
も も 助詞
もも もも 名詞
も も 助詞
もも もも 名詞
の の 助詞
うち うち 名詞
>>> ks = KouseiService(APPID)
>>> d = o.call(sentence=u'遙か彼方に小形飛行機が見える。',
output_coding='utf-8')
>>>
>>> for r in d.response['ResultSet']['Result']:
>>> print '\t'.join([str(r['StartPos']), str(r['Length']), r['Surface'],
... r['ShitekiWord'], r['ShitekiInfo']])
...
0 2 遙か ●か 表外漢字あり
2 2 彼方 彼方(かなた)、かなた 用字
5 5 小形飛行機 小型飛行機 誤変換
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 22:32
- in Python
2008年03月14日
Pythonで全角半角を正規化する方法
インターネット上の日本語を扱っていると、全角半角が統一されていない事による表記揺れをなんとかしたい場面に出くわします。半角で書かれた iPod も、全角で書かれたiPodも同じものとして扱いたいときや、あるいは単に見た目がきれいになるように、英数字は半角に、カタカナは全角にそろえたい、という場合です。
Python では setomitsさんによる zenhan.py を使うと、文字種ごとに全角半角を選択して変換することができ、除外文字も設定できるので便利です。ただ、そこまで柔軟でなくても良く、単に表記揺れがなくなれば良い、という場合も多いかと思います。その場合はPythonの標準ライブラリに含まれる unicodedata モジュールの normalize 関数を使うと便利です。
>>> import unicodedata
>>>
>>> s = 'フガホゲ-%*@ABC−%*@123'.decode('euc-jp')
>>> n = unicodedata.normalize('NFKC', s)
>>>
>>> print s.encode('euc-jp')
フガホゲ-%*@ABC−%*@123
>>>
>>> print n.encode('euc-jp')
フガホゲ-%*@ABC−%*@123
Unicode で定義される各文字は、等価な別表現がある場合(たとえば半角のAと全角のA)に、どの表現を標準とするべきか、という情報が付与されているそうです。normalize関数はこの情報を使って、表記を統一する処理を行います。normalize関数の第一引数に 'NFKC' を渡すことで、ガ(カ+濁点)のような複合文字が期待通りに分解・再合成されます。(詳しく知りたい方は Unicode正規化 あたりをどうぞ)
実際の変換結果を見てみると、英字、数字は半角に、カタカナは全角に正規化されることになっているようです。記号については、基本的に半角のようですが、全角マイナスと半角マイナスのように、別の文字として扱われているものもあるようです。マイナスが半角に正規化されるべきかどうかは場合によって異なると思われますが、ほとんどの用途にはこれで十分なのではないでしょうか。
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 21:23
- in Python
2008年02月27日
Yahoo! Japan の Webサービス用 Pythonライブラリ
Yahoo!デベロッパーネットワーク で公開されているWebサービスの Python バインディングを書いたので公開します。
UPDATED 2008/03/22:
YAPI-0.3 がリリースされています。
kh.log - YAPI-0.3 校正支援、ローカルサーチ、トピックスへの対応を追加
ダウンロード: YAPI-0.2.tar.gz
libxml2-python 2.6.30以上が必須です。
いまのところ、検索系4種と形態素解析の5つのAPIのみの対応です。
XMLをPythonオブジェクトに変換するところで悩んでしまって、ちょっと奇妙な実装になっています。Yahoo!のAPIにはすべて、XML Schemaが用意されているのですが、これをどう生かせば良いのかがわからなかったため、独自のパージング関数を書いてしまいました。興味のある方は中をご覧ください。(そして正しい方法をご連絡ください…)
使用法は以下。
READMEより:
== YAPI ==
This is a module package to make use of the Web API
provided by Yahoo! Japan Developer Center.
Currently supported API:
Search (Web, Image, Video, WebUnit)
MAService
== Install ==
python setup.py install
== Synopsis ==
>>> from YAPI import *
>>> APPID='Your Application ID Here.'
>>>
>>> ma = MAService(APPID)
>>> d = ma.call(sentence=u'すもももももももものうち'
output_coding='utf-8')
>>>
>>> d
<YAPI.Response.MAServiceResponse object at 0x309547f0>
>>>
>>> for w in d.response['ResultSet']['ma_result']['word_list']['word']:
... print '\t'.join((w['surface'], w['reading'], w['pos']))
...
すもも すもも 名詞
も も 助詞
もも もも 名詞
も も 助詞
もも もも 名詞
の の 助詞
うち うち 名詞
- Permalink
- Comments (0)
- Trackbacks (1)
- by
- at 22:45
- in Python
2007年10月13日
Lightweight Languages AHP
Lightweight Languages AHPというのをやってみた。ふだん使っていて、いまやもっとも馴染んでいるPythonよりRubyのほうが若干スコアが高い。実はPythonよりRubyを使いたいと思っているのかも。
細かく見てみるとなかなか興味深い。読み取れるのはこんなところだろうか:
- RubyはPythonやPerlよりずっと変態性が高いと思っている(そのとおり。)
- (自分にとっては)PythonのほうがRubyより開発環境と記述性で優れていると思う
- Ruby/PerlよりもPythonのほうが高速に動くことが多いと思っている(でも実際のところその認識はアヤシイとも思っているし、ほんとうは違いがよくわかっていない。そもそもLLに高速性は求めていない。)
- Pythonの色気のなさがたまにいやになる
- もうPerlを大事なところで使おうとは思わない(が、あの変態性はたまに懐かしい)
- (PHPのことはあまりよく知らないし、知ろうとも思っていない)
実際もう数年すると、Rubyが仕事で使いたい言語になっている可能性はあるかな。
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 22:01
- in Python
2007年09月20日
Python for 702NK/702NK2プログラミングブック
会社からの帰り道、地下鉄のホームで「Python for 702NK/702NK2プログラミングブック」を読みながら歩いている人を見かけました。Pythonの文字と緑色の表紙を手がかりにamazonを検索してタイトルを知ったのですが、なかなかマニアックな本のようです。
こんなものを読みながら歩いている人を見かけるなんて、やはり東京っていろんな人がいるんだなあ、と。
そのとき自分はカバンに入りきらなかった「入門 GNU Emacs 第3版(512ページ)」を手に持っていましたがね。
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 21:24
- in Python
2007年01月15日
境界を越える日付
会社で訊かれたこと。いや、割り込んだことか。日付を1日づつインクリメントして、月の終わりとか、年の終わりとかをきれいに超える簡単な方法。
2006-12-30
2006-12-31
2007-01-01
...
と言うやつね。
python の場合
datetimeを使う。
python
>>> import datetime
>>> d = datetime.date(2006, 12, 25)
>>> d_end = datetime.date(2007, 1, 4)
>>> delta = datetime.timedelta(1)
>>> while True:
... if d == d_end: break
... print d.strftime("%Y-%m-%d")
... d += delta
...
2006-12-25
2006-12-26
2006-12-27
2006-12-28
2006-12-29
2006-12-30
2006-12-31
2007-01-01
2007-01-02
2007-01-03
>>>
shellの場合
こちらはXX日前〜YY日前という指定。
for i in `seq 21 -1 12`; do date --date "$i days ago" +"%Y-%m-%d"; done 2006-12-25 2006-12-26 2006-12-27 2006-12-28 2006-12-29 2006-12-30 2006-12-31 2007-01-01 2007-01-02 2007-01-03
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 23:57
- in Python
2007年01月10日
osxのpythonでCtrl-Aとか日本語入力とか。
setomitsさんがblogSetomits : Mac OS X 上の Python インタプリタとかblogSetomits : あらためて Python 2.4.4あるいはblogSetomits : 続 Mac OS X 上の Python インタプリタで書かれているように、osxのpythonのインタラクティブモードはなんだか動作がヘンです。Emacsキーバインドが効かなかったり、日本語がちゃんと入力できなかったり。
はじめ、readlineをコンパイルしてみたり、python自体をコンパイルしてみたりしたのですが状況はそれほど変わらず。結局、rlwrapをMacPorts(旧DarwinPorts)から導入し、~/.inputrcを設定することで問題が解決しました。
ちなみにrlwrapというのはreadlineラッパーです。これがどんなものかは川o・-・)<2nd life - rlwrap - readline ラッパーで説明されていますので、ご参照ください(手抜き)。自分もここでrlwrapを知りました。
以下、手順。
1.MacPortsのインストール
InstallingMacPorts - MacPorts - Tracに書かれているとおりXcode Toolsをインストールして、環境変数を設定してから、MacPortsの.dmgをインストールすればOK、のはず。自分はDarwinPortsのころにインストールしたのでよくわからん。たぶん同じだけど。
2.rlwrapのインストール
ターミナルから
sudo port install rlwrap
とするだけ。
標準構成ならたぶん /opt/local/bin/rlwrapに入るかな。
3. ~/.inputrcの設定。
意味はわからんけどreadlineさまが機嫌良く動いてくれるように、以下のおまじないを ~/.inputrcに追加。
set convert-meta off set output-meta on set input-meta on
4. 実行
以下のような感じ。例ではわからないが、ちゃんとCtrl-AとかCtrl-H とかのEmacsキーバインドが効いている。
% rlwrap python2.4
Python 2.4.4 (#1, Oct 18 2006, 10:34:39)
[GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> u = 'あいうえお'.decode('euc-jp')
>>> len(u)
5
>>> for c in u:
... print hex(ord(c))
...
0x3042
0x3044
0x3046
0x3048
0x304a
どうでもいいけど、標準の pytho2.3.5 で decode('euc-jp')とすると、"LookupError: unknown encoding: euc-jp"と怒られてしまう。JapaneseCodecて2.3から標準でなかったっけ?
- Permalink
- Comments (1)
- Trackbacks (0)
- by
- at 11:06
- in Python
2006年11月15日
JUMAN Python バインディング (SWIG)
形態素解析器JUMANをPythonモジュールとして使うためのバインディングを作りました。
JUMANは-Sオプションをつけて起動すると、サーバーモードで動作します。サーバーモードのJUMANは他のプログラム(たとえばPython)とソケットで通信して、形態素解析の結果を返してくれます。大量の文書を解析するときなどは、ひとつの文書ごとにプロセスを起動するよりも効率がよいのですが、それでもソケット通信の分、速度が落ちてしまいます。
JUMANを、Cで書かれたPythonモジュールとしてラップしてやるバインディングさえ書ければ、このソケット通信の無駄をなくすことができます。
ちょうどSWIGの使いかたを学びたかったこともあって、バインディングを書いてみたのでした。サーバーモードのJUMANとソケット通信するよりは、15〜20%ほど速いようです。
SWIGの定義ファイル作成にあたっては、SWIGオフィシャルや83's : JumanのRubyバインディングを参考にさせていただきました。
モジュールは以下のように使います。
#!/usr/bin/python
# -*- coding: euc-jp -*-
import cJuman
S = [
'私の名前は中野です。',
'',
'これはJUMAN Pythonテストです。',
]
cJuman.init(['-B', '-e2'])
print cJuman.parse_opt(S, cJuman.SKIP_NO_RESULT)
結果は以下の通り。
私 わたくし 私 名詞 6 普通名詞 1 * 0 * 0 "漢字読み:訓 代表表記:私" @ 私 わたし 私 名詞 6 普通名詞 1 * 0 * 0 "代表表記:私" の の の 助詞 9 接続助詞 3 * 0 * 0 NIL 名前 なまえ 名前 名詞 6 普通名詞 1 * 0 * 0 "代表表記:名前" は は は 助詞 9 副助詞 2 * 0 * 0 NIL 中野 なかの 中野 名詞 6 人名 5 * 0 * 0 NIL @ 中野 なかの 中野 名詞 6 地名 4 * 0 * 0 NIL です です だ 判定詞 4 * 0 判定詞 25 デス列基本形 24 NIL 。 。 。 特殊 1 句点 1 * 0 * 0 NIL EOS EOS これ これ これ 指示詞 7 名詞形態指示詞 1 * 0 * 0 NIL は は は 助詞 9 副助詞 2 * 0 * 0 NIL JUMAN JUMAN JUMAN 未定義語 15 その他 1 * 0 * 0 NIL \ \ \ 特殊 1 空白 6 * 0 * 0 NIL Python Python Python 未定義語 15 その他 1 * 0 * 0 NIL テスト てすと テスト 名詞 6 サ変名詞 2 * 0 * 0 "代表表記:テスト" です です だ 判定詞 4 * 0 判定詞 25 デス列基本形 24 NIL 。 。 。 特殊 1 句点 1 * 0 * 0 NIL EOS
SWIGの定義ファイルはこちら。 [cJuman.i]
これを使って、以下のようにしてモジュールを作成します。
tar xvzf juman-5.1.tar.gz cd juman-5.1 ./configure make make install cd lib cp ~/cJuman.i . swig -python cJuman.i gcc -c cJuman_wrap.c -I/usr/include/python2.4 gcc -shared *.o -o _cJuman.so
ちなみにUbuntuでは CC=/usr/bin/gcc-3.4と、明示的にgccのバージョンを指定しました。
余談。余暇を利用して書いていたのですが、がんばりすぎて体調をくずし、本業を休んでしまいました。本業が忙しかったことに加えて、SWIGでバインディングを書くのが意外と楽しく、睡眠時間を削ってしまったのでした。反省です。
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 23:15
- in Python
2006年10月30日
Google Co-op で Python Search Engineを作ってみた
昨日紹介した Google Co-op の Custom Search Engine 作成機能を使って、Python Search Engineを作ってみました。
まだ、python.org、python.jpのほか、数人のpython使いのブログを登録しただけの状態ですが、python.jpのライブラリリファレンスが簡単に検索できるようになったのは、意外と便利です。
とはいえ、作ってから気づいたのですが、オフィシャルであるpython.orgとpython.jpを除いたら、Python関連サイトをあまり知りません。COREBlogで有名な柴田さんのブログなどを探して登録してみたものの、早くもネタ切れ状態です。
幸い、Custom Search Engine には、Googleアカウントを持っている人同士で共同編集ができる機能があります。Python Search Engineも共同編集(に応募)可能にしてあるので、Python方面でご活躍中の方、Pythonで仕事している方、Pythonに興味ある方、で手伝ってもいいなと思われたら、ぜひご参加ください。Python Search Engineから、"Volunteer to contribute to this search engine." と書かれたリンクをクリックすれば、応募できます(たぶん)。
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 22:20
- in Python
2006年10月01日
kakaku.com Web API for Python (ElementTree使用版)
ついさっきkh.log - kakaku.com Web API for Pythonを書いたところ ですが、ElementTreeという便利なモジュール(python 2.5から標準モジュールになった )を知ったので、書き換えてみました。一応、前のものも残しています。
ElementTreeの使いかたは、perezvonの日記 - Raku APIやElementTree Overview ::: www.effbot.orgを参考にさせていただきました。
KakakuComAPIクラス(ElementTree版)をダウンロードする
以下のようなかんじ。だいぶすっきりした。
import urllib, types
try:
import xml.etree.ElementTree as ET
except ImportError:
try:
import cElementTree as ET
except:
import elementtree.ElementTree as ET
from xml.dom import minidom
class KakakuComAPI(object):
API_ENDPOINT = r'http://api.kakaku.com/Ver1/ItemSearch.asp'
UNMARSHALLERS = {
'Item': lambda e: dict([(c.tag, c.text) for c in e]),
'ProductInfo': lambda e: [c.text for c in e if c.tag == 'Item'],
'Error': lambda e: e[0].text,
}
@classmethod
def search(cls, **args):
params = cls.__parameterize(args)
url = cls.API_ENDPOINT + '?' + params
result = {}
f = urllib.urlopen(url)
for event, elem in ET.iterparse(f):
unmarshal = cls.UNMARSHALLERS.get(elem.tag, lambda e: e.text)
elem.text = unmarshal(elem)
if elem.tag in ('ProductInfo', 'Error', 'NumOfResult'):
result[elem.tag] = elem.text
f.close()
result['RequestedUrl'] = url
return result
@classmethod
def __parameterize(cls, args):
kw = args.get('Keyword')
arg_enc = args.get('ArgsEncode')
if type(kw) is types.UnicodeType:
kw = kw.encode('shift_jis', 'ignore')
elif arg_enc:
kw = kw.decode(arg_enc, 'ignore').encode('shift_jis', 'ignore')
params = []
params.append("%s=%s" % ('Keyword', urllib.quote(kw)))
for p in ('ResultSet', 'CategoryGroup', 'SortOrder', 'PageNum'):
v = args.get(p)
if v != None:
params.append("%s=%s" % (p, urllib.quote(v)))
return '&'.join(params)
以下、使用例。ここは前と同じ。
Keywordに日本語を含む場合はsjisで渡すか、unicodeで渡すか、そうでなければArgsEncodeで明示するかする必要があることに注意。
from kakaku_api import KakakuComAPI
r = KakakuComAPI.search(Keyword="vaio")
r = KakakuComAPI.search(Keyword=u"バイオ")
r = KakakuComAPI.search(Keyword=u"バイオ".encode("shift_jis"))
r = KakakuComAPI.search(Keyword=u"バイオ".encode("euc-jp"), ArgsEncode="euc-jp")
r = KakakuComAPI.search(Keyword="vaio",
ResultSet="medium",
SortOrder="pricerank",
PageNum="4",
CategoryGroup="Pc")
結果の形式が前回とはちょっと違っているので注意。商品情報はItemsというキーで格納していたのですが、今回はProductInfoキーで格納してます。
{'ProductInfo': [{'BbsPageUrl': u'http://kakaku.com/bbs/Main.asp?PrdKey=01307211611',
'CategoryName': u'\u30d1\u30bd\u30b3\u30f3\u5468\u8fba\u6a5f\u5668>MP3',
'ImageUrl': u'http://img.kakaku.com/images/productimage/m/01307211611.jpg',
'ItemPageUrl': u'http://kakaku.com/item/01307211611/',
'LowestPrice': u'15298',
'MakerName': u'SONY',
'NumOfBbs': u'516',
'ProductID': u'01307211611',
'ProductName': u'NW-E005 \u30d0\u30a4\u30aa\u30ec\u30c3\u30c8 (2GB)',
'PvRanking': u'4',
'ReviewPageUrl': u'http://kakaku.com/prdevaluate/evaluate.asp?PrdKey=01307211611'},
... ],
'NumOfResult': u'762',
'RequestedUrl': 'http://api.kakaku.com/Ver1/ItemSearch.asp?Keyword=vaio&ResultSet=medium&CategoryGroup=Pc&SortOrder=pricerank&PageNum=4'}
または、エラーがあった場合は、
{'Error': u'\nItemNotFound',
'RequestedUrl': 'http://api.kakaku.com/Ver1/ItemSearch.asp?Keyword=vaio0000'}
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 16:55
- in Python
kakaku.com Web API for Python
価格.comがAPIを公開したので、Pythonバインディング: KakakuComAPIクラスを作ってみました。python 2.4以上が必要。
中身は以下のような感じ。なんか、妙に長い。XMLのパーズ部分をもっとすんなり書けると良いのだけど。
import urllib, types
from xml.dom import minidom
class KakakuComAPI(object):
API_ENDPOINT = r'http://api.kakaku.com/Ver1/ItemSearch.asp'
ELEMENTS = ['ProductID',
'ProductName',
'MakerName',
'CategoryName',
'PvRanking',
'ImageUrl',
'ItemPageUrl',
'BbsPageUrl',
'ReviewPageUrl',
'LowestPrice',
'NumOfBbs']
@classmethod
def search(cls, **args):
params = cls.__parameterize(args)
url = cls.API_ENDPOINT + '?' + params
f = urllib.urlopen(url)
xml = f.read()
f.close()
result = cls.__construct(xml)
result['RequestedUrl'] = url
return result
@classmethod
def __parameterize(cls, args):
kw = args.get('Keyword')
arg_enc = args.get('ArgsEncode')
if type(kw) is types.UnicodeType:
kw = kw.encode('shift_jis', 'ignore')
elif arg_enc:
kw = kw.decode(arg_enc, 'ignore').encode('shift_jis', 'ignore')
params = []
params.append("%s=%s" % ('Keyword', urllib.quote(kw)))
for p in ('ResultSet', 'CategoryGroup', 'SortOrder', 'PageNum'):
v = args.get(p)
if v != None:
params.append("%s=%s" % (p, urllib.quote(v)))
return '&'.join(params)
@classmethod
def __construct(cls, xml):
result = {}
dom = minidom.parseString(xml)
err = dom.getElementsByTagName('Error')
if err and len(err) >= 1:
msg = err[0].getElementsByTagName('Message')[0]
result['Error'] = msg.firstChild.nodeValue
nor = dom.getElementsByTagName('NumOfResult')
if nor and len(nor) >=1:
result['NumOfResult'] = nor[0].firstChild.nodeValue
items = dom.getElementsByTagName('Item')
if items:
item_list = []
for item in items:
item_list.append(cls.__parse_item(item))
result['Items'] = item_list
return result
@classmethod
def __parse_item(cls, item):
result = {}
for e in cls.ELEMENTS:
tags = item.getElementsByTagName(e)
if tags:
result[e] = tags[0].firstChild.nodeValue
else:
result[e] = ''
return result
以下、使用例。
Keywordに日本語を含む場合はsjisで渡すか、unicodeで渡すか、そうでなければArgsEncodeで明示するかする必要があることに注意。
from kakaku_api import KakakuComAPI
r = KakakuComAPI.search(Keyword="vaio")
r = KakakuComAPI.search(Keyword=u"バイオ")
r = KakakuComAPI.search(Keyword=u"バイオ".encode("shift_jis"))
r = KakakuComAPI.search(Keyword=u"バイオ".encode("euc-jp"), ArgsEncode="euc-jp")
r = KakakuComAPI.search(Keyword="vaio",
ResultSet="medium",
SortOrder="pricerank",
PageNum="4",
CategoryGroup="Pc")
結果として受け取る r はこんなかんじ
{'Items': [{'BbsPageUrl': u'http://kakaku.com/bbs/Main.asp?PrdKey=01307211611',
'CategoryName': u'\u30d1\u30bd\u30b3\u30f3\u5468\u8fba\u6a5f\u5668>MP3',
'ImageUrl': u'http://img.kakaku.com/images/productimage/m/01307211611.jpg',
'ItemPageUrl': u'http://kakaku.com/item/01307211611/',
'LowestPrice': u'15298',
'MakerName': u'SONY',
'NumOfBbs': u'516',
'ProductID': u'01307211611',
'ProductName': u'NW-E005 \u30d0\u30a4\u30aa\u30ec\u30c3\u30c8 (2GB)',
'PvRanking': u'4',
'ReviewPageUrl': u'http://kakaku.com/prdevaluate/evaluate.asp?PrdKey=01307211611'},
... ],
'NumOfResult': u'762',
'RequestedUrl': 'http://api.kakaku.com/Ver1/ItemSearch.asp?Keyword=vaio&ResultSet=medium&CategoryGroup=Pc&SortOrder=pricerank&PageNum=4'}
または
{'Error': u'\nItemNotFound',
'RequestedUrl': 'http://api.kakaku.com/Ver1/ItemSearch.asp?Keyword=vaio0000'}
追記
ElementTreeを使ったバージョンも書いてみました。see: kh.log - kakaku.com Web API for Python (ElementTree使用版)- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 14:30
- in Python
2006年04月27日
cvsでcommitメールを送るためのpythonスクリプト
とりあえず書いただけ。
設定方法などは後ほど追記します。
cvsでcommitメールを送るためのpythonスクリプト
追記: 2006/04/27 23:00
スクリプトを更新しました。2006/04/24 23:00以前にダウンロードした方は、もう一度ダウンロードしてください。以前の版では、環境によってデッドロックを起こす場合があります。
設置方法は以下の通り…と説明を書こうとしたのですが、力尽きました。commit をメール通知する設定というページを参考に、cvsform.plをcvsmail.pyと読み替えれば、おそらく設定できるはずです。
以下、簡単に注意点や説明を。
- このスクリプトは、CVSへのcommit時に、更新されたファイルのdiffをリストアップしてメール送信するためのものです。
- SMTP, FROM, SUBJECT, CVS, KANJIなどを環境に合わせて変更してください。
- DEFの内容は引数が欠けている場合の気休めなので、基本的に無視してください。
- CVSのバージョンによって、loginfo中に%{sVv}と書いたときに得られる文字列のフォーマットが違うようです。スクリプト中のコメントを参考に、適合するほうのコメントをはずしてください。
以上。
ちなみにこんなメールが送られてきます。
From: cvs@your.domain
To: kharakawa@ubuntu
Subject: [CVS] testproj commit mail.
Message-Id: <---@ubuntu>
Date: Thu, 27 Apr 2006 23:14:08 +0900 (JST)
Update of /usr/share/cvsroot/testproj
In directory ubuntu:/tmp/testproj
Modified Files:
fugahoge
Log Message:
change 'before' to 'AFTER'
1 file(s) affected.
Index: fugahoge
===================================================================
RCS file: /usr/share/cvsroot/testproj/fugahoge,v
retrieving revision 1.1
retrieving revision 1.2
diff -r1.1 -r1.2
3c3
< befor
---
> AFTER
追記: 2006/04/29 22:00
さらに少し修正しました。正規表現の修正。
- Permalink
- Comments (0)
- Trackbacks (0)
- by
- at 08:11
- in Python