Categories

Calendar

May 2017
M T W T F S S
« Jun    
1234567
891011121314
15161718192021
22232425262728
293031  

CV 课程 Project:简单验证码的识别

验证码的识别可以说是一个非常困难的问题,更何况现在有一些验证码让人来辨认都有些不容易,当然正如我标题里说的,我这里讨论的是一种简单的验证码,具体来说就是经过旋转、缩放之后再加上一些随机线条作为干扰而得到的图片,如右图所示。其实这个问题最开始是 MSTC 第四届趣味程序设计竞赛中的一道题,这个学期上了一门《计算机视觉》课,最后要求交一个 Project ,老师给了一些题目,也可以自己想主题,于是我就定了这个主题。

由于最近各种 deadline ,我也没空把详细过程再用 blog 的方式写一遍了,如果感兴趣可以直接看我的 Report 文档以及完整的代码。

为 Python 的 HTTP 客户端加入自定义的 Cookie

几乎所有脚本语言都提供了方便的 HTTP 客户端处理的功能,Python 也不例外,使用 urllib 和 urllib2 可以很方便地进行 HTTP GET 和 POST 等各种操作。并且还允许以类似于插件的形式加入一些 handler ,来定制 request 和 response ,比如代理的支持和 cookie 的支持都是这样添加进来的。具体来说,通过如下方式构造一个 opener :

opener = urllib2.build_opener(urllib2.HTTPCookieProcessor())

然后这个 opener 就可以处理 cookie 了,相当方便,并且可定制性也……好吧,总之,现在我希望能在客户端手动插入一些 cookie 值,但是不管是 HTTPCookieProcessor 还是 cookielib 里的 CookieJar 都没有提供类似的方法可以来实现。

Duplicate Elimination in Scrapy

之前介绍 Scrapy 的时候提过 Spider Trap ,实际上,就算是正常的网络拓扑,也是很复杂的相互链接,虽然我当时给的那个例子对于我感兴趣的内容是可以有一个线性顺序依次爬下来的,但是这样的情况在真正的网络结构中通常是少之又少,一但链接网络出现环路,就无法进行拓扑排序而得出一个依次遍历的顺序了,所以 duplicate elimination 可以说是每一个 non-trivial 的必备组件之一,这样就算在遍历的过程中遇到环路也不用怕,排重组件会检测到已经访问过的地址,从而避免在环路上无限地循环下去。最简单的办法也就是每次抓取页面的时候记录下 URL ,然后每次抓取新的 URL 之前先检测一下是否已经有记录了。不过,通常我们并不直接按字符比较 URL ,因为那样通常会漏掉许多本来确实是重复的 URL ,特别是现在动态页面盛行的情况,例如在 cc98 (ZJU 的一个校内论坛)上下面几个 URL 路径是等价的:

Scrapy 轻松定制网络爬虫

网络爬虫(Web Crawler, Spider)就是一个在网络上乱爬的机器人。当然它通常并不是一个实体的机器人,因为网络本身也是虚拟的东西,所以这个“机器人”其实也就是一段程序,并且它也不是乱爬,而是有一定目的的,并且在爬行的时候会搜集一些信息。例如 Google 就有一大堆爬虫会在 Internet 上搜集网页内容以及它们之间的链接等信息;又比如一些别有用心的爬虫会在 Internet 上搜集诸如 foo@bar.com 或者 foo [at] bar [dot] com 之类的东西。除此之外,还有一些定制的爬虫,专门针对某一个网站,例如前一阵子 JavaEye 的 Robbin 就写了几篇专门对付恶意爬虫的 blog (原文链接似乎已经失效了,就不给了),还有诸如小众软件或者 LinuxToy 这样的网站也经常被整个站点 crawl 下来,换个名字挂出来。其实爬虫从基本原理上来讲很简单,只要能访问网络和分析 Web 页面即可,现在大部分语言都有方便的 Http 客户端库可以抓取 Web 页面,而 HTML 的分析最简单的可以直接用正则表达式来做,因此要做一个最简陋的网络爬虫实际上是一件很简单的事情。不过要实现一个高质量的 spider 却是非常难的。

Play Babelize with Google Translate

