bottle是一个python WSGI框架,简单的一个py文件,集成了router、redirect、template,request/response获取与设定等功能,下面介绍其基本使用方法。
先import相关方法,并声明Bottle对象:
from bottle import Bottle, jinja2_template as template, static_file, redirect, request, response, run
app = Bottle()
Router
利用python的decorator方法,可以声明多个URL对应一个处理函数:
@app.get('/')
@app.get('/index')
def index():
return 'Hello bottle!'
template
template用于将后台代码与前端代码分离,增加后台代码重用:
@app.get('/login')
def login():
return template("login.html", handler=get_site_info())
@app.post('/login')
def login_post():
return UserService.login()
redirect
bottle提供了redirect方法用于页面跳转,如登出后跳转到登录页面:
@app.get('/log-out')
def log_out():
UserService.log_out()
redirect('/login', 302)
request/response
bottle提供了request和response对象,通过这两个对象,可方便地操作请求与响应数据:
@app.get('/admin')
def admin():
_status = request.query.get('status', None)
response.set_cookie('status', _status)
static_file
网页包含html、js、图片等静态内容,处理这些静态内容的请求,我们不需要编写专门的router处理,只需要将静态内容放到一个文件夹下,利用如下一段代码,即可处理所有static文件请求:
@app.get('/static/<filename:re:.*')
def server_static_file(filename):
return static_file(filename, root='./static/')
最后,使用run方法让我们后台服务跑起来:
run(app, host='localhost', port=8080)
Have fun!
2012年12月11日星期二
2012年12月10日星期一
社会化评论系统 ”多说“
多说 是一个评论系统,其整合了新浪微博、豆瓣、人人等多个社交网站评论插件,原先孤立的站点文章、博文可以通过 多说 与社交网站关联起来,利用社交人气活跃站点。
多说 是个开源的评论系统,使用起来也非常简单,先在多说官网进行注册,注册完成后将获得一段代码,将该段代码粘贴到网页代码<body></body>间任意位置,就可以使用多说评论系统。效果如下:
Have fun!
多说 是个开源的评论系统,使用起来也非常简单,先在多说官网进行注册,注册完成后将获得一段代码,将该段代码粘贴到网页代码<body></body>间任意位置,就可以使用多说评论系统。效果如下:
Have fun!
2012年12月9日星期日
新浪微博开放平台应用之数据抓取
新浪微博开放平台为开发者提供了很多API,用于访问或修改各种数据,如微博、评论、话题、收藏、用户标签等。下面展示如何使用“话题”的API,对特定数据进行访问。
新浪微博中的话题,由##括起来,要访问话题数据,需用到 trends/statuses 接口,其接受以下参数:
- source : 所申请的app_key
- trend_name : 要抓取的话题
- count : 抓取条目的数量
通过GET方式(或直接通过游览器),访问以下URL:
http://api.t.sina.com.cn/trends/statuses.json?count=40&source=31641035&trend_name=带上猫咪去旅行
该URL指示获取最多40条,话题包含“带上猫咪去旅行”关键字的微博数据,访问该URL后,可获得以下形式的数据:
[{
"created_at":"Fri Dec 07 23:01:47 +0800 2012",
"id":3520736712709956,
"text":"#带上猫咪去旅行图站#低调内测上线 http://t.cn/zjJypQ5",
"source":"<a href=\"http://weibo.com\" rel=\"nofollow\">新浪微博</a>",
"thumbnail_pic":"http://ww4.sinaimg.cn/thumbnail/66f77025gw1dzlk18f7r3j.jpg",
"bmiddle_pic":"http://ww4.sinaimg.cn/bmiddle/66f77025gw1dzlk18f7r3j.jpg",
"original_pic":"http://ww4.sinaimg.cn/large/66f77025gw1dzlk18f7r3j.jpg",
"user":
{"id":1727492133,
"screen_name":"bangerlee",
"name":"bangerlee",
"province":"44",
"city":"1",
"location":"广东 广州",
"gender":"m",
"created_at":"Fri Apr 09 15:12:15 +0800 2010",
}]
可以看到返回的微博数据包含了我们想要搜索的关键词#带上猫咪去旅行#,另还有微博文字内容、微博图片ip、微博用户名等信息。
通过一个python小程序,我们可以实现数据抓取:
运行以上程序有:
linux # python get_data.py
bangerlee
#带上猫咪去旅行图站#低调内测上线 http://t.cn/zjJypQ5
http://ww4.sinaimg.cn/thumbnail/66f77025gw1dzlk18f7r3j.jpg
Have fun!
2012年11月27日星期二
文件系统缓存控制小工具vmtouch
文件系统缓存的一个作用是加快文件读取速度,vmtouch可用于管理文件系统缓存,是个有意思的小工具。vmtouch有以下功能:
以下为vmtouch使用示例:
最开始 a.txt 文件被载入到缓存中,占用84个page,共336K;使用vmtouch -e 将文件从缓存中清除;使用tail命令读取 a.txt 部分内容,再使用vmtouch进行查看,a.txt 部分内容被载入缓存,占用10个page,40K。
下面是vmtouch的具体实现:
递归查找文件:因为我们向vmtouch传入的可以是目录,最终是要操作该目录下的所有文件,而目录下可能包含目录,因而需要用到递归。vmtouch中vmtouch_crawl函数是个递归函数,若其参数path指示一个目录,则不断递归,是否是目录通过stat结构的st_mode字段判断,vmtouch_crawl函数中用到stat、opendir、readdir系统调用。
打开/映射文件:目录下每个文件最终会跳出递归调用,vmtouch_file函数被vmtouch_crawl调用,用于文件处理。vmtouch_file先判断文件类型,对链接以及过大的文件(500*1024*1024)不进行处理,调用open、mmap完成文件打开和虚拟内存映射。
查询:vmtouch_file调用mincore查询某个文件的缓存占用情况,传入系统调用mincore的第一个参数是mmap的返回值,第二个参数是文件长度值,第三个参数是指向一块pages_in_file大小的内存指针。根据mincore的查询结果,如果一个页面在内存中,则增加pages_in_core等统计值。
载入内存:要将一个文件载入缓存,对其进行读取即可,vmtouch_file中通过对mem的访问操作达到载入文件缓存的目的:
清除缓存:在linux下,清除一个文件相应的缓存可调用posix_fadvise完成,posix_fadvise函数原型如为:int posix_fadvise(int fd, off_t offset, off_t len, int advice); 传入相应文件描述符、文件大小和 POSIX_FADV_DONTNEED 标志即可完成缓存清除。
内存锁:有时候我们系统一些数据长驻内存,不被交换出去,这时我们可通过mlock调用实现,mlock第一个参数为mem,第二个参数为文件长度。
vmtouch可用于“预热”文件系统缓存,有意识地换出冷数据、控制热数据常驻内存,从而减少page fault,增加缓存命中率。
Have fun!
- 查询文件/目录有多少被载入缓存
- 将文件/目录载入缓存
- 将文件/目录从缓存中清除
- 锁定缓存
以下为vmtouch使用示例:
最开始 a.txt 文件被载入到缓存中,占用84个page,共336K;使用vmtouch -e 将文件从缓存中清除;使用tail命令读取 a.txt 部分内容,再使用vmtouch进行查看,a.txt 部分内容被载入缓存,占用10个page,40K。
下面是vmtouch的具体实现:
递归查找文件:因为我们向vmtouch传入的可以是目录,最终是要操作该目录下的所有文件,而目录下可能包含目录,因而需要用到递归。vmtouch中vmtouch_crawl函数是个递归函数,若其参数path指示一个目录,则不断递归,是否是目录通过stat结构的st_mode字段判断,vmtouch_crawl函数中用到stat、opendir、readdir系统调用。
打开/映射文件:目录下每个文件最终会跳出递归调用,vmtouch_file函数被vmtouch_crawl调用,用于文件处理。vmtouch_file先判断文件类型,对链接以及过大的文件(500*1024*1024)不进行处理,调用open、mmap完成文件打开和虚拟内存映射。
查询:vmtouch_file调用mincore查询某个文件的缓存占用情况,传入系统调用mincore的第一个参数是mmap的返回值,第二个参数是文件长度值,第三个参数是指向一块pages_in_file大小的内存指针。根据mincore的查询结果,如果一个页面在内存中,则增加pages_in_core等统计值。
载入内存:要将一个文件载入缓存,对其进行读取即可,vmtouch_file中通过对mem的访问操作达到载入文件缓存的目的:
清除缓存:在linux下,清除一个文件相应的缓存可调用posix_fadvise完成,posix_fadvise函数原型如为:int posix_fadvise(int fd, off_t offset, off_t len, int advice); 传入相应文件描述符、文件大小和 POSIX_FADV_DONTNEED 标志即可完成缓存清除。
内存锁:有时候我们系统一些数据长驻内存,不被交换出去,这时我们可通过mlock调用实现,mlock第一个参数为mem,第二个参数为文件长度。
vmtouch可用于“预热”文件系统缓存,有意识地换出冷数据、控制热数据常驻内存,从而减少page fault,增加缓存命中率。
Have fun!
2012年11月22日星期四
rtags——node.js+redis实现的标签管理模块
引言
在我们游览网页时,随处可见标签的身影:
API
rtags提供以下接口:
首先调用 Tag#createTag 生成一个 Tag 实例,传入一个字符串指示物件的类别,比如 ‘blogs’ 指示博文,‘clothes’ 指示衣服:
var tag = rtags.createTag('blogs');
然后添加该类别的物件和对应的标签,Tag#add 接收两个参数,第一个是物件的标签,有多个标签可用逗号隔开;第二个参数是物件的 id,以下代码中以 strs 下标为 id:
var strs = [];
strs.push('travel,photography,food,music,shopping');
strs.push('music,party,food,girl');
strs.push('mac,computer,cpu,memory,disk');
strs.push('linux,kernel,linus,1991');
strs.push('kernel,process,lock,time,linux');
strs.forEach(function(str, i){ tag.add(str, i); });
经过上面调用,redis 数据库中就有了博文标签数据,我们就可以进行相关查询了。查询某物件具有哪些标签,我们可以调用 Tag#queryID,该函数接收物件 id 和一个回调函数作为参数,查询结果作为数组存放在 ids 中:
tag
.queryID(id = '3')
.end(function(err, ids){
if (err) throw err;
console.log('Tags for "%s":', id);
var tags = ids.join(' ');
console.log(' - %s', tags);
});
以上代码用于查询 id 为 ‘3’ 的博文的标签,执行该段代码,输出为:
Tags for "3":
- kernel linux linus 1991
要查询两个物件具有哪些相同标签,同样调用 Tag#queryID,这时传入的参数应为两个物件的 id 和一个回调函数:
tag
.queryID(id1 = '3', id2 = '4')
.end(function(err, ids){
if (err) throw err;
console.log('Tags for "%s" and "%s" both have:', id1, id2);
var tags = ids.join(' ');
console.log(' - %s', tags);
});
以上代码用于查询 id 为 ‘3’ 和 ‘4’ 的博文共有的标签,查询结果为:
Tags for "3" and "4" both have:
- kernel linux
rtags 还提供根据标签搜索物件的功能,调用 Tag#queryTag,传入标签和一个回调函数,若有多个标签,可用逗号隔开:
tag
.queryTag(tags = 'music,food')
.end(function(err, ids){
if (err) throw err;
console.log('The objects own the "%s" tags:', tags);
var id = ids.join(' ');
console.log(' - %s', id);
process.exit();
});
以上代码查询同时具有 ‘music’ 和 ‘food’ 标签的博文,其输出为:
The objects own the "music,food" tags:
- 0 1
安装
rtags通过以下命令安装,该命令会一同安装rtags依赖的redis模块:
$ npm install rtags
亦可以通过以下命令从 github 获取 rtags 源码:
$ git clone git@github.com:bangerlee/rtags.git
拉起 redis-server,安装 should 模块后,我们可以执行 rtags 源码目录下的例子:
$ cd rtags/test
$ node index.js
github地址: https://github.com/bangerlee/rtags.git
欢迎 git pull/fork/clone。
Have fun!
在我们游览网页时,随处可见标签的身影:
- 进入个人微博主页,可以看到自己/他人的标签,微博系统会推送与你有相同标签的人
- 游览博文,大多数博文有标签标记,以说明文章主旨,方便搜索和查阅
- 网上购物,我们经常使用标签进行商品搜索,如点选 “冬装” + “男士” + “外套” 进行衣物过滤
API
rtags提供以下接口:
- 添加物件及其标签 Tag#add(tags, id[, fn])
- 查询物件的标签 Tag#queryID(id, fn)
- 查询两个物件共有的标签 Tag#queryID(id1, id2, fn)
- 查询具有特定标签的物件 Tag#queryTag(tags, fn)
- 删除物件的标签 Tag#delTag(tags, id[, fn])
- 删除物件 Tag#remove(id[, fn])
首先调用 Tag#createTag 生成一个 Tag 实例,传入一个字符串指示物件的类别,比如 ‘blogs’ 指示博文,‘clothes’ 指示衣服:
var tag = rtags.createTag('blogs');
然后添加该类别的物件和对应的标签,Tag#add 接收两个参数,第一个是物件的标签,有多个标签可用逗号隔开;第二个参数是物件的 id,以下代码中以 strs 下标为 id:
var strs = [];
strs.push('travel,photography,food,music,shopping');
strs.push('music,party,food,girl');
strs.push('mac,computer,cpu,memory,disk');
strs.push('linux,kernel,linus,1991');
strs.push('kernel,process,lock,time,linux');
strs.forEach(function(str, i){ tag.add(str, i); });
经过上面调用,redis 数据库中就有了博文标签数据,我们就可以进行相关查询了。查询某物件具有哪些标签,我们可以调用 Tag#queryID,该函数接收物件 id 和一个回调函数作为参数,查询结果作为数组存放在 ids 中:
tag
.queryID(id = '3')
.end(function(err, ids){
if (err) throw err;
console.log('Tags for "%s":', id);
var tags = ids.join(' ');
console.log(' - %s', tags);
});
以上代码用于查询 id 为 ‘3’ 的博文的标签,执行该段代码,输出为:
Tags for "3":
- kernel linux linus 1991
要查询两个物件具有哪些相同标签,同样调用 Tag#queryID,这时传入的参数应为两个物件的 id 和一个回调函数:
tag
.queryID(id1 = '3', id2 = '4')
.end(function(err, ids){
if (err) throw err;
console.log('Tags for "%s" and "%s" both have:', id1, id2);
var tags = ids.join(' ');
console.log(' - %s', tags);
});
以上代码用于查询 id 为 ‘3’ 和 ‘4’ 的博文共有的标签,查询结果为:
Tags for "3" and "4" both have:
- kernel linux
rtags 还提供根据标签搜索物件的功能,调用 Tag#queryTag,传入标签和一个回调函数,若有多个标签,可用逗号隔开:
tag
.queryTag(tags = 'music,food')
.end(function(err, ids){
if (err) throw err;
console.log('The objects own the "%s" tags:', tags);
var id = ids.join(' ');
console.log(' - %s', id);
process.exit();
});
以上代码查询同时具有 ‘music’ 和 ‘food’ 标签的博文,其输出为:
The objects own the "music,food" tags:
- 0 1
安装
rtags通过以下命令安装,该命令会一同安装rtags依赖的redis模块:
$ npm install rtags
亦可以通过以下命令从 github 获取 rtags 源码:
$ git clone git@github.com:bangerlee/rtags.git
拉起 redis-server,安装 should 模块后,我们可以执行 rtags 源码目录下的例子:
$ cd rtags/test
$ node index.js
github地址: https://github.com/bangerlee/rtags.git
欢迎 git pull/fork/clone。
Have fun!
2012年11月16日星期五
使用libqrencode生成二维码
libqrencode用于生成QR code格式的二维码,其用C编写。相比ZXing支持一维、二维和多种编码格式,libqrencode功能更简单,只针对最常见的QR code,只能用于编码。
libqrencode提供的接口在源码qrencode.h文件中有详细说明,除了编程接口,libqrencode还提供了一个现成的程序用于生成二维码。安装libqrencode后,源码目录下生成qrencode,其用法如下:
./qrencode -s 5 -o bangerlee.png bangerlee.blogspot.com
以上命令将字符串 "bangerlee.blogspot.com" 编码为QR code二维码,其中 -s 指示二维码上黑白小块的大小(单位为像素),-o 指示生成的二维码图像文件名称。
libqrencode支持对中文进行编码。
Have fun!
libqrencode提供的接口在源码qrencode.h文件中有详细说明,除了编程接口,libqrencode还提供了一个现成的程序用于生成二维码。安装libqrencode后,源码目录下生成qrencode,其用法如下:
./qrencode -s 5 -o bangerlee.png bangerlee.blogspot.com
以上命令将字符串 "bangerlee.blogspot.com" 编码为QR code二维码,其中 -s 指示二维码上黑白小块的大小(单位为像素),-o 指示生成的二维码图像文件名称。
libqrencode支持对中文进行编码。
Have fun!
2012年11月13日星期二
Node.js+MongoDB实现短域名功能——开源项目short
MongoDB是一个分布式的文档存储数据库,数据用二进制的JSON格式BSON存储。
设计一个存储博文的数据库表,如果使用关系型数据库,博文本身用一个表存储,评论用另一个单独的表存储,而使用MongoDB,评论可嵌入博文表,一篇完整的博文,其相关信息只需存放在一个表中:
下面来看如何使用Node.js和MongoDB实现短域名功能,主要用到Node.js的Mongoose模块。
首先设计短域名在MongoDB中的保存结构,除原URL、短域名这两个字段要存储外,还可以存储生成时间、访问者等与短域名相关的信息,表结构如下:
以上URL表示缩短前的域名,hash表示短域名。
其次考虑接口,接口很简单,一个接口generate用于接收URL,返回短域名;另一个接口retrieve接收短域名,返回原URL。
最后需要设计一个hash函数实现URL与短域名关联,hash函数供generate函数调用。
generate函数:
以上用到mongoose的save接口,往mongoDB服务器保存短域名数据。
retrieve函数:
findByHash函数中,调用mongoose的findeOne接口,findeOne根据传入的hash值,在mongoDB服务器中查找相应的短域名条目。完成查找后,findByHash再调用mongoose的update接口更新短域名条目中的hits等字段。
hash函数:
hash函数很简单,一个URL通过hasher对应到一个长度为6的 [0-9a-zA-Z]字符串。
调用以上generate接口,完成 URL为 http://nodejs.org/,以及URL为 http://bangerlee.blogspot.com/ 的短域名生成后,使用mongo进行数据查询,我们可以看到:
有了以上短域名功能,我们可以进一步搭建一个提供短域名跳转的服务器,其核心是根据hash,调用retrieve函数,从MongoDB服务器上获取相应的URL,完成域名跳转:
执行以上服务器程序,然后在地址栏输入 http://localhost:8080/GHJwvl ,回车之后就会跳转到 http://bangerlee.blogspot.com/ 。
Have fun!
设计一个存储博文的数据库表,如果使用关系型数据库,博文本身用一个表存储,评论用另一个单独的表存储,而使用MongoDB,评论可嵌入博文表,一篇完整的博文,其相关信息只需存放在一个表中:
下面来看如何使用Node.js和MongoDB实现短域名功能,主要用到Node.js的Mongoose模块。
首先设计短域名在MongoDB中的保存结构,除原URL、短域名这两个字段要存储外,还可以存储生成时间、访问者等与短域名相关的信息,表结构如下:
以上URL表示缩短前的域名,hash表示短域名。
其次考虑接口,接口很简单,一个接口generate用于接收URL,返回短域名;另一个接口retrieve接收短域名,返回原URL。
最后需要设计一个hash函数实现URL与短域名关联,hash函数供generate函数调用。
generate函数:
以上用到mongoose的save接口,往mongoDB服务器保存短域名数据。
retrieve函数:
findByHash函数中,调用mongoose的findeOne接口,findeOne根据传入的hash值,在mongoDB服务器中查找相应的短域名条目。完成查找后,findByHash再调用mongoose的update接口更新短域名条目中的hits等字段。
hash函数:
调用以上generate接口,完成 URL为 http://nodejs.org/,以及URL为 http://bangerlee.blogspot.com/ 的短域名生成后,使用mongo进行数据查询,我们可以看到:
有了以上短域名功能,我们可以进一步搭建一个提供短域名跳转的服务器,其核心是根据hash,调用retrieve函数,从MongoDB服务器上获取相应的URL,完成域名跳转:
执行以上服务器程序,然后在地址栏输入 http://localhost:8080/GHJwvl ,回车之后就会跳转到 http://bangerlee.blogspot.com/ 。
Have fun!
订阅:
博文 (Atom)