January 3, 2010 at 4:57 pm · Filed under Gossip
很久以前做了个豆瓣-电子科大图书馆馆藏查询的Bookmarklet/Greasemonkey Script,
在图书馆借书的时候才发现手持设备根本没法查馆藏信息, 悲剧啊!
最近一直在看Google App Engine的文档, 就打算写个App来体验下.
于是就有了这个项目: 郫县豆瓣.mobile.
名字来源于电子科大幼儿园郫县金凤村附属电子高专,和豆瓣.
功能很简单, 就是利用豆瓣的API查询图书, 然后同时查询图书的馆藏状态.
把服务跑在GAE而不是栋力的服务器上的坏处是:
- 电子科大的DNS经常抽风, 外网访问图书馆系统不稳定
- 访问延迟偏高
昨天最开始测试的时候, urlfetch不停的超时, 最后不得已, 还是在209上搭了个桥, 囧.
稍微修改了下原来用PHP写的Web Services, 支持多个请求合并, 这样可以减少urlfetch的调用数目.
不过既然做了个网站, 就打算把原来只停留在TODO list上的features全部实现了,
包括:
- 用户借书清单, 对我这种很久去一次图书馆借一堆书的人省得用纸笔了
- 图书自动续借, 懒人专用
- 图书借阅信息双向同步(比如借了本书就在豆瓣上标记为”在读”, 归还后标记为”读过”), 懒人专用
- 归还通知, XMPP的也好, 邮件的也好, 甚至Twitter的也好, 看有没有精力折腾吧.
比较落后于时代, 在郫县豆瓣.mobile里也是第一次用Google Analytics,
不得不说Google Analytics和Google App Engine的确是简单好用到极致了.
最后, 郫县豆瓣.mobile项目是开源的, 基于Apache License 2.0发布,
代码托管在Github, 地址: http://github.com/killkeeper/Douban-UESTC-Library-Mashup-Mobile

·· Tags: douban·GAE·github·Google·Python
December 16, 2009 at 8:31 pm · Filed under Program
Nodebox强大之处在于, 有无数第三方的扩展库, 可以快速的实现数据处理和可视化.
Graph就是一个很方便的用于图论可视化的扩展库.
不过Nodebox是Mac-only的(基于Cocoa), Shoebot是其基于GTK+和Cairo的移植.
断断续续花了两天时间把graph库移植到了shoebot下, 一些诡异的细节问题折磨了我n久.
经过了对原graph库的一些hack, 现在基本上可以正常的跑起来了.
除去对graph库的hack外, 我也改了不少shoebot的源码,
一方面是使得shoebot的命令调用更兼容Nodebox, 一方面是移植了部分Nodebox更新后, shoebot还没有移植的功能.
先放一张example图, 改天把源码再仔细检查下, 就放到github上去.
·· Tags: Nodebox·Python·shoebot·visualization
December 13, 2009 at 10:15 pm · Filed under Program
忘了最早哪儿看到的了, 去年用AS3写了一个,
不过我的AS3实在是烂.
今天est大神提到了这个, 我就顺便用shoebot重写了一次.
分词使用的pymmseg, 不过缺点是分词后不会有词性, 这样就无法通过词性筛掉一部分出现频率高但是实际上重要性不大的词.

如图是胡core在十七大上的讲话, 当然太长了, 我只用了新华社稿子的前两页.
(社会主义果然无比强大啊!)
几点总结:
1. shoebot的确很好用, 或者应该说nodebox真的很好用 -__-!
2. 关于文字排布, 最简单的方法往往是最简单的.
接下来准备把这个东西继续完善下,
1. 做一个HTTP的服务, 免得只能在本机跑很无趣.
2. 做一点语义元素上的挖掘, 我倒是想看看单词在给定距离下的邻接性会不会有什么有趣的东西… 比如根据单词的邻接图绘制最小生成树?
3. 有空了打算做个cluster, 说不定也是一个有趣的结果.
·· Tags: Python·shoebot·visualization
November 15, 2009 at 11:30 am · Filed under Gossip, Program
无聊得蛋痛, 想起了电子科大附属幼儿园”门户”的那个CAPTCHA.
前几周帮导师准备支持向量机的上机实验的时候, 正好看到一个用svm识别手写阿拉伯数字的数据库.
简单来说, 手写数字的图形被缩放为16×16的二值图像最后转化为256参数的多元分类问题,
考虑到上面这个阿拉伯数字数据库不错的交叉检验准确率, 我也就顺便拿来做”门户”的CAPTCHA识别了.
写了个脚本拖了100+个验证码样本回来, 仔细看了下,
虽然这个第二版山寨门户的CAPTCHA比第一版的CAPTCHA有了不少的进步(第一版的数字无比规则以至于可以直接写一个Greasemonkey脚本用canvas来识别),
但是总体上还是比较好识别的, 统一是二值图片, 字符间有清晰的间隙(除了有一张图有一点毛刺外),
只是图片加上了一些简单的几何变换.