Have you played such a game when you were young? One person think a sentence and tell another in a whisper (or just use gesture language or anything that might loss some information when transmitting the bits). Then sentence is passed along in that way until the last one. Then he tell us what he […]

Poor Man’s Picasaweb Photo Uploading Script

虽然不太常用网络相册,但是有时候也会把照片传到 Picasaweb 上作为一个备份。如果安装了 Picasa 的话可以很方便地上传,另外,也有为 IE 做的 ActiveX 控件可以方便地批量上传照片。但是 Linux 下地 Picasa 据说是用 wine 模拟的,不想用,而浏览器也没有 ActiveX 可以用,手工一个一个地上传颇有一些麻烦。后来发现 Google 其实提供了它的各种服务的 API 的 Python binding 可以比较方便地使用,这样就可以弄一个脚本来上传了。

iRobot 之梦

iRobot 其实只是一开始胡乱找来的一个 code name ,不过现在已经成了一个小小的梦想的代名词。这个梦似乎是从 2007 年 12 月开始的。那天是去考六级,按照我以往的习惯去得有点早,教室还不让进,于是我便在东区长廊平台那里逛,想想俱乐部实践项目的事情。实践项目就是微软那边每年都会有的发放到各个俱乐部去的项目,具体做什么由自己定,当然他们那边是希望尽量和微软技术沾边的,虽然不多,但是微软也会给项目拨一些钱,不管怎么说,一些人一起做一个东西就是一件快乐的事情,这也正是俱乐部一直都在思考的一个问题啊:大家人是聚到一起了,可是要做点什么呢?虽然大家也并不是闲着,但也总想多一些点子吧!

for vs. each

虽然这个问题我是在 Python 里遇到的,但是用 Ruby 解释起来比较容易一些。在 Ruby 里,遍历一个数组可以有很多种方法,最常用的两种无非是 for 和 each:

arr = [’a’, ‘b’, ‘c’]
 
arr.each { |e|
puts e
}
 
for e in arr
puts e
end

通常我比较喜欢后者,似乎因为写起来比较好看,不过从效率上来说前者应该会稍微快一点,因为后者实际上是在遍历的过程中对每个元素都调用一个 lambda 函数来做的,虽然一般情况下并不明显,不过设置上下文并调用函数确实是有开销的,特别是在动态语言里面(不考虑 JIT 内联优化的话)。不过这次的问题并不是性能。然而确实跟“ each 对每个元素都会新建一个 scope 而 for 则不是”有关。

真·天气预报签名档

之前做了一个天气预报签名档,实际上只是显示了即时天气,这两天终于晴朗起来了(或者说,至少不下雨了),于是心情好更新了一下,顺便从 Yahoo Weather 上把未来五天的天气情况也抓下来放到图片里。总算对得起天气预报这个词了。

效果如右图所示。代码没有什么大的变化,只是实验室网络不知道为什么最近奇慢无比,由于新版本现在要下载不少图标,所以我加了本地缓存。缓存的办法很简单,就是把图标保存到一个本地文件中,要找出 URL 和本地文件的对应关系最简单的办法就是用 URL 作为本地文件名,不过通常 URL 并不是一个合法的文件名,因此,为了避免冲突,平时大家用得最多的办法就是对 URL 取一个 hash digest (比如,用 MD5 或者 SHA-1 之类的)来得到文件名。这个在 Python 中也是很容易的事,因为相关的库已经可以直接拿来用了。

天气预报签名档

也不知道有多久了,从接近开学一直到现在,杭州天天都在下雨,估计至少有二十天了吧。实在是一件让人非常郁闷的事。之前看到寒仔在 cc98 上的签名档图片是根据时间动态生成的,觉得很好玩,于是也决定弄一个动态的签名档玩玩,正好就做天气预报好了。

首先要选定一个天气来源。之前听说 iGoogle 里面的天气预报小工具预报得非常不准,除了“Current”里的天气情况和目前室外的情况差不多之外,预报的结果似乎完全不可信。 ^_^bb 其实我也完全没有看天气预报的习惯,反正我天天都带着伞的。那么我也干脆弄一个“即时”天气好了,显示当前天气,可以“足不出户,知窗外天气”——关键是要做得漂亮些。但是我又懒得去找那些天气相关的图片素材,最后随便挑选了几个天气来源,就直接选了 Yahoo Weather 。