<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2381794355363305424</id><updated>2011-07-28T20:32:22.534-07:00</updated><category term='天空'/><category term='END'/><category term='宅男学厨'/><category term='有关工程'/><category term='子曾经曰过'/><category term='算法'/><category term='hacks'/><category term='虚拟化'/><category term='有关数学'/><category term='锤子'/><title type='text'>重剑无锋 大巧不工</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>28</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-394782250168874262</id><published>2010-10-22T19:50:00.000-07:00</published><updated>2010-10-22T19:50:48.451-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='END'/><title type='text'>离开</title><content type='html'>这个十月,我离开了那个熟悉的城市。经历了一些事情,认识了一些人,想说的太多,但是在这个离别的时候,却又什么都不想说。就如散伙饭上接连的23杯酒一样,意识模糊却又感受深刻...&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;朋友们,珍重!虽然写在这里,可能你们都看不见.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;这个十月,我来到了这个陌生的城市，陪伴可爱的兜兜。这个城市很大,但是也很疏离...给自己定了两年的目标,希望一步一步脚踏实地能够走好.越发的意识到自己肩上的责任和压力是那么的清晰和重大。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;这份新生活的开始,我需要对伟铭大哥道一声谢谢,虽然你也可能看不见:)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;说点和标题相关的吧,这个博客将不再更新.新的博客地址是&amp;nbsp;http://guangfeng.blogspot.com 依旧在伟大的"X"之外...&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;END&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-394782250168874262?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/394782250168874262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2010/10/blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/394782250168874262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/394782250168874262'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2010/10/blog-post.html' title='离开'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-847297220420860163</id><published>2010-05-14T01:10:00.000-07:00</published><updated>2010-05-14T01:17:12.835-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hacks'/><category scheme='http://www.blogger.com/atom/ns#' term='天空'/><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><title type='text'>并行计算框架 ParallelPython</title><content type='html'>如何在有限的硬件条件下,使程序耗时更少,或者处理数据量更大?&lt;br /&gt;&lt;br /&gt;这个问题在进入多核时代以来,似乎多了一种解决途径,那就是充分利用多处理器(核)来并行的完成计算任务.&lt;br /&gt;&lt;br /&gt;这里的多处理环境可以是指一台拥有多核处理器甚至多颗处理器的服务器,也可以是指一个拥有多节点的计算机群。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;针对开篇提出的那个问题,解决办法其实都是"分而治之"。从数据分割入手,我们可以得到类似MapReduce的解决方案,类似的Python实现也有不少;从程序角度去看,目前主要是以下几种途径:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;大规模并行处理系统(MPP,&lt;i&gt;&lt;b&gt;Figure 1&lt;/b&gt;&lt;/i&gt;) &lt;/li&gt;&lt;li&gt;对称多处理(SMP,&lt;i&gt;&lt;b&gt;Figure 2&lt;/b&gt;&lt;/i&gt;)&lt;/li&gt;&lt;li&gt; 分布式计算(集群/网格计算,&lt;i&gt;&lt;b&gt;Figure 3&lt;/b&gt;&lt;/i&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_RLf4SUMna24/S-z7rxg9-HI/AAAAAAAAAk4/Zy42Oe0QKJo/s1600/MPP.GIF" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://3.bp.blogspot.com/_RLf4SUMna24/S-z7rxg9-HI/AAAAAAAAAk4/Zy42Oe0QKJo/s320/MPP.GIF" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&amp;nbsp;&lt;i&gt;&lt;b&gt;Figure 1 MPP&lt;/b&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_RLf4SUMna24/S-z8bsG4l5I/AAAAAAAAAlA/iRTvj1sJaG4/s1600/smp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="228" src="http://1.bp.blogspot.com/_RLf4SUMna24/S-z8bsG4l5I/AAAAAAAAAlA/iRTvj1sJaG4/s320/smp.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;&lt;b&gt;Figure 2 SMP&lt;/b&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;i&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;a href="http://2.bp.blogspot.com/_RLf4SUMna24/S-z85HvvgBI/AAAAAAAAAlI/1zVP1BjJmLE/s1600/Us-nasa-columbia.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_RLf4SUMna24/S-z85HvvgBI/AAAAAAAAAlI/1zVP1BjJmLE/s320/Us-nasa-columbia.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;i&gt;&lt;b&gt;Figure 3 Cluster&lt;/b&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;本文主要介绍的ParallelPython(简称pp)框架可以有效支持SMP和集群方式进行并行计算。&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;i&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;根据官方介绍&lt;i&gt;&lt;b&gt;,&lt;/b&gt;&lt;/i&gt;pp提供了在SMP(多CPU或多核)和集群(通过网络连接的多台计算机)上并行执行Python代码的机制,具有以下特性:&lt;/div&gt;&lt;ul&gt;&lt;li&gt;在SMP和集群上并行执行Python代码&lt;/li&gt;&lt;li&gt;易于理解和实现的基于工作的并行机制，便于把穿行应用转换成并行的&lt;/li&gt;&lt;li&gt;自动构造最佳配置(默认时工作进程数量等同于系统处理器数量)&lt;/li&gt;&lt;li&gt;动态处理器分配(允许运行时改变工作处理器数量)&lt;/li&gt;&lt;li&gt;函数的工作缓存(透明的缓存机制确保后续调用降低负载)&lt;/li&gt;&lt;li&gt;动态负载均衡(任务被动态的分配到各个处理器上)&lt;/li&gt;&lt;li&gt;基于SHA的连接加密认证&lt;/li&gt;&lt;li&gt;跨平台移植(Windows/Linux/Unix)&lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: left;"&gt;和传统的线程模型不同的是,thread和threading模块无法在字节码一级实现并行。因为Python解释器使用GIL(全局解释器锁)来在内部禁止并行执行。这个GIL限制你在SMP机器上同一时间也 只能执行一条字节码指令。而pp在内部使用进程和进程间通信来组织并行计算。并隐藏了所有内部的细节和复杂性，应用程序只需要提交工作任务并取回结果就可以了。&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;代码说话:&lt;/div&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;import pp&lt;br /&gt;nodes = ('10.0.0.1',)&lt;br /&gt;jober = pp.Server(ppservers=nodes)&lt;br /&gt;f = jober.submit(&lt;i&gt;func,args,depfunc,module&lt;/i&gt;)&lt;/div&gt;&lt;br /&gt;&lt;b&gt;submit&lt;/b&gt;函数接受worker具体执行的函数&lt;i&gt;func&lt;/i&gt;,参数args以及&lt;i&gt;func&lt;/i&gt;内部调用的函数&lt;i&gt;depfunc&lt;/i&gt;和涉及到的模块&lt;i&gt;module&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;相应的节点机器上执行:&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;./ppservers.py&lt;/div&gt;&lt;br /&gt;不过节点机器上可能会报错"&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Socket connection is broken&lt;/span&gt;".解决办法如下:&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;class Close(Exception):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pass&lt;br /&gt;&lt;br /&gt;def send(self, data):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bufsz = self.bufsz&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; t_size = len(data)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; size = struct.pack('!Q', t_size)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p_size = self.socket.send(size)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if p_size == 0:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise Close('end connection')&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; s_size = 0L&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while s_size &amp;lt; t_size:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nd_sz = min(bufsz, t_size - s_size)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; p_size = self.socket.send(data[s_size:s_size+nd_sz])&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if p_size == 0:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; raise Close('end connection')&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; s_size += p_size&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-847297220420860163?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/847297220420860163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2010/05/parallelpython.html#comment-form' title='27 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/847297220420860163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/847297220420860163'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2010/05/parallelpython.html' title='并行计算框架 ParallelPython'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_RLf4SUMna24/S-z7rxg9-HI/AAAAAAAAAk4/Zy42Oe0QKJo/s72-c/MPP.GIF' height='72' width='72'/><thr:total>27</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-4190958381700658280</id><published>2010-05-13T03:02:00.000-07:00</published><updated>2010-05-13T03:04:33.217-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><title type='text'>并发编程利器Eventlet</title><content type='html'>&lt;span style="font-size: small;"&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;a href="http://eventlet.net/"&gt;Eventlet&lt;/a&gt;是由第二人生(&lt;a href="http://secondlife.com/"&gt;Secondlife&lt;/a&gt;)开源的高度伸缩性的Python网络编程库.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;根据官方介绍大致特性如下:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;非阻塞I/O模型&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;协程(Coroutines)使得开发者可以采用阻塞式的开发风格,却能够实现非阻塞I/O的效果&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;隐式事件调度,使得可以在Python解释器或者应用程序的某一部分去使用Eventlet&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;关于协程,大致可以理解成允许子程序可以多次暂停和恢复执行,是实现多任务的一种有效手段,具体见&lt;a href="http://en.wikipedia.org/wiki/Coroutine#cite_note-0"&gt;这里&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;在Python的世界里,实现了nonblocking I/O的产品并不算少.比如内置的Asyncore和著名的Twisted.相比之下,Eventlet是更容易上手和使用的。&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;举个例子&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;import eventlet&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;pool = eventlet.GreenPool()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;while True:&amp;nbsp;&amp;nbsp;&amp;nbsp; pool.spawn(&lt;i&gt;func,args&lt;/i&gt;)&lt;/span&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;上面这段代码,几乎就是使用eventlet的范式：&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;GreenPool 用来实现协程,保证并行;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;Spawn&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 用来调用相应的函数,完成具体业务.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size: small;"&gt;每个func之间切换，实施“你运行一会、我运行一会”，并且在进行切换时必须指定何时切换以及切换到哪，当出现阻塞时，就显式切换到另一 段没有被阻塞的代码段执行，直到原先的阻塞状况消失以后，再人工切换回原来的代码段继续处理.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;Eventlet内置提供了一个基于上述原理实现的数据库连接池,目前仅支持MySQL和PostgreSQL.为了测试其性能如何,我参考了&lt;a href="http://gashero.yeax.com/?p=25"&gt;gashero的这篇文章&lt;/a&gt;,并简化了测试方案.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;测试对象分别是MySQLdb(MySQL驱动的Python封装),Eventlet.db_pool,DBUtils&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;测试代码如下:&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;import time&lt;br /&gt;import random&lt;br /&gt;import MySQLdb&lt;br /&gt;import eventlet.db_pool as db_pool&lt;br /&gt;from DBUtils.PooledDB import PooledDB&lt;br /&gt;&lt;br /&gt;conn_kwargs={'host':'192.168.8.84','user':'root','passwd':'','db':'logs'}&lt;br /&gt;sql="""SELECT * FROM test WHERE id=%d"""&lt;br /&gt;pooled=db_pool.ConnectionPool(MySQLdb,**conn_kwargs)&lt;br /&gt;pooldb=PooledDB(MySQLdb,**conn_kwargs)&lt;br /&gt;&lt;br /&gt;def query(conn):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cur=conn.cursor()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; cur.execute(sql%(random.randint(1,1000)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; data=cur.fetchall()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return cur&lt;br /&gt;&lt;br /&gt;def print_now():&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print time.strftime("%H:%M:%S")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;br /&gt;&lt;br /&gt;def test1(times):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_now()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i in range(0,times):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn=MySQLdb.connect(**conn_kwargs)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; r = query(conn)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; r.close()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.close()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_now()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;br /&gt;&lt;br /&gt;def test2(times):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_now()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i in range(0,times):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn=pooled.get()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; query(conn)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; finally:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pooled.put(conn)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_now()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;br /&gt;&lt;br /&gt;def test3(times):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_now()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i in range(0,times):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn=pooldb.connection()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; r=query(conn)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; r.close()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; conn.close()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print_now()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/div&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;然后进入Python解释器交互环境&lt;/span&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Python -i db-pool-test.py&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; test1(10000) //MySQLdb&lt;br /&gt;16:04:34&lt;br /&gt;16:11:25&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; test2(10000) //Event&lt;br /&gt;16:12:35&lt;br /&gt;16:15:22&lt;br /&gt;&amp;gt;&amp;gt;&amp;gt; test3(10000) //DBUtils&lt;br /&gt;16:15:28&lt;br /&gt;16:18:09&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;总体来看,和传统的MySQLdb相比,性能有了很大的提升,和DBUtils差别并不是很明显.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;协程凶猛啊!&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-4190958381700658280?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/4190958381700658280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2010/05/eventlet.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/4190958381700658280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/4190958381700658280'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2010/05/eventlet.html' title='并发编程利器Eventlet'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-484646800913905074</id><published>2010-04-27T23:19:00.000-07:00</published><updated>2010-04-27T23:21:14.926-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='算法'/><category scheme='http://www.blogger.com/atom/ns#' term='有关数学'/><title type='text'>通过权重评分得到更美味的番茄炒蛋</title><content type='html'>哼哼,我首先声明这不是一篇cookbook文:)&lt;br /&gt;&lt;br /&gt;在今天互联网上,我们可以广泛的看到用户反馈(评分)系统的身影.评价区间有1-10分的心理测评,自然也有超级简单的+/-法:譬如很赞一个美女的时候,你可以送个玫瑰或者番茄啥的,不以为然的时候更可以砸个鸡蛋过去.&lt;br /&gt;&lt;br /&gt;举个例子,如果一篇文章写得很不错,有100个人参与评价,80个人给了1,20个人给了0,那么这篇文章的评分(rating)应该是0.8.越是很有可能以加粗高亮的方式推荐给其他用户,得到了很不错的点击率.这时,问题就出来了:rating值很高的资源就一定真的评价高么?&lt;br /&gt;&lt;br /&gt;好吧,请允许我邪恶的想一下,如果某用户写了一篇文章,然后自己先给打几个1分.于是,史上最满意文章(rating值是1)就这样来到了我们的网站！&lt;br /&gt;&lt;br /&gt;想象一下大多数新产生的资源不是得分极高(评价少,分数普遍高)就是得分极低(无人问津).这也是上述评分机制一个非常突出的缺陷.我们意识到:对于那些只有极少数评价的资源,他们的rating相较于那些有着极多评价的资源缺乏一定的&lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif;"&gt;“&lt;b&gt;certainty&lt;/b&gt;” or “&lt;b&gt;believability&lt;/b&gt;”&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif;"&gt;因此,我们需要"修正"一下这个计算方法:&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif;"&gt;对于评价很少的资源,可以认为其本身既不受欢迎也没有啥争议(不能引起话题).它的rating更应该去接近去整体评价的平均水平;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif;"&gt;那些评价很多的资源,通过修正也更多的体现出"相对的高",也就是更多的接近其本来的rating.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;那么,我们可以给所有资源的平均rating和特定评价资源的平均rating各引入一个权值.这个权值就是整体平均评价人数和资源评价人数.这里的整体平均评价人数的设定可以根据真实的计算得出(动态值),当然也可以自己根据喜好设定一个.值越小说明你对评分要求越不严格，影响rating所需要的票数越少；值越大说明你越在意样本过少所带来的负面影响，同时说明资源必须保证一定的人气.&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;br = ( (avg_num_votes * avg_rating) + (this_num_votes * this_rating) )/(avg_num_votes + this_num_votes)&lt;/div&gt;&lt;br /&gt;其中:&lt;br /&gt;&lt;ul style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;li&gt;avg_num_votes:整体平均评价人数&lt;/li&gt;&lt;li&gt;avg_rating:资源平均rating&lt;/li&gt;&lt;li&gt;this_num_votes:待评价资源人数&lt;/li&gt;&lt;li&gt;this_rating:待评价资源rating&lt;/li&gt;&lt;/ul&gt;&lt;ul style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;/ul&gt;这也就是江湖上赫赫有名的&lt;b&gt;贝叶斯评价&lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif;"&gt;(Bayesian probability&lt;/span&gt;&lt;span class="Apple-style-span" style="border-collapse: separate; color: black; font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"&gt;&lt;span class="Apple-style-span" style="font-size: 13px; line-height: 19px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif;"&gt;)&lt;/span&gt;,&lt;/b&gt;更多信息可以围观&lt;a href="http://en.wikipedia.org/wiki/Bayesian_probability"&gt;维基百科&lt;/a&gt;.&lt;br /&gt;实际上这种评分系统广泛适用于很多知名的&lt;span style="font-family: &amp;quot;Trebuchet MS&amp;quot;,sans-serif;"&gt;WEB&lt;/span&gt;2.0站点.&lt;br /&gt;&lt;br /&gt;目前正在火热举行的&lt;a href="http://ent.hunantv.com/v/flowers/index.html"&gt; 花儿朵朵&lt;/a&gt;等选秀活动,可以考虑在此基础上增加一个"人的可信度"(来鉴别社区、论坛的马甲号,具体可以采用积分等手段),这样或许对提高选手评价的准确性和有效性起到一定的积极作用,也可以衍生出更多有趣的现象.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-484646800913905074?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/484646800913905074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2010/04/blog-post_27.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/484646800913905074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/484646800913905074'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2010/04/blog-post_27.html' title='通过权重评分得到更美味的番茄炒蛋'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-543141295952430839</id><published>2010-04-24T22:14:00.000-07:00</published><updated>2010-04-24T22:14:34.773-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='宅男学厨'/><title type='text'>上图不说话</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://farm5.static.flickr.com/4054/4550208950_0afb3ec308.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://farm5.static.flickr.com/4054/4550208950_0afb3ec308.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-543141295952430839?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/543141295952430839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2010/04/blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/543141295952430839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/543141295952430839'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2010/04/blog-post.html' title='上图不说话'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm5.static.flickr.com/4054/4550208950_0afb3ec308_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-7251501303522778600</id><published>2010-04-15T20:33:00.000-07:00</published><updated>2010-04-15T20:33:58.475-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='算法'/><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><title type='text'>芒果圈SNS用户社交分析图谱[上]</title><content type='html'>SNS(Social Networking Services,传说中的社会化网络服务)是当今互联网上很潮的一个应用.专指旨在帮助人们建立社会性网络的互联网应用服务.&lt;br /&gt;&lt;br /&gt;几乎各大互联网公司都推出了类似的产品,公司的&lt;a href="http://home.hunantv.com/"&gt;芒果圈&lt;/a&gt;就是其中之一.上线运营小半年以来,各项指标都还不错,基本保持平稳增长趋势. 某个月黑风高的夜晚,我突然心血来潮,想看看社区当中用户的交往情况如何,也可以为下一阶段若干产品开发提供相关思路.&lt;br /&gt;&lt;br /&gt;从用户评论关系入手,通过数据库将数据做了格式化(csv),通过对偶来表示用户之间的交互:&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white;"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;3,14822&amp;nbsp;&amp;nbsp; //3号用户对14822号用户评论了一次哦&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;4,14822&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;14822,4&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;5,14880&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;这个简单的数据表示的关系图是这样的&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://farm5.static.flickr.com/4055/4525053776_0728373a63_o.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://farm5.static.flickr.com/4055/4525053776_0728373a63_o.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;最终得到的数据大约有20万个左右这样的点,将所有的节点和边的关系映射出来之后得到:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://farm5.static.flickr.com/4024/4524439317_b5c56dd910_b.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://farm5.static.flickr.com/4024/4524439317_b5c56dd910_b.jpg" width="452" /&gt;&lt;/a&gt;&lt;/div&gt;中间那个蓝色的点是我们的客服,围绕在周围的几乎就是社区的意见领袖了,大量的3-4节点自组织结构说明社区存在很多彼此熟悉的小圈子.看来初步验证了有人的地方就有江湖啊&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-7251501303522778600?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/7251501303522778600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2010/04/sns.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/7251501303522778600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/7251501303522778600'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2010/04/sns.html' title='芒果圈SNS用户社交分析图谱[上]'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm5.static.flickr.com/4024/4524439317_b5c56dd910_t.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-8138702311429590981</id><published>2010-03-16T02:10:00.000-07:00</published><updated>2010-03-16T02:11:14.473-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><title type='text'>I don't wanna miss you</title><content type='html'>兜兜去了广州.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.youtube.com/watch?v=Vo_0UXRY_rY"&gt;I don't want to miss a thing&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I could stay awake just to hear you breathing&lt;br /&gt;&lt;br /&gt;Watch you smile while you are sleeping&lt;br /&gt;&lt;br /&gt;While you're far away and dreaming&lt;br /&gt;&lt;br /&gt;I could spend my life in this sweet surrender&lt;br /&gt;&lt;br /&gt;I could stay lost in this moment forever&lt;br /&gt;&lt;br /&gt;Every moment spent with you is a moment I treasure&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I don't wanna close my eyes&lt;br /&gt;&lt;br /&gt;I don't wanna fall asleep&lt;br /&gt;&lt;br /&gt;Cause I'd miss you, baby&lt;br /&gt;&lt;br /&gt;And I don't wanna miss a thing&lt;br /&gt;&lt;br /&gt;Cause even when I dream of you&lt;br /&gt;&lt;br /&gt;The sweetest dream will never do&lt;br /&gt;&lt;br /&gt;I'd still miss you, baby&lt;br /&gt;&lt;br /&gt;And I don't wanna miss a thing&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Lying close to you feeling your heart beating&lt;br /&gt;&lt;br /&gt;And I'm wondering what you're dreaming&lt;br /&gt;&lt;br /&gt;Wondering if it's me you're seeing&lt;br /&gt;&lt;br /&gt;Then I kiss your eyes and thank God we're together&lt;br /&gt;&lt;br /&gt;And I just wanna stay with you&lt;br /&gt;&lt;br /&gt;In this moment forever, forever and ever&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I don't wanna close my eyes&lt;br /&gt;&lt;br /&gt;I don't wanna fall asleep&lt;br /&gt;&lt;br /&gt;Cause I'd miss you, baby&lt;br /&gt;&lt;br /&gt;And I don't wanna miss a thing&lt;br /&gt;&lt;br /&gt;Cause even when I dream of you&lt;br /&gt;&lt;br /&gt;The sweetest dream will never do&lt;br /&gt;&lt;br /&gt;I'd still miss you, baby&lt;br /&gt;&lt;br /&gt;And I don't wanna miss a thing&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I don't wanna miss one smile&lt;br /&gt;&lt;br /&gt;I don't wanna miss one kiss&lt;br /&gt;&lt;br /&gt;Well, I just wanna be with you&lt;br /&gt;&lt;br /&gt;Right here with you, just like this&lt;br /&gt;&lt;br /&gt;I just wanna hold you close&lt;br /&gt;&lt;br /&gt;Feel your heart so close to mine&lt;br /&gt;&lt;br /&gt;And stay here in this moment&lt;br /&gt;&lt;br /&gt;For all the rest of time&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Don't wanna close my eyes&lt;br /&gt;&lt;br /&gt;Don't wanna fall asleep&lt;br /&gt;&lt;br /&gt;Cause I'd miss you, baby&lt;br /&gt;&lt;br /&gt;And I don't wanna miss a thing&lt;br /&gt;&lt;br /&gt;Cause even when I dream of you&lt;br /&gt;&lt;br /&gt;The sweetest dream will never do&lt;br /&gt;&lt;br /&gt;Cause I'd still miss you, baby&lt;br /&gt;&lt;br /&gt;And I don't wanna miss a thing&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I don't wanna close my eyes&lt;br /&gt;&lt;br /&gt;I don't wanna fall asleep&lt;br /&gt;&lt;br /&gt;Cause I'd miss you, baby&lt;br /&gt;&lt;br /&gt;And I don't wanna miss a thing&lt;br /&gt;&lt;br /&gt;Cause even when I dream of you&lt;br /&gt;&lt;br /&gt;The sweetest dream will never do&lt;br /&gt;&lt;br /&gt;I'd still miss you, baby&lt;br /&gt;&lt;br /&gt;And I don't wanna miss a thing&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Don't wanna close my eyes&lt;br /&gt;&lt;br /&gt;Don't wanna fall asleep, yeah&lt;br /&gt;&lt;br /&gt;I don't wanna miss a thing&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;''世界末日''主題曲中文翻譯&lt;br /&gt;&lt;br /&gt;I don't want to miss a thing(我不願錯過這一切)&lt;br /&gt;&lt;br /&gt;為了聽見你的呼吸，我可以不睡&lt;br /&gt;&lt;br /&gt;在你沉睡時，注視著你的笑容&lt;br /&gt;&lt;br /&gt;當你夢見遠方&lt;br /&gt;&lt;br /&gt;我願用一輩子甜蜜的臣服於你&lt;br /&gt;&lt;br /&gt;永遠迷失在這片刻間&lt;br /&gt;&lt;br /&gt;和你在一起的每一刻都是我所珍愛的時刻&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;不願閉上眼睛&lt;br /&gt;&lt;br /&gt;不願入睡&lt;br /&gt;&lt;br /&gt;因為我可能會錯過你，寶貝&lt;br /&gt;&lt;br /&gt;我不願錯過這一切&lt;br /&gt;&lt;br /&gt;因為即使我夢見你&lt;br /&gt;&lt;br /&gt;最美的夢也無法取代&lt;br /&gt;&lt;br /&gt;我依然想念你，寶貝&lt;br /&gt;&lt;br /&gt;我不願錯過任何事&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;躺在你身旁，感覺著你的心跳&lt;br /&gt;&lt;br /&gt;我想知道你夢見了什麼&lt;br /&gt;&lt;br /&gt;你是否在夢中遇見了我&lt;br /&gt;&lt;br /&gt;於是，我吻了你的雙眼&lt;br /&gt;&lt;br /&gt;感謝上帝讓我倆在一起&lt;br /&gt;&lt;br /&gt;我要永遠和你停留在這個時刻&lt;br /&gt;&lt;br /&gt;生生世世&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;我不願錯過任何一個笑容&lt;br /&gt;&lt;br /&gt;我不願錯過任何一個吻&lt;br /&gt;&lt;br /&gt;我就是要和你在一起&lt;br /&gt;&lt;br /&gt;像現在一樣&lt;br /&gt;&lt;br /&gt;我要緊緊的抱著你&lt;br /&gt;&lt;br /&gt;感受你的心貼近我的心&lt;br /&gt;&lt;br /&gt;在此時此地&lt;br /&gt;&lt;br /&gt;和我倆的餘生&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-8138702311429590981?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/8138702311429590981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2010/03/i-dont-wanna-miss-you.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/8138702311429590981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/8138702311429590981'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2010/03/i-dont-wanna-miss-you.html' title='I don&apos;t wanna miss you'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-5090847552808463799</id><published>2010-02-01T05:28:00.000-08:00</published><updated>2010-02-01T05:28:39.886-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><title type='text'>22岁,人生第一个十万....</title><content type='html'>05年大一,看着宿舍楼下"IT培训成就十万年薪"的商业广告,我嘴角的微笑告诉别人,我的不屑.作为ACM教练的我,觉得这个数字很容易得到...&lt;br /&gt;&lt;br /&gt;07年大三,退学的我,为了生计每日奔波,做着一个普通的埃踢民工,会因为每月10号多出来的2k而欢呼不已,会在周末的时候带着兜兜出去"吃大餐",那年我看到一套房子的首付也不需要十万...&lt;br /&gt;&lt;br /&gt;09年正式工作刚好一年,出来混社会差不多两年,我每日在忙碌工作之余,常常在想啥时候能年薪十万丫,兜兜告诉我不急,生活的意义不在于此...另一方面我开始留恋数码新品,开始讲究生活质量,却没有为兜兜做过什么让她可以放下担心的事情....这一年,我的东西多了,兜兜的没变多少&lt;br /&gt;&lt;br /&gt;10年2月1日,财务的变动让我开始关心今年自己的总收入到底有多少,在网银的总计一栏我赫然发现那个数字超过了十万,而我似乎开始麻木了...&lt;br /&gt;&lt;br /&gt;再过几个小时就是我23岁的生日,十万,一个曾经的梦想对我来说承载了太多的回忆和承诺.比这些更重要的是 感谢兜兜从那个时候开始就一直在我身边,无论是几平米的小屋,抑或是下雪天去雪地里刨食,不论是我赋闲待业,也不论我是连续加班,不离不弃.而我欠她的太多太多...&lt;br /&gt;如果说男人天生需要奋斗，那么世俗的金钱和权利即是一座座里程碑,那么这样一个开始或许意味着前方将有更难走的路和更难爬的山,但是这些之后的风光是否更加美丽,更加绚丽?&lt;br /&gt;&lt;br /&gt;默默许下人生第二个心愿,希望在这个路标之后,到达下一个真正意义上的里程碑的时候,我可以看到兜兜在我身边幸福的微笑.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-5090847552808463799?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/5090847552808463799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2010/02/22.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/5090847552808463799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/5090847552808463799'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2010/02/22.html' title='22岁,人生第一个十万....'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-9161916884646889205</id><published>2010-01-05T09:02:00.000-08:00</published><updated>2010-01-05T19:47:40.760-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='锤子'/><title type='text'>使用awk处理网站访问日志[上]</title><content type='html'>对于一个程序来说,Loging是一件非常有利的武器,其可以帮助程序员快速的找到BUG,分析性能瓶颈等等...甚至还可以在技术社区彰显一番代码的华丽,实乃死coder居家旅行必备之宝.而网站访问日志除了对开发者有修改缺陷,提升功力之良效以外,对待运营人员,也是分析用户行为的第一手宝贵资料.&lt;br /&gt;&lt;br /&gt;本博打算通过若干系列文章来讲讲如何有效运用访问日志来改善程序和用户行为分析:)也就是说:站在程序员的角度来审视程序的运行状态;通过数字手段来分析用户访问状况&lt;br /&gt;&lt;br /&gt;既然一切都从访问日志开始,那么首先就来parser weblog吧.让数据变得更加可读些,嘿嘿,自然也更方便处理些.&lt;br /&gt;这里的日志格式如下:&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;124.205.30.210 - - [14/Dec/2009:16:02:46 +0800] "GET /HLRelationLog/ent.hunantv.com/y/l/20090306/225172.html H&lt;br /&gt;TTP/1.1" 404 252&lt;br /&gt;124.205.30.210 - - [14/Dec/2009:16:04:51 +0800] "GET /HLRelationLog/ent.hunantv.com/y/l/20090901/410652.html H&lt;br /&gt;TTP/1.1" 404 252&lt;br /&gt;211.152.32.122 - - [14/Dec/2009:16:15:10 +0800] "GET /manager/html HTTP/1.1" 404 210&lt;br /&gt;124.205.30.210 - - [14/Dec/2009:17:02:18 +0800] "GET / HTTP/1.1" 200 44&lt;br /&gt;124.205.30.210 - - [14/Dec/2009:17:02:19 +0800] "GET /favicon.ico HTTP/1.1" 404 209&lt;br /&gt;124.205.30.210 - - [14/Dec/2009:17:24:59 +0800] "GET /HLRelationLog/ent.hunantv.com/x/20090616/331092.html"&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;格式很简单:来路IP,本地时间,以及访问的路径.实际情况下往往还有一个User-Agent.但是在本篇我们无视这个参数.先将这些数据"取"出来存入数据库再说.&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black;"&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;awk -F ' ' '/HLRelationLog/ {printf("insert into logs (url,ip,time) values (\"%s\",\"%s\",\"%s\");",$7,$1,substr($4,2))}' access.log &amp;gt; target.sql&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;然后将数据导入&lt;br /&gt;&lt;/div&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mysql -u root -p -h 8.8.8.8 &amp;lt; target.sql &lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;这里简单再来看看大致的访问情况:&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;awk -F ' ' '/HLRelationLog/ {print $7}' access.log |sort|uniq -c|sort -nr &amp;gt; sort.txt&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;结果摘抄如下:&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;13102 /HLRelationLog/ent.hunantv.com/e/h/20080917/49514.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 7112 /HLRelationLog/ent.hunantv.com/e/h/20080719/23308.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 6539 /HLRelationLog/ent.hunantv.com/m/20091231/536520.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 6451 /HLRelationLog/ent.hunantv.com/m/20090427/281233.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 5739 /HLRelationLog/ent.hunantv.com/m/20091222/527487.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 5248 /HLRelationLog/ent.hunantv.com/x/20091224/529517.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4863 /HLRelationLog/ent.hunantv.com/y/20091219/524512.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4597 /HLRelationLog/ent.hunantv.com/m/20091221/526802.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4168 /HLRelationLog/ent.hunantv.com/m/20091221/526782.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 4162 /HLRelationLog/ent.hunantv.com/y/20081028/87956.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 3951 /HLRelationLog/ent.hunantv.com/m/20091222/527342.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 3729 /HLRelationLog/ent.hunantv.com/e/20080716/22250.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 3631 /HLRelationLog/ent.hunantv.com/e/h/20080728/26581.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 3561 /HLRelationLog/ent.hunantv.com/m/20091222/527785.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 3372 /HLRelationLog/ent.hunantv.com/e/h/20080903/42076.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 3339 /HLRelationLog/ent.hunantv.com/y/20091216/522056.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 3163 /HLRelationLog/ent.hunantv.com/y/l/20091221/525879.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 2998 /HLRelationLog/ent.hunantv.com/y/20091216/521082.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 2914 /HLRelationLog/ent.hunantv.com/x/20091221/526583.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 2889 /HLRelationLog/ent.hunantv.com/y/20081231/154998.html&lt;br /&gt;&amp;nbsp;&amp;nbsp; 2851 /HLRelationLog/ent.hunantv.com/z/20091225/530766.html&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;下面来处理下频道的访问分布,每个link的倒数第三段[x,y,e...]:首先通过awk得到每个link的频道的识别符和访问数量,丢进一个文件&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;map(lambda x:[x,sum(map(lambda y:int(y[1]),filter(lambda z:z[0]==x,t)))],set(map(lambda x:x[0],t))) &lt;br /&gt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;[['x\n', 48173], ['y\n', 266146], ['d\n', 4035], ['z\n', 40631], ['e\n', 98009], ['ent\n', 558], ['m\n', 174542], ['t\n', 59660]]&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;来看看并发的情况: &lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;tail -10000 access.log | awk '{print $4;}' | sort | uniq -c | sort -nr | head&lt;br /&gt;&lt;br /&gt;=====我是分割线====&lt;br /&gt;&lt;br /&gt;33 [31/Dec/2009:22:03:18&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 16 [25/Dec/2009:18:16:07&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 14 [25/Dec/2009:18:16:06&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 9 [31/Dec/2009:22:03:19&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8 [25/Dec/2009:18:13:35&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7 [31/Dec/2009:22:06:38&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7 [31/Dec/2009:19:22:40&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7 [25/Dec/2009:19:55:54&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7 [25/Dec/2009:14:39:06&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7 [02/Jan/2010:18:37:54&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-9161916884646889205?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/9161916884646889205/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2010/01/awk.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/9161916884646889205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/9161916884646889205'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2010/01/awk.html' title='使用awk处理网站访问日志[上]'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-82268199266300683</id><published>2009-12-13T01:58:00.000-08:00</published><updated>2009-12-13T01:58:46.498-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='宅男学厨'/><title type='text'>[宅男学厨]三明治</title><content type='html'>今年出去买了鸡蛋和煎锅:)瞅着手边的材料,除了上次还没用完的土司就还有番茄和奶酪等.那么就做个简单的三明治吧.&lt;br /&gt;&lt;br /&gt;将土司去边,从对角线切开,奶酪也如此对切。&lt;br /&gt;&lt;br /&gt;去鸡蛋一枚,入碗打散,加入少许盐.将之前的土司夹奶酪浸入碗中,三边开口处都要粘满蛋汁哦.&lt;br /&gt;&lt;br /&gt;将土司丢入煎锅,先用中火炸四边,待封口后,转用小火炸两边.至两面均酥皇,将剩余的鸡蛋汁全部交上去,片刻后起锅:)&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_RLf4SUMna24/SyS6NKKd1bI/AAAAAAAAAVw/Iu3MYy_z2hU/s1600-h/IMAGE_00118.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_RLf4SUMna24/SyS6NKKd1bI/AAAAAAAAAVw/Iu3MYy_z2hU/s400/IMAGE_00118.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_RLf4SUMna24/SyS6uLuHIWI/AAAAAAAAAV4/lS7jwqx_kDE/s1600-h/IMAGE_00120.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_RLf4SUMna24/SyS6uLuHIWI/AAAAAAAAAV4/lS7jwqx_kDE/s400/IMAGE_00120.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-82268199266300683?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/82268199266300683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/12/blog-post_13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/82268199266300683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/82268199266300683'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/12/blog-post_13.html' title='[宅男学厨]三明治'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_RLf4SUMna24/SyS6NKKd1bI/AAAAAAAAAVw/Iu3MYy_z2hU/s72-c/IMAGE_00118.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-544720663563084427</id><published>2009-12-11T20:32:00.000-08:00</published><updated>2009-12-11T20:32:12.664-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='宅男学厨'/><title type='text'>[宅男学厨]煎蛋,培根与吐司</title><content type='html'>昨天晚上和March Liu交流了下做饭的心得,得其真传.今天决定从最简单的开始,打好基本功.给自己做一顿早餐.&lt;br /&gt;&lt;br /&gt;看看手边的材料,似乎鸡蛋为最.在我系统分析了&lt;a href="http://space.tv.cctv.com/act/article.jsp?articleId=ARTI1239857430495437&amp;amp;nowpage=1"&gt;33种鸡蛋相关做法&lt;/a&gt;之后,我决定做史上最有名的......煎蛋吧.岂料杯具发生了,家里的鸡蛋被我放置的太久,竟然,竟然坏掉了很多(:&lt;br /&gt;&lt;br /&gt;好不容易找到了一个能用的,打蛋装碗.&lt;br /&gt;&lt;br /&gt;锅里放油,开火,以油熟且尚未冒烟为宜(否则,你的油就会...)好,就是此刻,将鸡蛋丢入锅中,待蛋白部分发白略黄的时候,在其周围加水若干滴(保证下形状,嘿嘿).加盐.翻转鸡蛋,煎另一面.起锅.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_RLf4SUMna24/SyMbBJIlxDI/AAAAAAAAAVg/YXHj5TKVl7E/s1600-h/IMAGE_00116.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_RLf4SUMna24/SyMbBJIlxDI/AAAAAAAAAVg/YXHj5TKVl7E/s400/IMAGE_00116.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;怎么样,第一次煎蛋还算不错吧:)&lt;br /&gt;&lt;br /&gt;接着,将培根丢入锅中约2min,起锅,配合我事前准备的奶酪.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_RLf4SUMna24/SyMbdKgqN9I/AAAAAAAAAVo/sAtJqYetptI/s1600-h/IMAGE_00117.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_RLf4SUMna24/SyMbdKgqN9I/AAAAAAAAAVo/sAtJqYetptI/s400/IMAGE_00117.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;战斗结束,历时6min ;)之前在网上查看食谱的时候,见到一种做法:&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt; &lt;span style="font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;span style="font-size: x-small;"&gt;&lt;span id="reply_content_223168124"&gt;&lt;pre&gt;两片厚片土司去边 一个鸡蛋加少许盐打散 一片或两片奶酪&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;平底锅里放一点黄油熔化后 将去边土司加好奶酪片 放在鸡蛋液里沾一下&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;四周都要沾到 夹起来沾好蛋的土司 在锅里 用中火煎 先煎四边&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;再煎两面 然后转小火 将剩下的鸡蛋均匀的倒上去 如果没剩下鸡蛋&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;就免了这一步了 之后用小火慢慢煎到两面金黄松脆 里面的奶酪半融化状&lt;/pre&gt;&lt;pre&gt;的时候 就能吃了 非常好吃 蛋香奶香麦香稍微有点淡淡的咸味&lt;/pre&gt;&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt; &lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&amp;nbsp; &lt;br /&gt;&lt;/div&gt;厨艺果然是创意无限.不知为啥我想起了Bitmap来:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-544720663563084427?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/544720663563084427/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/12/blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/544720663563084427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/544720663563084427'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/12/blog-post.html' title='[宅男学厨]煎蛋,培根与吐司'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_RLf4SUMna24/SyMbBJIlxDI/AAAAAAAAAVg/YXHj5TKVl7E/s72-c/IMAGE_00116.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-1018281422254645391</id><published>2009-12-11T10:57:00.000-08:00</published><updated>2009-12-11T11:04:36.618-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='锤子'/><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><title type='text'>使用coLinux+Debian+Putty+Emacs构建快速开发环境</title><content type='html'>本博的笔记本比较古董,跑VirtualBox之流甚是吃力,更不用说Vmware这样的超级杀器.本来一直采用的是Msys来进行*nix的模拟的,不过由于某些软件包实在不给面子,害的我每次都得连接至公司的服务集群上进行测试,如此下来,多有不便:(&lt;br /&gt;&lt;br /&gt;于是乎,经过一番爆狗,终于找到了coLinux这样的好东西.CoLinux是在Windows上能够运行的linux. 在Windows计算机上安装Linux的时候，可以不用追加新的硬盘，也不用重新做分区等工作。 如果使用coLinux的话，不重新安装Windows，不变更硬盘分区就可以很轻松地构筑Linux环境。&lt;br /&gt;&lt;br /&gt;如果说Cygwin是在C库程序阶段模拟UNIX（在源码级别的互换性）的话，则coLinux是在能驱动真的Linux原核程序上，与Linux和应用程序具有互换性。即：Debian和Fedora能够直接运行。换句话说，coLinux就是一个 Linux 内核，它经过修改，以与另一个操作系统协作运行。主机操作系统（Windows 或 Linux）控制操作系统的物理资源，而访客（guest）操作系统（coLinux）获得硬件的虚拟抽象。主机操作系统必须提供以特权级别（ring 0）执行驱动程序的方法，并提供分配内存的方法.&lt;br /&gt;&lt;br /&gt;接下来的事情就很容易了,&lt;a href="http://sourceforge.net/projects/colinux/files/"&gt;猛击此处&lt;/a&gt;下载当前的coLinux的二进制版本,同时本博下载了列表下方的Debian5.0的压缩包.运行coLinux的安装程序,一路Next至Over(安装目录最好不要出现中文或空格).解压前述Debian的压缩文件至coLinux的老巢.接下来,可以使用Debian提供的BAT脚本直接执行了.&lt;br /&gt;&lt;br /&gt;不过也许各位已经发现Debian里只有2GB左右的空间,而且貌似不能上网也没有开启sshd.接下来我们一步一步解决这些问题:&lt;br /&gt;&lt;br /&gt;首先,再次&lt;a href="http://gniarf.nerim.net/colinux/fs/fs_4095Mb.bz2"&gt;猛击一下下&lt;/a&gt;,我们得到一个已经做好的4GB大小的分区文件(下载文件很小,只有4xKB的样子).解压丢至coLinux的基地去.&lt;br /&gt;&lt;br /&gt;接着,在你的Debian里配置下第二块网卡(eth1):&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;allow-hotplug eth1&lt;br /&gt;iface eth1 inet static&lt;br /&gt;address 192.168.1.6 //根据实际情况,自行改变&lt;br /&gt;gateway 192.168.1.1&lt;br /&gt;netmask 255.255.255.0&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;这里贴下我的coLinux.conf文件&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;# The default kernel&lt;br /&gt;kernel=vmlinux&lt;br /&gt;&lt;br /&gt;# File contains the root file system.&lt;br /&gt;# Download and extract preconfigured file from SF "Images for 2.6".&lt;br /&gt;cobd0="Debian-5.0r2-lenny.ext3.2gb"&lt;br /&gt;&lt;br /&gt;# Swap device, should be an empty file with 128..512MB.&lt;br /&gt;cobd1="fs_root" //扩展的4GB文件&lt;br /&gt;&lt;br /&gt;cofs0=d:\ //与Windows交互设置,这是coLinux自己的方式&lt;br /&gt;&lt;br /&gt;root=/dev/cobd0&lt;br /&gt;&lt;br /&gt;initrd=initrd.gz&lt;br /&gt;&lt;br /&gt;# Slirp for internet connection (outgoing)&lt;br /&gt;# Inside running coLinux configure eth0 with this static settings:&lt;br /&gt;# ipaddress 10.0.2.15&amp;nbsp;&amp;nbsp; broadcast&amp;nbsp; 10.0.2.255&amp;nbsp;&amp;nbsp; netmask 255.255.255.0&lt;br /&gt;# gateway&amp;nbsp;&amp;nbsp; 10.0.2.2&amp;nbsp;&amp;nbsp;&amp;nbsp; nameserver 10.0.2.3&lt;br /&gt;eth0=slirp //dhcp&lt;br /&gt;# Tuntap as private network between guest and host on second linux device&lt;br /&gt;eth1=tuntap //这里就是之前在系统里设置的eth1&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;启动进入系统,进行挂载测试&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mkdir -p /mnt/ext&lt;br /&gt;mount -t ext3 /dev/cobd1 /mnt/ext&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;如果可以访问的话,那么写入你的/etc/fstab.系统启动时会自动挂载&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;/dev/cobd1 /root ext3 defaults 0 1 //这里我用来扩展了/root,你自然也可以改成/home/xxx 不过记得拷贝文件&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;类似的,将windows交互目录挂载进来&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;mkdir -p /mnt/host&lt;br /&gt;mount -t cofs cofs0 /mnt/host &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;接下来,重启系统,通过&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;apt-get install ssh&lt;/span&gt;来打开sshd,选择putty登陆上去.编译Emacs之前记得先安装ncurses (:&lt;br /&gt;&lt;br /&gt;展示下效果&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_RLf4SUMna24/SyKVZLv_0fI/AAAAAAAAAVQ/X5LjYJZEBcg/s1600-h/emacs-python.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_RLf4SUMna24/SyKVZLv_0fI/AAAAAAAAAVQ/X5LjYJZEBcg/s400/emacs-python.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_RLf4SUMna24/SyKVpuOSNNI/AAAAAAAAAVY/tcRMLaLI3_g/s1600-h/emacs-python.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_RLf4SUMna24/SyKVpuOSNNI/AAAAAAAAAVY/tcRMLaLI3_g/s400/emacs-python.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;这个黑黑的CMD窗口就是coLinux启动的Debian终端,如果觉着不爽,也可以用colinux-daemon把其做成系统服务.最后赞一下,coLinux的速度真的很快&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-1018281422254645391?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/1018281422254645391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/12/colinuxdebianputtyemacs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/1018281422254645391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/1018281422254645391'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/12/colinuxdebianputtyemacs.html' title='使用coLinux+Debian+Putty+Emacs构建快速开发环境'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_RLf4SUMna24/SyKVZLv_0fI/AAAAAAAAAVQ/X5LjYJZEBcg/s72-c/emacs-python.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-9199508059828282862</id><published>2009-12-02T05:31:00.000-08:00</published><updated>2009-12-02T05:34:12.497-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><category scheme='http://www.blogger.com/atom/ns#' term='有关工程'/><title type='text'>基于REST风格构建WEB应用的实践反思</title><content type='html'>&lt;div&gt;&lt;div&gt;江湖上有着这样一则传闻:&lt;br /&gt;面试官:"请问REST是虾米?"&lt;br /&gt;面试者:"哦,您放心,我是永远不知道休息的..."&lt;br /&gt;&lt;br /&gt;我想面试官的这个问题,本文的读者应该大体是有一个&lt;a href="http://zh.wikipedia.org/wiki/REST" id="h0or" title="概念"&gt;概念&lt;/a&gt;的.不过为了行文的方便,这里本博还是将REST的核心原则摘录于下：.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;为所有“资源”定义标识(URI)  &lt;/li&gt;&lt;li&gt;将所有资源链接在一起  &lt;/li&gt;&lt;li&gt;使用标准方法  &lt;/li&gt;&lt;li&gt;资源多重表述  &lt;/li&gt;&lt;li&gt;无状态通信 &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;由于公司战略需要一款SNS产品,本博有幸参与了整个开发活动,并主持了架构设计和实现.因此得以实战REST,并将前后遇到的一些问题和思考记录下来,遂成此文.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;那么为啥会考虑采用REST作为系统架构风格呢?&lt;br /&gt;&lt;br /&gt;首先,由于是一款自己运营SNS产品,根据产品规划部门制定的需求,在技术上要求我们实现大量的用户行为记录,同时还要为用户提供包含博客、相册、视频在内的web2.0“标准”应用以及支持第三方植入应用的OpenAPI体系.因此系统在安全性,并发性,稳定性,扩展性等方面均有较高的要求.&lt;br /&gt;其次,由于项目团队的人员配备,开发模式,开发周期等因素的影响,敏捷开发也成为一个潜在的要求.&lt;br /&gt;针对这些客观实际情况,本博考察了主流SNS的技术方案,结合自身特定,决定采用REST来实施构建:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;资源URI可以有效描述系统涉及的角色(用户,及其产生的行为结果),无论是在用户群体还是在单一个用户对象.&lt;/li&gt;&lt;li&gt;系统对外以URL形式(对内则是URI)来与客户端通讯,这也是负载均衡得以实施的前提&lt;/li&gt;&lt;li&gt;URI(Entity,QueryString,Method)封装了编程实体,后端程序可以有效建立Resource-Object映射,配合Key-Value缓存以及ORM等技术手段优化,可以满足对伸缩性的要求.&lt;/li&gt;&lt;li&gt;REST提倡的HTTP操作方法封装了数据操作的CRUD&lt;/li&gt;&lt;li&gt;URI之间的聚合(combination)有效建立起一组可复用的API体系.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;实践中采用REST风格来构建项目,较为显著的带来了两个方面的提升:技术层次上,团队内推广和普及了敏捷开发,并在实践中性能成一套符合自身情况的开发流程;在HTTP协议,Web服务器,键值缓存,开发语言等方面开拓了技术视野并形成了相应的技术积累.管理层次上,由于构建REST应用的需要,将人员合理分配成应用开发,API开发等不同的小组,责权分明.但是很显然,这一架构的引入不可能是一帆风顺的,在实践中我们也遇到了很多问题,很多场景下我们也不得不去破坏学术定义(REST Anti-Pattern REST反模式):&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;什么是资源?&lt;/li&gt;&lt;/ul&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;这样一个基础的命题上,保持怎样一个粒度,对API的构建乃至整个系统至关重要.是按照"语义"级别,将用户定义为/user/uid这样,还是针对系统级别,将数据表结构定义为资源.在这个问题上,内部产生了很多的思考和争议.虽然我们最终采用了类似前者的思路,但是这只是根据当时需求情况的取舍,这样的定义来带的后果是对"简单数据"CRUD的极大便利;资源交叉高复用,原子操作性较强.但是对集合类似资源(用户组等)至少在概念层次上是无力的,往往需要引用大量的SQL模板来进行封装使用,这也成为性能的一个隐患.而实际上后端开发人员80%的事情均用在这里(从整体最优来看,也是值得的).&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 反之,如果我们将数据表,列这些定义成为资源的话,那么实际上我们将走到一条Meta-Data(元数据)编程的路子上.显然在逻辑层次上我们将不需要去考虑业务中角色以及相互关联的&lt;br /&gt;问题.这种类似"虚拟机"(提供一套策略而不是机制)的架构风格应对复杂逻辑是绰绰有余的.但是在SNS这样一个毕竟存在大量单一应用以及"简单数据"访问的情况下,这样有似乎有点"过度设计".当然这只决定于需求和性能之间的平衡.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;对Method的使用&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 几乎任何一份REST实践指南的资料中都指出过DELETE和PUT的模拟问题,使用GET/POST去实现这样一种模拟. &lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;完全的使用GET方式去实现,这么做的唯一好处,是开发便利:只需要将这样一条URL贴到浏览器的地址栏中,就可以完成测试.但是,这样的系统本身并没有把URI看成是"资源",而仅仅是&lt;br /&gt;一种传递参数的字符串而已.同时这种链接一般不可加入书签,而且有“爬虫”造成非预期副作用的风险(假设你传递了一个?method=delete这样的参数).&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;完全的使用POST方式去实现,这种做法被flicker等知名网站广泛使用,但实际上走回了SOAP的老路上.他不但完全忽视了REST的根本原则并且接下来也无法利用"缓存".我们的系统采&lt;br /&gt;用这种方式的原因是设计上的"便捷"(:&lt;br /&gt;&lt;/div&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;NoSQL?&lt;/li&gt;&lt;/ul&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SNS为NoSQL的思想贡献了相当大的关注力,这种思想意图使用key-value键值数据库来完全取代现在有的关系型数据库,通过键值缓存技术来提升性能.虽然如此,但NoSQL对系统的设计要求是相当之高,否则很容易就会发现构建出来的系统几乎不能满足良好的扩展性. &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;工具与方法论&lt;/li&gt;&lt;/ul&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 开发初期,如何能使更多的开发人员理解REST思想,并应用于开发活动,我们提供了一个在线的调试器,当你输入URL的时候,可以查看返回数据以及相关信息.国内的Taobao开放平台也提供&lt;br /&gt;了类似的沙盒环境(sandbox).推广一种工具往往比推广一种思想要容易的多.当我们意识到并不是所有人都需要明白什么是REST的时候,我们提供了一组language binding clinet library.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;软件开发世界没有"银弹",试图用一种架构风格/模式去解决遇到的所有问题是不现实的.在实践中遇到的种种问题,探究他们的缘起以及解决之道,有利于加深对REST架构的理解和应用.那么,当我们 意识到这些问题,并尝试解决的时候,不妨跳出原有的思维局限,开拓眼界,引入更加符合实际情况的混合架构风格设计方案,这也是我们下一代技术产品的思路,并且有打算以开放源码的方式展现在 大家眼前,提供一个Resty的"砖头".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-9199508059828282862?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/9199508059828282862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/12/restweb.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/9199508059828282862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/9199508059828282862'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/12/restweb.html' title='基于REST风格构建WEB应用的实践反思'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-7438728943427220782</id><published>2009-11-30T00:47:00.000-08:00</published><updated>2009-11-30T00:47:25.707-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><title type='text'>Django的HTTPHandler模型图</title><content type='html'>很早之前的一篇读书笔记,今天有朋友问我这方面的问题,正好就重新贴出来吧.&lt;br /&gt;时间过得好快啊(:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_RLf4SUMna24/SxOGbC3jg1I/AAAAAAAAAVE/86kUJPbU4mk/s1600/12494420600.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_RLf4SUMna24/SxOGbC3jg1I/AAAAAAAAAVE/86kUJPbU4mk/s640/12494420600.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-7438728943427220782?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/7438728943427220782/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/11/djangohttphandler.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/7438728943427220782'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/7438728943427220782'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/11/djangohttphandler.html' title='Django的HTTPHandler模型图'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_RLf4SUMna24/SxOGbC3jg1I/AAAAAAAAAVE/86kUJPbU4mk/s72-c/12494420600.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-6152680480993615936</id><published>2009-11-28T05:20:00.000-08:00</published><updated>2009-11-28T05:23:10.378-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='算法'/><category scheme='http://www.blogger.com/atom/ns#' term='有关数学'/><title type='text'>也谈网页正文提取[下]</title><content type='html'>&lt;a href="http://gfnpad.blogspot.com/2009/11/blog-post.html"&gt;上回&lt;/a&gt;书到使用行文本密度(Text Density)来解决网页正文提取问题.给出了一个学术界定量的文本行密度阀值.一般来说武功秘籍的下半部总是看起来牛逼些的,就像当年梅超风练的&amp;lt;九阴真经&amp;gt;一样,练了半本书的&lt;a href="http://baike.baidu.com/view/28507.htm"&gt;一路掌法&lt;/a&gt;,已经是妇孺闻之变色的"女魔头"了.所以本博的这下半篇也来不得丝毫差池,怎么也得看起来十分有料才行.&lt;br /&gt;&lt;br /&gt;前文所述之阈值估计过程本质上是一个全局统计各个密度的过程，并没有像学习算法一样考虑文本行的分布情况，如在页面的中间发生以及文本行可能在一起出现的可能性高等。但阈值估计有助于快速地选择行，而且可以在没有学习样本的情况下获得较好的表现。&lt;br /&gt;&lt;br /&gt;但是不同的场景需求对结果的精度要求是不一样的,作为一直致力于追求更快,更准,更优的本博来说,自然是希望抽取的结果最优.这里的"最优"有两个方面的含义：&lt;br /&gt;&lt;ul&gt;&lt;li&gt;抽取的结果尽可能包含正确的行&lt;/li&gt;&lt;li&gt;抽取的结果尽量少地包含错误的结果&lt;/li&gt;&lt;/ul&gt;为了达到这样的效果,这里介绍两个主要的手段,神经网络(ANN)和错误控制(FDR).&lt;br /&gt;&lt;br /&gt;首先来看看神经网络，对这个名字觉得耳熟的朋友肯定至少被忽悠过一次数据挖掘或者人工智能.至少本博第一次听说的时候,是被唬的不行,觉着以自己愚钝的天资还是做不明真相的围观群众好了.但是在我们这里,没有必要那么夸张,下面就由有着生物学背景的本博带领去一亲人工神经网络的芳泽.&lt;br /&gt;&lt;br /&gt;既然是人工神经网络,从名字就知道这肯定是模仿其他某些神经组织结构机理而形成的模型.实际上,它所模仿的对象您现在也用着呢,那就是我们人类的"神经细胞"，专业的说法叫做神经元.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_RLf4SUMna24/SxENgBo1zNI/AAAAAAAAAUk/JB9XLVSQTug/s1600/9.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="219" src="http://1.bp.blogspot.com/_RLf4SUMna24/SxENgBo1zNI/AAAAAAAAAUk/JB9XLVSQTug/s320/9.png" width="320" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;神经元结构上大致都可分成胞体和突起两部分,突起又分树突和轴突两种。轴突开始一段称为始段，离开细胞体若干距离后始获得髓鞘，成为神经纤维。我们日常感受的刺激在神经结构上就由树突将冲动转向细胞体.典型的神经突触是在两个神经元之间形成的单向通信机制。神经信息的流向是从突触前细胞到突触后细胞。突触通常形成在突触前细胞的轴突和突触后细胞的细胞体或树突之间.如下图所示&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_RLf4SUMna24/SxERlnZ-lQI/AAAAAAAAAUs/wFeQqwP9e2I/s1600/040656832.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_RLf4SUMna24/SxERlnZ-lQI/AAAAAAAAAUs/wFeQqwP9e2I/s320/040656832.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;人工神经网络就是模仿上述神经突触联接的结构进行信息处理的数学模型.由大量的节点（或称“神经元”）和之间相互联接构成。每个节点代表一种特定的输出函数.每两个节点间的连接都代表一个对于通过该连接路径的加权值,也叫权重,这相当于人工神经网络的记忆. 输出则依赖节点间的链接方式，权重值和节点输出函数.神经网络的构建一般用来模拟自然界某种算法或者函数的逼近,或者某种逻辑的推演(例如本文的问题).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;一个典型的单层神经元网络由有限个神经元构成,上图.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_RLf4SUMna24/SxEUAUD3eRI/AAAAAAAAAU8/6L58jkN-oRM/s1600/TM%E6%88%AA%E5%9B%BE%E6%9C%AA%E5%91%BD%E5%90%8D.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_RLf4SUMna24/SxEUAUD3eRI/AAAAAAAAAU8/6L58jkN-oRM/s400/TM%E6%88%AA%E5%9B%BE%E6%9C%AA%E5%91%BD%E5%90%8D.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;从左到右分别是:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;输入层,众多神经元接受大量非线形输入信息。&lt;/li&gt;&lt;li&gt;隐藏层,简称“隐层”，是输入层和输出层之间众多神经元和链接组成的各个层面，也是实现监督学习算法的主要层面. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;输出层,信息在神经元链接中传输、分析、权衡,形成输出结果。&lt;/li&gt;&lt;/ul&gt;在我们解决网页正文提取这个特定的场景下,我们采用的神经元学习算法可以归类为&lt;b&gt;监督式学习网络&lt;/b&gt;,即从问题领域中&lt;b&gt;提供训练范例，&lt;/b&gt;&lt;b&gt;包含输入资料与输出资料。 网络从中学习输入资料与输出资料的内在对映规则&lt;/b&gt;.很像老师教学生几个例题,告诉答案,然后训练学生做新的题目.&lt;br /&gt;&lt;br /&gt;"ANN是不是一种很复杂的东西?"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "也许以前是,但现在已经不是了"&lt;br /&gt;"为什么"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "因为名气大的招数,往往也是高手努力去研究的东西,像ANN这样的利器,江湖甚至出了一个&lt;a href="http://leenissen.dk/fann/html/files2/installation-txt.html#Python_Bindings"&gt;FANN&lt;/a&gt;"&lt;br /&gt;&lt;br /&gt;首先建立一个fann的训练工程，然后丢给他我们预先标记好的训练文本,过程就是这么简单吖.&lt;br /&gt;关于生成训练文本这里,如果完全手工的话,估计也是一件吐血的事情.但是这活儿又不能没有人工干预,所以折中的办法是预先制定一个训练数据生成算法,然后人工标记检查一下.&lt;br /&gt;&lt;br /&gt;训练数据文本格式如下:&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;3 2 1 //训练对总数 每训练对输入数 每训练对输出数&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;1 1&amp;nbsp;&amp;nbsp; //训练对 输入&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //训练对 输出&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;1 0&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;1&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;-1 1&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white;"&gt;&lt;span style="background-color: black; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;1 &lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;生成算法大致如下:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;分别计算当前行与前行以及后行的文本密度、文本字节数、总字节数&lt;/li&gt;&lt;li&gt;若当前行文本密度在0.3以上,则标记输出结果为1，反之为0&lt;/li&gt;&lt;/ul&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;out = map(lambda x,y,z:[x,y,z],[Para()]+d[0:-1],d,d[1:]+[Para()])&lt;br /&gt;f.write("%s %s %s\n"%(len(d),3,1))&lt;br /&gt;line = 3*"%s "+"\n"&lt;br /&gt;for x,y,z in out:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; f.write(line%(y.density,y.bytes,len(y.text)))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (y.density &amp;gt; 0.3):&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; f.write("1\n")&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; f.write("0\n")&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;使用FANN进行训练的主要过程，在前文的LineWirter中加入一个方法:&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;def get_density_with_ann(self):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; obj = libfann.fann_create_standard_array(2, (3, 1))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ann = fann.fann_class(obj)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; patterns = fann.read_train_from_file('train_data.txt')&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ann.train_on_data(patterns, 1000, 1, 0.0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [line[3] for line in map(lambda x:[x.density,x.bytes,len(x.text),x.text] , self.lines) if ann.run(line[0:2])[0] &amp;gt; 0]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;/div&gt;&lt;br /&gt;使用ANN处理文本提取,可以根据输入的上下文进行启发式学习，从而使得输出更加适合于实际情况.利用机器学习来处理每一文本行的信息，可以找出有用的模式.从人工的决策过程分析，我们采用了九个因素用于决定如何过滤文本行。这些因素分别是当前行的密度、当前行的HTML字节数、当前行的输出文本长度、前一行的这三个值、后一行的这三个值。&lt;br /&gt;&lt;br /&gt;当然神经网络也不是完美的,它需要一定量的网页学习.而且如果网页的结构变化较大，那么感知器反而会带来一些弊病.造成精度缺失的情况.本博的实际实验情况中,由于对多种类型的网页都进行了训练,结果在我们给出的示例网页中,结果稍微逊于另外一个测试用例.&lt;br /&gt;&lt;br /&gt;如果对抽取的结果准确要求相对教高,并且又没有那么多的训练数据可供使用,那又该怎么办呢?本博这里隆重推出终极杀器----&lt;a href="http://en.wikipedia.org/wiki/False_discovery_rate"&gt;FDR &lt;/a&gt;也有人称之为检出率算法,因为其只考虑期望部分的错误率.这里简要阐述FDR的意义以及应用过程。&lt;br /&gt;&lt;br /&gt;假设问题有N个可能的候选输出，每个输出可以采用一个概率或可能性值表示输出结果的正确性概率，根据输出的概率从N个选择中选择一定数量的结果作为最后的输出。假设挑选了 个输出作为结果，其中有s个是真正正确的，另外有 个是错误的，实践中希望错误比例Q=V/R平均而言不能超过某个预先设定的值(如0．05)，在统计学上，这也就等价于控制FDR不能超过5%.&lt;br /&gt;&lt;br /&gt;"看起来很复杂的东西,背后往往相当简单"&lt;br /&gt;&lt;br /&gt;这个问题可以转化成：设总共有n个候选输出，每个输出对应的P值从小到大排列分别是P(1)..P(m)，若想控制FDR不能超过q，则只需找到最大的正整数i，使得P(i)&amp;lt;=(i*q)/m；然后，挑选对应P(1)，p(2)，⋯ ，P(i)作为输出结果,这样就能从统计学上保证FDR不超过q.&lt;br /&gt;&lt;br /&gt;在前文的LineWriter里加入如下代码即可:&lt;br /&gt;&lt;div style="background-color: black;"&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;def output_fdr(self):&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.compute_density()&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pvalue = map(lambda x:1.0/x.density ,self.lines)&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pvalue.sort(reverse=True)&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i = len(self.lines)&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; m = [j for j in range(i) if pvalue[j] &amp;lt;= (j*5)/i][0]&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; density = 1.0/pvalue[m]&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output = StringIO.StringIO()&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output.writelines(''.join([l.text for l in self.lines if l.density &amp;gt; density]))&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return output.getvalue()&lt;br /&gt;&lt;/div&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;采用FDR方法统计意义上的学习之后,得到的新的文本密度p为0.59.&lt;br /&gt;&lt;br /&gt;最后简单对比下本文设计和实现的三种算法:ANN算法和估值算法总体性能较好，但是FDR在控制错误上具有很好的表现；如果应用需求很高的错误率，那么FDR是一个较好的选择；NN算法的最大问题是需要有学习的样本；估值算法对于简单的网页具有简单高效的特点.&lt;br /&gt;&lt;br /&gt;光風(gfn)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-6152680480993615936?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/6152680480993615936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/11/blog-post_28.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/6152680480993615936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/6152680480993615936'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/11/blog-post_28.html' title='也谈网页正文提取[下]'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_RLf4SUMna24/SxENgBo1zNI/AAAAAAAAAUk/JB9XLVSQTug/s72-c/9.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-8231877063724838244</id><published>2009-11-28T03:09:00.001-08:00</published><updated>2009-11-28T03:12:36.294-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><category scheme='http://www.blogger.com/atom/ns#' term='有关工程'/><title type='text'>基于Subversion的版本管理流程</title><content type='html'>&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;摘要&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;:&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;本文围绕开源版本控制软件&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;Subverison,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;结合开发涉及角色描述版本控制管理流程&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;涉及角色&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul type="disc"&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;程序员&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;小组责任人&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;项目经理&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;代码仓库&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul type="disc"&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;开发目录&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;(&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;以下称&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;b&gt;trunk&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;),&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;包含各个小组的开发目录&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;里程碑目录&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;(&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;以下称&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;b&gt;tags&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;),&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;包含面向集成测试的里程碑版本&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;生产目录&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;(&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;以下称&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;&lt;b&gt;release&lt;/b&gt;&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;),&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;包含用于生产环境的代码&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;协同流程&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: center;"&gt;&lt;span style="font-size: small;"&gt;&lt;img alt="" border="0" height="264" src="http://docs.google.com/File?id=dfsqnx9d_18f59gz7cd_b" width="320" /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul type="disc"&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;程序员&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ol type="1"&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;根据项目经理、小组责任人的分配的任务从&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;trunk&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;检出对应模块目录&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;进行功能开发&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;;&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;在分配给小组的开发服务器上经行单元测试&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;;&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;修正集成测试反馈的代码缺陷&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;重复步骤&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;2)&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;后交付责任人。&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul type="disc"&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;小组责任人&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ol type="1"&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;在各个里程碑期间&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;保证组内程序员开发的代码通过单元测试&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;;&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;与项目经理沟通后&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;确定当前小组负责模块的稳定版本&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;提交至项目经理指定的&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;tags&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;版本目录。&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;协助项目经理经行集成测试&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;接受测试反馈&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;并组织修复&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;重复步骤&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;2)&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;。&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul type="disc"&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;项目经理&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ol type="1"&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;召集各小组负责人在里程碑点进行集成测试&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;;&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;测试产生的问题反馈至相应模块责任人&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;;&lt;/span&gt;&lt;/li&gt;&lt;li style="text-align: justify;"&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;确认通过集成测试的系统版本&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;提交至&lt;/span&gt;&lt;span style="font-family: 'Times New Roman'; font-size: small;"&gt;release,&lt;/span&gt;&lt;span style="font-family: '宋体'; font-size: small;"&gt;并根据实际情况安排部署。&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-left: 0pt; margin-right: 0pt; text-align: justify;"&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-8231877063724838244?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/8231877063724838244/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/11/subversiondoc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/8231877063724838244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/8231877063724838244'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/11/subversiondoc.html' title='基于Subversion的版本管理流程'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-666492502727161560</id><published>2009-11-28T01:41:00.000-08:00</published><updated>2009-11-28T02:21:19.210-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='算法'/><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><category scheme='http://www.blogger.com/atom/ns#' term='有关数学'/><title type='text'>也谈网页正文提取[上]</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;看到这里,如果有看官不知道啥叫正文提取,那我只能说,大哥我真的没有忽悠您，我既没说"网页去噪",也没说互联网的"自动摘要",更没说海量互联网数据的"文本挖掘"。由此可见本博是个很厚道的人,会手把手教你如何完成这个看起来牛逼实则很简单的一件事情,绝对让你感到物超所值(阅读的时间)。&lt;br /&gt;&lt;br /&gt;从字面意思上理解,网页的正文提取嘛,无非就是把网页当中对咱最有价值的那部分文章给取出来撒.有点编程经验的朋友肯定都知道,右键网页源文件,看看html代码,取出来有正则匹配一下也就几分钟而已的事情。更好一点的办法,那自然是用上像DOM或者XPath这样专门对付html的利器,多写几次估计一分钟也不要。如果本博也这么干的话,那还怎么体现您的慧眼如矩呢:)&lt;br /&gt;&lt;br /&gt;上面说的方法,实际上在垂直搜索引擎的定向抓取中,给一个目标站点利用DOM建立抽取模板是一个很常用也很准确的办法。但是当问题域变得稍微大那么一点点,比方说吧,我觉着谷歌做的不错，我也想搞一个的话,那咋整呢?再利用上面的办法,机械的给每一个页面建立DOM,是会死人的哟XD&lt;br /&gt;&lt;br /&gt;那么问题其实就变成了对于任意篇网页,有没有办法"聪明"点的法子,能识别出正文部分呢?&lt;br /&gt;既然我们人是可以做到这一点的,那么就说明存在利用人工智能去解决这个问题的可能性.当然,我们现在不急,先从简单的做起.&lt;br /&gt;&lt;br /&gt;网页里面除了可读文本就是链接,图片,视频,以及其他媒体类型.而后面这些东东在HTML里面都是用专有的标签来显示的,而且还是被标签所"夹住"的。那我们来看看一个文本块里,除了标签还剩下来的东西有多少.&lt;br /&gt;&lt;br /&gt;通过Python内置的htmllib模块和formatter的配合,我们可以统计出网页中每一行文本中标签和正文的数量.代码如下:&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;#coding:utf-8&lt;br /&gt;&lt;br /&gt;import htmllib,urllib2&lt;br /&gt;import formatter,StringIO&lt;br /&gt;&lt;br /&gt;class TrackParser(htmllib.HTMLParser):&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self, writer, *args):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; htmllib.HTMLParser.__init__(self,*args)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.writer = writer&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def parse_starttag(self,i):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; index = htmllib.HTMLParser.parse_starttag(self,i)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.writer.index = index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return index&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def parse_endtag(self,i):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.writer.index = i&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return htmllib.HTMLParser.parse_endtag(self,i)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class Para:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.text = ''&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.bytes = 0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.density = 0.0&lt;br /&gt;&lt;br /&gt;class LineWirter(formatter.AbstractWriter):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; """&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; a Formatter instance to get text in lines&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; """&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.last_index = 0&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.lines = [Para()]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; formatter.AbstractWriter.__init__(self)&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def send_flowing_data(self, data):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; t = len(data)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.index += t&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; b = self.index - self.last_index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.last_index = self.index&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; l = self.lines[-1]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; l.text += data&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; l.bytes += b&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def send_paragraph(self,blankline):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if self.lines[-1].text == '':&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.lines[-1].text += 'n'*(blankline+1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.lines[-1].bytes += 2*(blankline+1)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.lines.append(Para())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def send_literal_data(self,data):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.send_flowing_data(data)&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def send_line_break(self):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.send_paragraph(0)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;def extract_text(html):&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; writer = LineWirter()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; fmt = formatter.AbstractFormatter(writer)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parser = TrackParser(writer,fmt)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parser.feed(html)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parser.close()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return writer.lines&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;htmls = urllib2.urlopen("http://ent.hunantv.com/d/x/20091128/503722.html")&lt;br /&gt;print map(lambda x:[x.bytes,len(x.text)],extract_text(htmls.read()))&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;看着飞速跑过的列表,你是不是恨不得把他给全部写入一个文件来看看结果?在文件尾部加入&lt;br /&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="background-color: black;"&gt;q = open("e.csv","w+").writelines('\n'.join(["%s,%s"%(x[0],x[1]) for x in s])) &lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;现在结果变成了一个csv文件鸟,来上个图看看:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_RLf4SUMna24/SxDhLbC3SNI/AAAAAAAAAS8/9S1NJ64PesA/s1600/1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_RLf4SUMna24/SxDhLbC3SNI/AAAAAAAAAS8/9S1NJ64PesA/s640/1.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;上图清晰的表达了该网页的文本分布,根据与页面的比对,我们发现文本所在的区域与相对应的行域保持了某种关系.这似乎说明我们的思路是正确的.&lt;br /&gt;&lt;br /&gt;实际上&lt;b&gt;行文本字节数与行总字节数的比值被称为行文本密度&lt;/b&gt;.有了这个概念,我们就可以对网页全文扫描计算相应的文本密度,这里我们不妨做一个假设,文本密度在0.5以上的就是我们需要的文本部分，也就是说我们认定某行的文本至少和该行的标签一样多的话,他就可能是我们需要的文本区域.&lt;br /&gt;&lt;br /&gt;修改上述代码的两个地方,我们来初试下身手,&lt;br /&gt;在原有的LineWriter里加入:&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def output(self):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.compute_density()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output = StringIO.StringIO()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for l in self.lines:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if l.density &amp;gt; 0.5: //这里就是我们设置的行文本密度&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output.write(l.text)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return output.getvalue()&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;修改extract_text函数&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;def extract_text(html):&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   writer = LineWirter()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  fmt = formatter.AbstractFormatter(writer)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  parser = TrackParser(writer,fmt)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  parser.feed(html)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parser.close()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return writer.output()&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;文件末尾改成&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;htmls = urllib2.urlopen("http://ent.hunantv.com/d/x/20091128/503722.html")&lt;br /&gt;s = open('e.html','w+').write(extract_text(htmls.read()))&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;先透口气,然后平静的点开e.html，喔,你看见了什么！&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_RLf4SUMna24/SxDliY9vIsI/AAAAAAAAATE/7DUljU_376o/s1600/2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_RLf4SUMna24/SxDliY9vIsI/AAAAAAAAATE/7DUljU_376o/s640/2.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;激动之后,应该会有这么一个疑问,刚才我们设置的文本密度为0.5，这个数字到底是怎么来的?他具有普适性么?&lt;br /&gt;&lt;br /&gt;其实这个文本密度是可以计算出来的:&lt;br /&gt;设y为行文本集合,z为行标签集合,则文本密度p为:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_RLf4SUMna24/SxDqMFgm2JI/AAAAAAAAATM/XqGBTea4pW4/s1600/4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_RLf4SUMna24/SxDqMFgm2JI/AAAAAAAAATM/XqGBTea4pW4/s320/4.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;设i代表任意行,分别用yi,zi代表任意行文本/标签的长度,设且均符合正态分布.uy,uz分别代表行文本和行标签的平均长度：&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_RLf4SUMna24/SxDr67Xc-0I/AAAAAAAAATU/n_oG0Phpi-M/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_RLf4SUMna24/SxDr67Xc-0I/AAAAAAAAATU/n_oG0Phpi-M/s320/2.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_RLf4SUMna24/SxDsAvMb8EI/AAAAAAAAATc/wExK4ZzSNQQ/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_RLf4SUMna24/SxDsAvMb8EI/AAAAAAAAATc/wExK4ZzSNQQ/s320/3.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;计算方差:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_RLf4SUMna24/SxDsVRyvooI/AAAAAAAAATk/j3suqYYzKXE/s1600/5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_RLf4SUMna24/SxDsVRyvooI/AAAAAAAAATk/j3suqYYzKXE/s320/5.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_RLf4SUMna24/SxDsZWcZJdI/AAAAAAAAATs/LXLUtDMb1CA/s1600/6.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_RLf4SUMna24/SxDsZWcZJdI/AAAAAAAAATs/LXLUtDMb1CA/s320/6.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;如果选择文本行的概率为p,那么标签行就为1-p.相应的各文本项平均长度为&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_RLf4SUMna24/SxDtUjSD2iI/AAAAAAAAAT0/vYKxmHbrC0I/s1600/7.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_RLf4SUMna24/SxDtUjSD2iI/AAAAAAAAAT0/vYKxmHbrC0I/s320/7.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_RLf4SUMna24/SxDtn9BVTtI/AAAAAAAAAT8/zb2gx9GXgIA/s1600/8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_RLf4SUMna24/SxDtn9BVTtI/AAAAAAAAAT8/zb2gx9GXgIA/s320/8.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;最后得到p的估值:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_RLf4SUMna24/SxDt9EzmgjI/AAAAAAAAAUE/VbFGecImez8/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_RLf4SUMna24/SxDt9EzmgjI/AAAAAAAAAUE/VbFGecImez8/s320/1.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;将我们选用的网页实际情况带入以后,我们得到真实的文本密度p大约为0.53,和估计值很相近.学术界有针对行的做了大量实验,得出新闻资讯类网站的文本密度大约在0.4-0.6左右,sina和sohu的这个值大约都是0.6;博客类网站的文本密度大约在0.7-0.8之间.&lt;br /&gt;&lt;br /&gt;作为这个话题上半部分的结束,谈谈这个文本密度的实际应用,除了本文所涉及到的文本抽取以外,文本密度现在被广泛应用于搜索引擎网页价值分析的预处理,同时我们也大体可以看出网站内容的大致分布.&lt;br /&gt;&lt;br /&gt;下半部分,本博将引入ANN(神经网络)和FDR(错误控制)的相关方法继续探讨这个话题.敬请围观.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;光風(gfn)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-666492502727161560?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/666492502727161560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/11/blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/666492502727161560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/666492502727161560'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/11/blog-post.html' title='也谈网页正文提取[上]'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_RLf4SUMna24/SxDhLbC3SNI/AAAAAAAAAS8/9S1NJ64PesA/s72-c/1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-4581819882572521308</id><published>2009-11-23T07:10:00.000-08:00</published><updated>2009-11-23T07:27:09.827-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><category scheme='http://www.blogger.com/atom/ns#' term='有关数学'/><title type='text'>数组过滤之bitmap解法</title><content type='html'>求一个数组中过滤掉重复的元素,并保证原有的元素均存在。&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black;"&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; data&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;['a', 'a', 'z', 'b', 'a', 'b', 'c']&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; def foo(f,n=0):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if f%2 != 0:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; l.append(n)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if f/2 == 1:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; l.append(n+1)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; return l&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; n += 1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foo(f/2,n)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; l = []&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; p = foo(reduce(lambda x,y:x|y,map(lambda x:1&amp;lt;&amp;lt;(128-ord(x)),data)))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; r = map(lambda x:chr(128-x),l)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; r&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;['z', 'c', 'b', 'a']&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;March Liu大法&lt;br /&gt;&lt;div style="background-color: black;"&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&gt;&gt;def refoo(d, k):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;c = d.get(k, 0)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;d[k] = c+1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;return d&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&amp;gt;&amp;gt;&amp;gt; map(lambda p: p[0], filter(lambda p:p[1]==1,  reduce(refoo, data, {}).iteritems()))&lt;/span&gt;&lt;span style="color: white;"&gt;&lt;/span&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-4581819882572521308?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/4581819882572521308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/11/bitmap.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/4581819882572521308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/4581819882572521308'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/11/bitmap.html' title='数组过滤之bitmap解法'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-7641875919541742315</id><published>2009-11-11T06:07:00.000-08:00</published><updated>2009-11-11T06:07:00.177-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='锤子'/><category scheme='http://www.blogger.com/atom/ns#' term='hacks'/><title type='text'>通过Shell Script解决Subversion分支与主干合并</title><content type='html'>最近公司内部推行了基于Subversion的开发流程规范.程序员在开发功能模块的时候,基本在各自的trunk活动,当完成单元测试后，方可提交至生产版本库.这样一来就涉及到版本合并的问题.&lt;br /&gt;&lt;br /&gt;使用Windows的朋友自然不觉得这是一个多麻烦的事情,毕竟有"小乌龟"嘛.可是,作为拥护Unix&amp;amp;Shell以及崇尚"DRY"原则,还不时热爱捣鼓点新鲜玩意儿的本博来说:岂有不用shell实现的道理;)&lt;br /&gt;&lt;div style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="background-color: black;"&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#!/bin/bash&lt;/span&gt;&lt;br style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;export trunk_dir=/root/dp-trunk/&lt;/span&gt;&lt;br style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;export release_dir=/root/dp-release/dp-0.1.0/&lt;/span&gt;&lt;br style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;trunk=`svn up $trunk_dir|grep revision|awk -F' ' '{ print $3 }'|awk -F'.' '{print $1}'`&lt;/span&gt;&lt;br style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;release=`svn info $release_dir | grep "Last Changed Rev"|awk -F: '{print $2}'`&lt;/span&gt;&lt;br style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;br style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;info=`svn merge -r $release:$trunk $trunk_dir $release_dir &amp;amp;&amp;amp; svn ci -m '' $release_dir`&lt;/span&gt;&lt;br style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;" /&gt;&lt;span style="color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;echo $info&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-7641875919541742315?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/7641875919541742315/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/11/shell-scriptsubversion.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/7641875919541742315'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/7641875919541742315'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/11/shell-scriptsubversion.html' title='通过Shell Script解决Subversion分支与主干合并'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-6978302105408731560</id><published>2009-11-05T17:45:00.000-08:00</published><updated>2009-11-05T17:56:17.464-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='锤子'/><category scheme='http://www.blogger.com/atom/ns#' term='hacks'/><title type='text'>Perl实现Subversion更新守护进程</title><content type='html'>和前一篇&lt;a href="http://gfnpad.blogspot.com/2009/11/subverison.html"&gt;使用Subverison同步多台服务器代码&lt;/a&gt;类似,前者主要解决Subversion向服务器同步完全相同的环境代码,但是当不同的服务器需要的程序并不一样的时候,前者就很捉襟见肘了.于是,这里给出一个Perl的Deamon实现&lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: black; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;#!/usr/bin/perl&lt;br /&gt;exit if fork();&lt;br /&gt;while(1) {system("svn up /root/192.168.8.192");sleep(5)};&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-6978302105408731560?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/6978302105408731560/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/11/perlsubversion.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/6978302105408731560'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/6978302105408731560'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/11/perlsubversion.html' title='Perl实现Subversion更新守护进程'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-5853186601905310515</id><published>2009-11-04T07:49:00.000-08:00</published><updated>2009-11-04T07:49:41.513-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='锤子'/><category scheme='http://www.blogger.com/atom/ns#' term='hacks'/><title type='text'>使用Subverison同步多台服务器代码</title><content type='html'>在实际生产中,一套分布式的程序可能需要被部署在很多环境相同的服务器上.如何实现程序的自动部署不仅可以降低因版本冲突而导致的服务异常,也可以未将来的持续集成做基础准备.&lt;br /&gt;&lt;br /&gt;这里采用的代码版本控制程序为Subversion,由中央版本库向多台服务器同步代码的方法有很多,基本上都是通过使用hook(post-commit)来实现的.&lt;br /&gt;&lt;br /&gt;这里记录下我的post-commit：&lt;br /&gt;&lt;br /&gt;&lt;div style="-moz-background-clip: border; -moz-background-inline-policy: continuous; -moz-background-origin: padding; background: rgb(0, 0, 0) none repeat scroll 0% 0%; color: white; font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;span style="font-size: small;"&gt;use Net::SSH::Expect;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;#此处添本代码仓库需要同步的服务器组&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;my @cluster = ('192.168.1.191',&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; '192.168.1.190',&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; '192.168.1.193'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; );&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;foreach $svr (@cluster) {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp; my $ssh = Net::SSH::Expect-&amp;gt;new(&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp; host =$svr,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp; password ='xxx', &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp; user ='xxx',&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp; raw_pty =1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp; );&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp; my $logins = $ssh-&amp;gt;login();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp; my $command = $ssh-&amp;gt;exec('svn up /path');&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp; $ssh-&amp;gt;close();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-5853186601905310515?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/5853186601905310515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/11/subverison.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/5853186601905310515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/5853186601905310515'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/11/subverison.html' title='使用Subverison同步多台服务器代码'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-2954330323402397795</id><published>2009-10-30T07:29:00.000-07:00</published><updated>2009-10-30T07:29:12.643-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><title type='text'>程序员十月刊阅读随想</title><content type='html'>从公司借阅了10月刊的程序员杂志,从08年以后,我已经很久没有看过这本杂志了.越来越多的商业广告和充斥满眼的宣传炒作渐渐感觉背离了这样一本杂志的初衷...&lt;br /&gt;&lt;br /&gt;这次翻阅倒也是因为March Liu大侠正在研究的ORM之上的语义网数据库模型,个人很感兴趣。于是找来原文围观下,有空的话发一篇随笔上来吧:)&lt;br /&gt;&lt;br /&gt;言归正传,本期程序员的前半部分讲了很多关于云计算的厂家宣传,后半部分又介绍了不少国内的虚拟化实践:综合来看,验证了个人对云计算未来物理基础的认识和判断----虚拟化.除了企业IT总体拥有成本之外的考量,虚拟化可以在现有物理机器之上虚拟出大量的node,在软件层面上实现分布式计算,负载均衡等架构技术从而实现系统的健壮,Scalability等特性。而且工业界目前的商业云计算案例似乎也都是构建在虚拟机堆栈之上的,比如Amazon S3.&lt;br /&gt;&lt;br /&gt;说道AWS，那还得说说Microsoft的云计算计划Azure,在RDB方向上的发力以及早期具备的API-Entry访问模式使其具有双重DB性质.这点似乎已经成为了数据库云计算方面的领跑者.同时看到微软近期对PHP的大力支持,是否可以认为是微软加大对互联网方向的投入和关注的信号呢?&lt;br /&gt;&lt;br /&gt;哦,今天知道了MTK的OS是nucleus...&lt;br /&gt;&lt;br /&gt;最后来谈谈关于开放平台的事情。现在越来越多的厂家开始在自己的路线图里出现API和SDK这样的字眼,那么构建开放平台到底是为了什么呢?&lt;br /&gt;&lt;br /&gt;一如Apple的App Store通过开放平台来实现产品销量的增加;另一如saleforce通过平台来卖软件获得收入.&lt;br /&gt;&lt;br /&gt;其实,个人以为开放平台的构建说到底还是为了更好的增加产品竞争力,实力强大的通过开放来统一产业链;实力弱小的通过开放来增加生存空间和砝码。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-2954330323402397795?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/2954330323402397795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/10/blog-post_30.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/2954330323402397795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/2954330323402397795'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/10/blog-post_30.html' title='程序员十月刊阅读随想'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-5487717923252469738</id><published>2009-10-26T20:58:00.000-07:00</published><updated>2009-10-26T20:58:29.262-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='锤子'/><category scheme='http://www.blogger.com/atom/ns#' term='hacks'/><title type='text'>Shell脚本收集</title><content type='html'>清除当前目录下所有emacs的临时文件&lt;br /&gt;&lt;ul style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;li&gt;find . -iname '*~' | xargs rm -f&lt;/li&gt;&lt;/ul&gt;添加 当前目录下所有未进入版本库的文件&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;svn st| tr '^\?' ' ' | xargs svn add&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-5487717923252469738?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/5487717923252469738/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/10/shell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/5487717923252469738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/5487717923252469738'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/10/shell.html' title='Shell脚本收集'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-2401748282203065498</id><published>2009-10-26T20:52:00.000-07:00</published><updated>2009-10-26T20:54:16.215-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='虚拟化'/><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><title type='text'>虚拟化技术漫谈</title><content type='html'>虚拟化是一个广义的术语，对于不同的人来说可能意味着不同的东西，这要取决他们所处的环境。在计算机科学领域中，虚拟化代表着对计算资源的抽象，而不仅仅 局限于虚拟机的概念。例如对物理内存的抽象，产生了虚拟内存技术，使得应用程序认为其自身拥有连续可用的地址空间（Address Space），而实际上，应用程序的代码和数据可能是被分隔成多个碎片页或段），甚至被交换到磁盘、闪存等外部存储器上，即使物理内存不足，应用程序也能 顺利执行。&lt;br /&gt;&lt;br /&gt;虚拟化的历史:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;硬件虚拟化,分时系统 IBM System/360 &lt;/li&gt;&lt;li&gt;处理器虚拟化,现在程序语言的虚拟里VM &lt;/li&gt;&lt;li&gt;指令集虚拟化,指令集转换 &lt;/li&gt;&lt;li&gt;库级虚拟化,例如PC平台上的某些街机模拟器 &lt;/li&gt;&lt;/ul&gt;VMM 调度虚拟机时，将其部分状态恢复到主机系统中。并非所有的状态都需要恢复，例如主机 CR3 寄存器中存放的是 VMM 设置的页表物理地址，而不是 Guest OS 设置的值。主机处理器直接运行 Guest OS 的机器指令，由于 Guest OS运行在低特权级别，当访问主机系统的特权状态（如写 GDT 寄存器）时，权限不足导致主机处理器产生异常，将运行权自动交还给 VMM。此外，外部中断的到来也会导致 VMM 的运行。VMM 可能需要先将 该虚拟机的当前状态写回到状态数据结构中，分析虚拟机被挂起的原因，然后代表 Guest OS 执行相应的特权操作。最简单的情况，如Guest OS 对 CR3 寄存器的修改，只需要更新虚拟机的状态数据结构即可。一般而言，大部分情况下，VMM 需要经过复杂的流程才能完成原本简单的操作。最后 VMM 将运行权还给 Guest OS，Guest OS 从上次被中断的地方继续执行，或处理 VMM “塞”入的虚拟中断和异常。这种经典的虚拟机运行方式被称为 Trap-And-Emulate &lt;br /&gt;&lt;br /&gt;VT-x 为 IA 32 处理器增加了两种操作模式：VMX root operation 和 VMX non-root operation。VMM 自己运行在 VMX root operation 模式，VMX non-root operation 模式则由 Guest OS 使用。两种操作模式都支持 Ring 0 ~ Ring 3 这 4 个特权级，因此 VMM 和 Guest OS 都可以自由选择它们所期望的运行级别。 这两种操作模式可以互相转换。运行在 VMX root operation 模式下的 VMM 通过显式调用 VMLAUNCH 或 VMRESUME 指令切换到 VMX non-root operation 模式，硬件自动加载 Guest OS的上下文，于是 Guest OS 获得运行，这种转换称为 VM entry。Guest OS 运行过程中遇到需要 VMM 处理的事件，例如外部中断或缺页异常，或者主动调用 VMCALL 指令调用 VMM 的服务的时候（与系统调用类似），硬件自动挂起 Guest OS，切换到 VMX root operation 模式，恢复 VMM 的运行，这种转换称为 VM exit。VMX root operation 模式下软件的行为与在没有 VT-x 技术的处理器上的行为基本一致；而VMX non-root operation 模式则有很大不同，最主要的区别是此时运行某些指令或遇到某些事件时，发生 VM exit。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-2401748282203065498?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/2401748282203065498/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/10/blog-post.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/2401748282203065498'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/2401748282203065498'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/10/blog-post.html' title='虚拟化技术漫谈'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-7953998037554724043</id><published>2009-10-26T20:34:00.000-07:00</published><updated>2009-10-26T20:34:00.087-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hacks'/><category scheme='http://www.blogger.com/atom/ns#' term='虚拟化'/><title type='text'>实战虚拟化技术之Xen</title><content type='html'>Xen是由剑桥大学开发的VMM.这里简要记录下安装过程中的几个问题:&lt;br /&gt;使用egrep '(vmx|svm)' /proc/cpuinfo 检测处理器是否支持虚拟化.&lt;br /&gt;如果不支持的话那么很遗憾,只能使用全虚拟化.&lt;br /&gt;接下来,按照手册的说明文件:&lt;br /&gt;make world&lt;br /&gt;make install&lt;br /&gt;然后修改grub的引导,使xen支持的内核可以启动,重启服务器.下面就可以体验xen了&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-7953998037554724043?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/7953998037554724043/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/10/xen.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/7953998037554724043'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/7953998037554724043'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/10/xen.html' title='实战虚拟化技术之Xen'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-8211513049976882298</id><published>2009-10-22T08:09:00.000-07:00</published><updated>2009-10-22T08:18:24.823-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hacks'/><category scheme='http://www.blogger.com/atom/ns#' term='虚拟化'/><title type='text'>实战虚拟化技术之VMware Server</title><content type='html'>在虚拟化技术方案中,最耳熟能详的莫过于VMware的产品了.其桌面端VMware Workstation让很多人体验了虚拟机的快感.在服务器虚拟化领域,它的对应产品就是VMware Server.&lt;br /&gt;本文主要描述了我在虚拟化方案技术选型中对Vmware Server考察的过程.&lt;br /&gt;&lt;br /&gt;测试环境&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&amp;nbsp;Machine :Dell PowerEdge R200 Intel(R) Pentium(R) Dual CPU E2180 @ 2.00GHz&lt;/li&gt;&lt;li&gt;&amp;nbsp;HostOS: CentOS 4.5&lt;/li&gt;&lt;li&gt;&amp;nbsp;Kernel: Linux2.6.9-89.0.11.EL&lt;/li&gt;&lt;li&gt;&amp;nbsp;Memory:2GB&lt;/li&gt;&lt;li&gt;&amp;nbsp;Software:Vmware Server 2.0.1&lt;/li&gt;&lt;/ul&gt;从Vmware官方下载二进制安装包,执行vmware-install.pl.根据提示输入你的实际参数,一般情况下直接默认就可以了.安装的最后会提示你是否运行vmware-config.pl.你可以选择yes,接下来如果遇到内核模块支持错误提示的话,可以放狗去搜对应内核模块的vmware-patch.我使用的CentOS4.5倒是没有这个问题.&lt;br /&gt;&lt;br /&gt;一切完毕之后,就从浏览器输入服务器ip:8333进入VMware Infrastructure Web Acess,你会发现这和workstation版本几乎没有什么区别.接着就是新建虚拟机了:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_RLf4SUMna24/SuB2S06a_wI/AAAAAAAAAR4/j6sgTNEDsbg/s1600-h/1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_RLf4SUMna24/SuB2S06a_wI/AAAAAAAAAR4/j6sgTNEDsbg/s400/1.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&amp;nbsp;.&lt;br /&gt;我配置的虚拟机参数Memory 256MB;Core 1;HDD 8G,由于使用场景的不同,我很关注I/O效率.所以特意做了一些实验,结果如下:&lt;br /&gt;&lt;br /&gt;avg-cpu:&amp;nbsp; %user&amp;nbsp;&amp;nbsp; %nice&amp;nbsp;&amp;nbsp;&amp;nbsp; %sys %iowait&amp;nbsp;&amp;nbsp; %idle&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp;&amp;nbsp; 2.00&amp;nbsp;&amp;nbsp; 25.00&amp;nbsp;&amp;nbsp; 73.00&lt;br /&gt;Device:&amp;nbsp;&amp;nbsp;&amp;nbsp; rrqm/s wrqm/s&amp;nbsp;&amp;nbsp; r/s&amp;nbsp;&amp;nbsp; w/s&amp;nbsp; rsec/s&amp;nbsp; wsec/s&amp;nbsp;&amp;nbsp;&amp;nbsp; rkB/s&amp;nbsp;&amp;nbsp;&amp;nbsp; wkB/s avgrq-sz avgqu-sz&amp;nbsp;&amp;nbsp; await&amp;nbsp; svctm&amp;nbsp; %util&lt;br /&gt;sda&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp; 86.00&amp;nbsp; 0.00 37.00&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00 32800.00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00 16400.00&amp;nbsp;&amp;nbsp; 886.49&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6.08&amp;nbsp; 566.00&amp;nbsp;&amp;nbsp; 6.89&amp;nbsp; 25.50&lt;br /&gt;dm-0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp; 0.00 88.00&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp; 704.00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp; 352.00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8.00&amp;nbsp;&amp;nbsp; 703.14 27351.68&amp;nbsp;&amp;nbsp; 2.89&amp;nbsp; 25.40&lt;br /&gt;dm-1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp; 0.00&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp; 0.00&amp;nbsp;&amp;nbsp; 0.00 &lt;br /&gt;&lt;br /&gt;总体来看.Vmware Server门槛较低,交互界面相对统一;对服务器几乎没有硬性要求.部署方便容易,磁盘镜像可复用.&lt;br /&gt;对于测试型场景来说,性能完全可以满足需求.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-8211513049976882298?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/8211513049976882298/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/10/vmware-server.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/8211513049976882298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/8211513049976882298'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/10/vmware-server.html' title='实战虚拟化技术之VMware Server'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_RLf4SUMna24/SuB2S06a_wI/AAAAAAAAAR4/j6sgTNEDsbg/s72-c/1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-4796126561617787918</id><published>2009-10-20T06:55:00.000-07:00</published><updated>2009-10-20T07:00:18.189-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='锤子'/><category scheme='http://www.blogger.com/atom/ns#' term='子曾经曰过'/><title type='text'>Emacs Advanced Guide - Chapter 1</title><content type='html'>&lt;div style="font-family: Verdana,sans-serif;"&gt;&lt;b&gt;子曰 "学而时习之"&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;HotKey for Copy &amp;amp; Paster&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;li&gt;C-@ C-W&amp;nbsp; 剪切&lt;/li&gt;&lt;li&gt;C-Y&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 粘贴&lt;/li&gt;&lt;li style="background-color: white; color: red;"&gt;&lt;b&gt;C-@ M-W&amp;nbsp; 复制&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="font-family: Verdana,sans-serif;"&gt;&lt;b&gt;HotKey for Delete&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;li&gt;C-D&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 删除后一个字符&lt;/li&gt;&lt;li&gt;C-BK&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 删除前一个字符&lt;/li&gt;&lt;li&gt;C-K&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; 删除到行尾&lt;/li&gt;&lt;li style="color: red;"&gt;&lt;b&gt;M-D&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 删除后一个字&lt;/b&gt;&lt;/li&gt;&lt;li style="color: red;"&gt;&lt;b&gt;M-K&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 删除到段尾&lt;/b&gt;&lt;/li&gt;&lt;li&gt;C-@&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 标记起点&lt;/li&gt;&lt;li&gt;C-W&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 剪切到缓冲区&lt;/li&gt;&lt;li&gt;C-X U&amp;nbsp;&amp;nbsp;&amp;nbsp; Undo&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="font-family: Verdana,sans-serif;"&gt;&lt;b&gt;&lt;span style="font-size: small;"&gt;HotKey for Cursor&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;ul style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;li&gt;C-F&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 后进一位&lt;/li&gt;&lt;li&gt;C-B&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 前进一位&lt;/li&gt;&lt;li&gt;C-N&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下一行&lt;/li&gt;&lt;li&gt;C-P&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 前一行&lt;/li&gt;&lt;li style="color: red;"&gt;&lt;b&gt;M-F&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下一个字&lt;/b&gt;&lt;/li&gt;&lt;li style="color: red;"&gt;&lt;b&gt;M-B&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 前一个字&lt;/b&gt;&lt;/li&gt;&lt;li style="color: red;"&gt;&lt;b&gt;M-A&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 段首&lt;/b&gt;&lt;/li&gt;&lt;li style="color: red;"&gt;&lt;b&gt;M-E&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 段位&lt;/b&gt;&lt;/li&gt;&lt;li&gt;C-A&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 行首&lt;/li&gt;&lt;li&gt;C-E&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 行尾&lt;/li&gt;&lt;li style="color: red;"&gt;&lt;b&gt;C-V&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上一页&lt;/b&gt;&lt;/li&gt;&lt;li style="color: red;"&gt;&lt;b&gt;M-V&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 下一页&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-4796126561617787918?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/4796126561617787918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/10/emacs-advanced-guide-chapter-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/4796126561617787918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/4796126561617787918'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/10/emacs-advanced-guide-chapter-1.html' title='Emacs Advanced Guide - Chapter 1'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2381794355363305424.post-7534647009449605112</id><published>2009-10-19T19:15:00.000-07:00</published><updated>2009-10-20T06:37:07.698-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='hacks'/><title type='text'>linux下使用vpn的方法</title><content type='html'>&lt;div style="text-align: left;"&gt;公司的开发服务器使用VPN连接,在Windows下面直接使用ppoe就可以了,但是在Liunx下面并不一样.这里将我的配置过程记录一下.&lt;br /&gt;&lt;br /&gt;由于我所使用的环境是Fedora，所涉及到的软件这里全部采用yum方式安装.&lt;br /&gt;首先需要保证系统上安装pptp的相关软件:&lt;br /&gt;&lt;br /&gt;#yum install NetworkManager-pptp&lt;br /&gt;&lt;br /&gt;这样你就可以在Gnome Network Manager里面去添加VPN连接了，注意选择PPTP:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_RLf4SUMna24/St0qMkUoxLI/AAAAAAAAARU/hp9czDMtxec/s1600-h/2581125536437685998.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5394514324056753330" src="http://2.bp.blogspot.com/_RLf4SUMna24/St0qMkUoxLI/AAAAAAAAARU/hp9czDMtxec/s320/2581125536437685998.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;下面进行连接配置:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Connection Name:随便填写,方便自己即可&lt;/li&gt;&lt;li&gt;Gateway: vpn连接的ip或者域名&lt;/li&gt;&lt;li&gt;User Name:用户名&lt;/li&gt;&lt;li&gt;Password:连接的密码&lt;/li&gt;&lt;/ul&gt;&lt;a href="http://4.bp.blogspot.com/_RLf4SUMna24/St0qbKtwbMI/AAAAAAAAARc/2gA4gpRHnWc/s1600-h/3306768026397069888.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5394514574880828610" src="http://4.bp.blogspot.com/_RLf4SUMna24/St0qbKtwbMI/AAAAAAAAARc/2gA4gpRHnWc/s320/3306768026397069888.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;在Apply之前,点击Advanced,勾选Use Point-to-Point encryption(MPPE),然后OK&lt;br /&gt;&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_RLf4SUMna24/St0q1StfgYI/AAAAAAAAARk/sqnPSwRvfDY/s1600-h/2531867415513348078.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5394515023703802242" src="http://4.bp.blogspot.com/_RLf4SUMna24/St0q1StfgYI/AAAAAAAAARk/sqnPSwRvfDY/s320/2531867415513348078.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;到这里,你可以尝试下选择NetworkManager里面的VPN Connection,如果连接成功的话,那么恭喜了；如果失败的话,没关系,我们继续:&lt;br /&gt;很有可能你的VPN连接默认会使用EAP来做认证,但在NetworkManager不能 disable EAP的认证，需要使用gconf-edit才行,在你的终端中输入gconf-editor.&lt;br /&gt;&lt;br /&gt;＃gconf-editor&lt;br /&gt;然后选择system-&amp;gt;networking-&amp;gt;connetions，找到子项有vpn连接的数字,在右边新建key,内容如下:&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_RLf4SUMna24/St0rebCZcFI/AAAAAAAAARs/wYgzol2G1jc/s1600-h/1426515181970694916.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5394515730313605202" src="http://2.bp.blogspot.com/_RLf4SUMna24/St0rebCZcFI/AAAAAAAAARs/wYgzol2G1jc/s400/1426515181970694916.jpg" style="height: 324px; width: 400px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;最后,连接到你的vpn服务器吧.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2381794355363305424-7534647009449605112?l=gfnpad.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://gfnpad.blogspot.com/feeds/7534647009449605112/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://gfnpad.blogspot.com/2009/10/linuxvpn.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/7534647009449605112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2381794355363305424/posts/default/7534647009449605112'/><link rel='alternate' type='text/html' href='http://gfnpad.blogspot.com/2009/10/linuxvpn.html' title='linux下使用vpn的方法'/><author><name>Guang Feng</name><uri>http://www.blogger.com/profile/04442436011950175510</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='31' src='http://4.bp.blogspot.com/_RLf4SUMna24/St0YBzuh7yI/AAAAAAAAAQo/0qCQ5M326m4/S220/2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_RLf4SUMna24/St0qMkUoxLI/AAAAAAAAARU/hp9czDMtxec/s72-c/2581125536437685998.jpg' height='72' width='72'/><thr:total>0</thr:total></entry></feed>
