站点图标 久久日记本

火车网站的自动登录

构思:

这两天,做了一件灰常有意义的事情。带来的最直接的成果是省了几包烟下来:)

因为最近我需要经常登录某个网站,而基本上每天早上我去登录时,都说系统已达最大在线人数。如果我不通过这个网站,据说需要几包烟来打通关系,因此我写了个自动登录的小程序,保证我能在服务开通的时刻第一时间登录。所以就可以把这几包烟省下来孝敬老爸了,哈哈。

担心万一此文扩散到某些地方,他们一调整,我也得跟着调整我的程序了,所以暂时不公开此网站具体信息:)

废话少说,切入正题。

1、失败的模拟预订

看网站页面的url,是asp写的。不过这网站看上去挺正式,估计直接操作数据库有点费事,还是做些客户端的模拟动作比较简单,因此也不打算关心是. net/lamp/java了。登录这个网站主要是为了做一个类似预订的操作,只不过有一个只能提前10天的时间限制,如果我能够登录后模拟正常预订但是绕过客户端验证直接订一个我想要的时间,再如果刚好开发者没有在业务方法的底层再次加验证,我就能够得逞:) OK,进预订页面看一下。用FireFox(FF虽然目前看国内很多网站还有问题,但是有些功能还是挺好使,我通常会装一个备用)的FireDebug插件Inspect一下,不太妙,预订那个按钮的发送参数里好像没有日期相关参数。再次确认,用Ethereal抓个包看一下(用什么抓包好?我不知道,只是比较习惯Ethereal的格式),果然,网站的开发者还是比较敬业,可能是为了防止向我这样的人的不良企图,没有直接传日期为参数,而是用固定的类似1 2 3 4代码表示合法范围内的预订日期,由服务器再转换为具体日期,看来超前预订的想法不太可能了,怎么办涅。。。

2.一些发现

抓下几个包来看了一下,得出几点:a、对于显示可预订日期、可预订位置、预订等几个关键请求,都是通过POST来发送的;b、POST时,会利用前一个页面的一个类似与STATUS的加密字符串做验证;c、会验证浏览器cookie和sesion。回过头来看,这些发现其实最后都没有用上,所以略过。

3.决定自动登录

既然提前预订不行,那只能是在早上服务放开时尽可能早的登录上去了。或者是时间过零点之后,服务开放之前看有没有可能登录上去。经过确认发现,网站关闭的时间段内,不但是入口地址,几个关键的url都无法直接访问,而且关闭和开放的时间,每天都不完全一样,貌似有人在每天这个时候手工重启web服务。看来人家做的还是相当敬业,想要在非服务时间登录,有难度。只有试试,在服务开放的第一时间自动登陆了。我始终相信,机器肯定跑的比人快:)

4.验证码识别失败

要自动登录,其他的思路都很明确:

a.轮询入口地址;

b.内容匹配,看是否出现需要的字段,也就是服务是否已放开;

c.一旦服务已放开,正则获取页面的STAT字段,以及浏览器的cookie sessionid;

d.根据Ethereal抓取的内容,填上我的UserName等字段,POST;

这些,用PHP的socket读写,很快就可以搞定。剩下唯一的问题是:验证码输入。这个网站的验证码,说简单不简单,说复杂也不复杂,是带干扰背景、彩色规则字体的5位数字。先用自己机器上的原有的一套识别代码试了下(曾经被用来测试我做的另一个网站的登录:),不灵,再google了一套试,还是不灵。晕了。。。

5.模拟精灵

柳暗花明。在找验证码识别代码的过程中,发现了模拟精灵,号称很弓虽大。这个工具是用一种基于LUA的所谓LAscript,倒是简明易懂。看了下web、element等几个库的方法,呵呵,和ruby极其类似,以好用为第一要义。再看image库的方法,image.bpp(),可以变为黑白色!有戏!那就用这个工具试试吧。

6.采样

首先要采集一下验证码单个数字的样本,需要把每个图片里的5个数字切割出来。这好办,取一个验证码图片,到PhotoShop里看一下,把5个数字的像素位置定一下。然后用LAScript脚本,写个循环,获取几次验证码图片(image.getURL),切割(image.Crop),去色(image.bpp),保存(image.save)。保证0-9的样本都有了。

7.试验

样本采集完了,试验一下。这里要相当注意:保存样本的时候对图片做了什么操作,对被验证图片要做完全一样的操作。因为,其中关键方法image.testXX()的基本原理是:拿样本图片和被验证图片逐个像素的去比较,根据最后差异的值(最小值0,最大值图片尺寸相关)判断是否相似。所以如果截图时挪了一个像素,结果就全错。哈哈!测试结果:准确率90%左右!

8.成功

接下去的事情就好办了,LAScript很好用,附带的教程也简明扼要。就按照step 4 的逻辑,比原来的php代码简单很多,因为根本不需要自己来发送POST包了。LAScript的主要设计目的之一就是为了做类似模拟的功能,所以获取图片(web.eleImages),在网页input框输入文本(element.setAttribute),提交表单(element.click) 都有现成方法。

大功告成!NND,俺不用再一早起来,手忙脚乱的猛敲键盘了。

原创地址转载,请尊重原作者版权,转载加上链接

退出移动版