上面是一个CAPTCHA的例子。
考虑到几何变换对字符产生的形变所造成的相同字符间差异,还没有手写阿拉伯数字样本间的差异大,
我就没做任何校正处理直接把字符切割了送去做训练和识别了.
通过识别各个字符的最大边界, 将四个字符分割出来, 统一复制到60×60的一块空画布上,
最后缩放到15×15, 转化为标准的二值 bitmap, 最后输出为libsvm的标准格式.
训练集我一共下载了124张CAPTCHA图片, 也就是496个字符的samples,
用libsvm对训练集做了5重的Cross-Validation, 自检验准确率: 97.1311% (Radial Basis核).
*EDIT* 又用线性核做了一次, 可以跑到98.1557%
总的来说, 支持向量机识别这个轻微几何变形的CAPTCHA还是有相当高的准确率的.
最后感谢无比handy的PIL以及Python,
这让我突然想起了用C/CPP写酵母基因预测程序时候的繁琐和折磨.
最后的最后, 我也不知道把这个CAPTCHA hack了有什么实质性的用处,
电子科大附属幼儿园门户系统如此山寨, 以至于从上一版本到现在的版本,
都可以绕过CAPTCHA直接提交信息进行认证,
回扣万岁!!
附简化原理图一张:

·· Tags: Captcha·libsvm·PIL·Python·SVM
July 14, 2009 at 12:48 am · Filed under Program
最近在试图用web.py这个轻量级框架写个网站,
实现的时候把每个页面的controller单独成module, 放在ctrls目录下,
接下来就发现了问题: 各个module和main module之间没法传递变量,
因此session, database, template render都没法在全局共享, 糟糕的问题.
问题的来源很简单:
web.py把request这一块完全托管了, 由其来初始化各个controller的类,
因此没法通过初始化函数传递我需要的变量进去.
今天仔细钻研了下才发现是我Python太菜的缘故,
其实用setattr()就可以把需要的变量传递给对应的类/模块了.
以下是一个实现的sample:
*UPDATE* 另外一个实现里我把所有模块都在load_controller()函数里通过__import__动态加载, 再通过globals()[CTRL_NAME] = CTRL_CLS 来实现, 这样可以省去前面的无数 from xxx import xxx
Read the rest of this entry »
·· Tags: Python·web.py
March 11, 2009 at 10:14 am · Filed under Gossip, Program
以前看了不少有关.NET下String和StringBuilder的性能对比,
前几天正好也看到了est分享的一篇讲Python一些tricks的文章,
里边提到了用”+”连接字符串的性能问题.
早上顺手做了个benchmark.
首先用list插入元素, 接着用join方法连接字符串:
import time
pad = "xYz%2#$lkjw4" * 50
pad_pool = []
t_s = time.time()
for x in xrange(10000):
pad_pool.append(pad)
base = "".join(pad_pool)
print "time:", time.time() - t_s
time: 0.0179998874664
接着用”+”来连接字符串:
import time
base = ""
pad = "xYz%2#$lkjw4" * 50
t_s = time.time()
for x in xrange(10000):
base += pad
print "time:", time.time() - t_s
time: 10.5399999619
————————————–
嗯, 用”+”来连接很有点惨烈啊, 这和.NET里的String的直接连接有点像,
不过这两个时间间的gap显然还要大得多.
我个人估计是”+”操作的需要不停的申请分配内存,
导致的性能低下?
·· Tags: Python
February 28, 2009 at 1:20 pm · Filed under Program
做个笔记扔这儿吧:
>>> sys = __import__('sys')
>>> os = __import__('os')
>>> re = __import__('re')
>>> unittest = __import__('unittest')
>>> sys
>>> <module 'sys' (built-in)>
>>> os
>>> <module 'os' from '/usr/local/lib/python2.2/os.pyc'>
·· Tags: Python
February 28, 2009 at 10:00 am · Filed under Program
众所周知, 某b是懒人, 当然这个前提与本文无关.
某b搭建的nba视频站虽然和NBA官方的版权声明冲突不小, 不过每天的PV还是能有大概17k,
不过这个统计的方法很可怕, php里先建立一个数组, 把每条访问数据push进去,
序列化, 扔到memcached里. 再一个访问来了, 反序列化, 再push, 再序列化…
后来干脆就准备写个实时的日志记录和处理的python程序, 不然序列化都会吃掉大量的脚本运行时间.
先很白痴的准备用FastCGI来做, 做一个webservice, php请求一次, 我就完成一次日志.
后来还是打webserver的主意, 不过FastCGI行不通, 就转而研究管道了.
mkfifo创建named pipeline后, 让nginx把日志输出到管道, 就可以通过python阻塞读取日志了,
不过这里python脚本要先阻塞读取, 再kill -HUP掉nginx, 让配置重新生效.
此后的处理就可以按照需要的配置来进行了,
处理后的日志数据存放在sqlite3数据库里, 方便进行查询和索引.
每条进来的日志先写在内存的数据库里, 达到一定数目时再用事务写到硬盘的实体表里.
昨天晚上大概写了个DEMO出来, 在本地调试管道,
发现一切都正常, 唯有打开事务后插入要出错,
后来Google了下, 发现也有人提到这个.
按照方法修正了, 就ok了.
继续完善了准备拿到209生产环境实践下, 然后扔到svn repoistory上去.
·· Tags: nginx·Python·sqlite·日志处理
February 15, 2009 at 11:42 am · Filed under Gossip, Program
我发现太geeky了也是坏事, 自从我觉得顺序复习单词表效果不好后,
我就自己写了个乱序复习单词的python小程序.
第二天我就觉得不满意, 就用cPickle加上了一个退出时自动把当前复习状态保存到内存里的功能.
当天下午嫌dump出来的文件过大, 又顺便把其bz2化了…
第三天加上了询问每个单词记忆状况的功能, 遗忘的单词会自动重复复习.
第四天觉得无声太无趣了, 就去找了找python的TTS解决方案,
后来找到一个非TTS的解决方案, pyspeech.
用起来倒是很简单, 就是用的windows讲述人的接口, 不过发音太扯淡了,
抓着个单词就乱读, 寒.
后来翻出来买的红宝送的MP3, 倒是读得字正腔圆,
可惜一个list一个MP3, 没法达到乱序复习同步播放的要求.
不过这MP3倒是很体贴的带了lrc文件,
我去下了个MP3切割工具, 发现可以导入cue格式, 就自己又写了个lrc2cue.py把lrc的信息抓出来生成cue,
终于是完成了每个单词独立声音文件的切割…
再写了个脚本完成切割后各个文件的重命名, 和使用lame把MP3转为WAV,
就可以用winsound模块把这个声音放出来了.
程序跑起来的时候, 听着单词发音, 我突然又觉得很无趣了.
damn.
·· Tags: Python
November 2, 2008 at 11:46 pm · Filed under Gossip, Program
Python写的pyMono Bot跑的很欢畅, 自从给xmpppy库里加上了一个每180s发送一次空包的hack后,
几乎没掉过线了, 不过倒是有些古怪的Exceptions经常把bot轰杀至渣.
因为错误处理写得很简单, 所以今天顺便看了下shell的文档,
写了个小shell程序, 挂在cron里, 每小时一次检查bot是否挂掉了.
anyway, I love this way of handling things.
·· Tags: Linux·Python·Shell
Next entries »