Some python segments

import MySQLdb
import subprocess
from smtplib import *
from datetime import date, timedelta

class StatEntry(object):
    def __init__(self, name, count):
        self.name = name
        self.count = count
    def __str__(self):
        return "%s\t%d" % (self.name, self.count)

def fetchdb(date):
    conn = MySQLdb.connect(host="localhost", user="root", passwd="acd", db="cls")
    cursor = conn.cursor()
    cursor.execute("SELECT link, count(*) FROM sdocom WHERE DATE(logtime) = DATE('%s') GROUP BY link" % date)
    rows = cursor.fetchall()
    result = map(lambda x: StatEntry(*x), rows)
    return result

def archive(datelist):
    for date in datelist:
        subprocess.call(["gzip", "cls-"+date+".log"])

def sendmail(results):
    mailcontent = reduce(lambda x,y: x+str(y)+"\n", results, "")
    smtp = SMTP("your.smtp.server")
    smtp.login("user","passwd")
    smtp.sendmail("cls-no-reply@smtp.server", ["your@mail.server"], mailcontent)
    smtp.quit()

def dumpall(data):
    content = reduce(lambda x,y: x+str(y)+"\n", data, "")
    print content

def main():
    yesterday = str(date.today()-timedelta(1))
    results = fetchdb(yesterday)
    #dumpall(results)
    sendmail(results)
    archive([yesterday])

if __name__ == '__main__':
    main()

As log file was imported to database automatically by other process, the script retrieves statistical data from mysql db and sends the result to your mail box via smtp. Also, log file would be compressed by gzip to minimize storage overhead. Add it to crontab, you will get daily statistical report.

This example shows you basic usage of mysql-python lib, smtplib and how to calculate yesterday by datetime.

烧饭再

看了烧饭1,就想看烧饭2.可是我思前想后,烧饭2这个标题总有那么一点不太对劲(大家自己体会),于是还是叫烧饭再吧。

今天介绍酱爆鸡丁,娘的,在北京的夏天吃这个吃得都快吐了,时隔一年本人亲自操刀上阵,不为别的,只为再吐一次。

用料:鸡胸肉一块,黄瓜一根,甜面酱,葱,料酒,酱油,盐,味精,淀粉,糖,自来水,菜刀,案板,锅,电磁炉,油烟机,自行车。。。

主要步骤如下:

  1. 鸡肉化冻,黄瓜大葱洗干净;
  2. 鸡肉切丁,大小以大块熟了小块还没有糊为宜,放碗里加淀粉、盐,抓之;
  3. 黄瓜切丁,大小自便,装盘;
  4. 葱切段,葱的用量大约根据以下公式计算: 葱用量=家里储备葱的总长度/未来可预计的几天內做菜总次数;
  5. 小碗装酱油、料酒、味精、水淀粉、糖搅和成汁备用;
  6. 开火倒油加热冒烟,把1/3葱和鸡丁扔进锅里,炒到洁白的鸡丁如嚼过的口香糖一般出锅;
  7. 锅里留一些油,油少了可以再加一些,待油热,放两勺甜面酱(这里用的是李锦记的沪式甜酱,这个味道比较符合本人年幼时候对甜面酱的最初记忆),把剩下的葱一起扔锅里炒到寂寞为止;
  8. 加黄瓜丁,盐,炒,加鸡丁,炒,加第5步准备的汁,炒;
  9. 等到粘稠之后即可出锅,如果没有粘稠也见好就收吧;
  10. #

有图不一定是真相:

GeoHash

今天偶然看到一个Ruby的GeoHash库,功能非常简单,就是将经纬度坐标哈希成字符串,并且,利用这个字符串可以粗略地比较两点的距离。这个库的代码host在GitHub上,要安装,需要将github加入gem:
sudo gem sources -a http://gems.github.com
sudo gem install davotroy-geohash

用法,irb:
irb(main):001:0> require ‘rubygems’
=> true
irb(main):002:0> require ‘geohash’
=> true
irb(main):003:0> GeoHash.encode(32.168, 118.54)
=> “wtsr12n0nj”
irb(main):004:0> GeoHash.decode(‘wtsr12n0nj’)
=> [32.168, 118.54]

代码可以从github上获得
git clone git://github.com/davetroy/geohash.git

GeoHash的核心部分用C实现,仔细看一下可以发现是一个四叉树的结构:

[codesyntax lang="c"]
#define BASE32	"0123456789bcdefghjkmnpqrstuvwxyz"
static void encode_geohash(double latitude, double longitude, int precision, char *geohash) {
	int is_even=1, i=0;
	double lat[2], lon[2], mid;
	char bits[] = {16,8,4,2,1};
	int bit=0, ch=0;

	lat[0] = -90.0;  lat[1] = 90.0;
	lon[0] = -180.0; lon[1] = 180.0;

	while (i < precision) {
		if (is_even) {
 			mid = (lon[0] + lon[1]) / 2;
 			if (longitude > mid) {
				ch |= bits[bit];
				lon[0] = mid;
			} else
				lon[1] = mid;
		} else {
			mid = (lat[0] + lat[1]) / 2;
			if (latitude > mid) {
				ch |= bits[bit];
				lat[0] = mid;
			} else
				lat[1] = mid;
		}

		is_even = !is_even;
		if (bit < 4)
			bit++;
		else {
			geohash[i++] = BASE32[ch];
			bit = 0;
			ch = 0;
		}
	}
	geohash[i] = 0;
}

[/codesyntax]

可惜在学校的时候没有看到这么精致的代码。

RDF, Sparql query with python

A simple query to test rdf and sparql.

[codesyntax lang="python"]
import sys
import rdflib
from rdflib.Graph import ConjunctiveGraph

g = ConjunctiveGraph()

g.parse(sys.argv[1], format="xml")

fbns = rdflib.Namespace("http://rdf.freebase.com/ns/")

player_refs = g.query("""SELECT ?player
        WHERE {
            ?root fb:soccer.football_roster_position.player ?player .
        }""", initNs={'fb':fbns})
players = []
for player in player_refs:
    gp = ConjunctiveGraph()
    gp.parse(player[0], format="xml")
    results = gp.query("""SELECT ?player_name ?player_position
        WHERE {
            ?player fb:type.object.name ?player_name .
            ?player fb:soccer.football_player.position_s ?player_position .
        }""", initNs={'fb':fbns})
    l = list(results)
    for r in l:
        if r[0].language == 'en':
            players.append(r)

for player in players:
    print player

[/codesyntax]

The query will return all player-position tuple from freebase’s db for specified resource.
To query for players of AC Milan, execute the script with resource location:
python rdfquery.py http://rdf.freebase.com/rdf/en/ac_milan
got:
(rdflib.Literal(‘Yoann Gourcuff’, language=u’en’, datatype=None), rdflib.URIRef(‘http://rdf.freebase.com/ns/en.midfielder’))
(rdflib.Literal(‘Andrea Pirlo’, language=u’en’, datatype=None), rdflib.URIRef(‘http://rdf.freebase.com/ns/en.midfielder’))
(rdflib.Literal(‘Paolo Maldini’, language=u’en’, datatype=None), rdflib.URIRef(‘http://rdf.freebase.com/ns/en.defender’))
(rdflib.Literal(‘Gianluca Zambrotta’, language=u’en’, datatype=None), rdflib.URIRef(‘http://rdf.freebase.com/ns/en.defender’))
(rdflib.Literal(‘Davide Facchin’, language=u’en’, datatype=None), rdflib.URIRef(‘http://rdf.freebase.com/ns/guid.9202a8c04000641f8000000000c75e75′))
(rdflib.Literal(‘Marcus Plinio Diniz Paixao’, language=u’en’, datatype=None), rdflib.URIRef(‘http://rdf.freebase.com/ns/en.defender’))

All resources are stored as rdf:resource references. If you are also Milan fan like me, take a quick look at the players, well, the data is not up to date:)

I have also tried to fetch data for my favorite local team.
python rdfquery.py http://rdf.freebase.com/rdf/en/jiangsu_shuntian
(rdflib.Literal(‘Yao Hanlin’, language=u’en’, datatype=None), rdflib.URIRef(‘http://rdf.freebase.com/ns/en.midfielder’))

烧饭

首先再祝标题中的人生日快乐。

虽说daf同学做菜好看好吃(看出奉承意思的读者请可以买棒棒糖奖励自己),但是这不能成为本人自甘堕落自甘刷碗停滞不前的理由。况且,作为一个口味疑似诡异的人,如果不练好技术,掌握一技之长,将来很难在厨房立足,更不要提取得话语权。甚至没有在饭前进厨房的机会,下场会很惨。

以上是关于烧饭必要性的论述。入正题,今天迎着正午的朝阳,从超市买回了青椒芹菜牛肉鸡肉,为了能让才华体现得淋漓尽致,做了两个菜。简述过程的话大抵是以下update体流程:

  1. 洗菜;
  2. 牛肉切丝(个中坎坷不作赘述),加料酒、淀粉、盐;
  3. 鸡肉切片(个中曲折不必了解),加蛋清、盐、淀粉;
  4. 芹菜切段;
  5. 小碗调酱油、醋、糖、料酒,备用;
  6. 葱姜切末备用;
  7. 开火倒油,油热了加葱姜末和辣椒酱(家里没有正经辣椒酱了,就用辣椒豆豉代替,此决定终遗千古恨),牛肉丝下锅,变色,取出;
  8. 炒芹菜;
  9. 牛肉芹菜混合,再炒,把第5步的混合液体倒进锅里,搅搅,加味精装盘;
  10. 洗锅;
  11. 开火倒油,油热了加葱姜末,鸡肉下锅,待变色后变糊前取出;
  12. 青椒撕碎下锅,不时加水,炒到上一步油烟被吸得差不多为止;
  13. 混合,加味精,出锅。
  14. #

留张照片有图有真相:

关于照片中出现的“暗物质”,绝对不是因为鸡肉片切得太不均匀导致有的糊了有的还没熟,最后葱姜通通糊掉油烟满厨房的结果。还有为什么只有一张照片呢?原因是另一盘菜拍照构图的时候发现需要的曝光时间比较长,没有带三脚架所以拍不出理想的效果,故而没有把照片发上来。画外音:就是酱油放多了太黑了,画外音毕。画外音:把刚才那个画外音的拖出去砍了,画外音毕。

最后引用一句名人名言,你永远不会知道自己的下一盘菜到底是什么味道。