铁路客服订票系统详解

订火车票,较难的步骤在用户登陆和提交车票订单。

一,用户登陆稍许容易手工进入,但其原理却比较复杂:

1,登录表单页面是 http 和 https 混合的多 iframe 页面,其中可以剥离出来独立工作的单元为 https://dynamic.12306.cn/otsweb/ ——含一层 iframe 的双层结构。其图形验证码只有在 iframe 内刷新或两层都刷新时才会自动更新,否则需要手动点击更新。

2,正常填写表单结束时,按提交按钮,执行 http://dynamic.12306.cn//otsweb/js/login.js 中的 checkAysnSuggest(),此时客户端脚本会用 AJAX 技术向服务器发送 https://dynamic.12306.cn/otsweb/loginAction.do?method=loginAysnSuggest 连接测试请求——这个 POST 请求没有数据内容,只有 HTTP 头,如果连接被弹回,则会收到 {"randError":"当前访问用户过多,请稍候重试!","randErrorFocus":"focus"},alert,清除密码和验证码值;若测试成功,就会收到 {"randError":"Y"},然后客户端执行 subForm()——先简单检测下表单是否填写或密码是否够长,然后就正式提交表单(https://dynamic.12306.cn/otsweb/loginAction.do?method=login),POST 内容如下:
loginUser.user_name 用户名
nameErrorFocus
passwordErrorFocus
randCode 验证码
randErrorFocus focus
user.password 密码
由于是 AJAX,这一“发送-接收-发送”过程的当前页面不会被刷掉(图形验证码不变),完全可以自己写脚本反复尝试登陆,并且去掉连接测试和表单自检过程直接提交表单。

3,但是想要反复自动提交还是有风险,如果正式提交时被服务器驳回,那么除了 alert 外,整个双层结构的页面都会被刷新掉,这不是 AJAX,而只是框架和表单提交,所以图形验证码会改变。因此,没有 OCR 程序的情况下不能简单 submit(),只能使用 AJAX 请求——先 POST,得到文本回应后根据某些特征判断是不是依旧为未登录页面,如果不是则最好,直接 document.open()、close() 替换当前文档;是的话无视回应,什么都不做,继续下一次登录,这样图形验证码就不会改变了。可以把这一过程写成循环或递归。

/* Firefox 铁杆用户 Firebug 党专用:*/
var dobj = {
randCode: '第一次登录前看到的验证码',
'loginUser.user_name': '你的用户名',
'user.password': '你的密码',
nameErrorFocus: '',
passwordErrorFocus: '',
randErrorFocus: 'focus'
};
function dback(ddat) {
if (ddat.indexOf('你的实名') > 0) {
var dnewDoc = document.open();
dnewDoc.write(ddat);
dnewDoc.close();
}
}
function dsub() {
jQuery.post('/otsweb/loginAction.do?method=login', dobj, dback, 'text');
}
setInterval(dsub, 1000);

二,提交车票订单这一步实在太痛苦了,因为数据库压力极大,被弹回是 99% 的事;但原理和第一步类似,甚至更简单些,用同样的方法也能改成循环或递归。这一步的代码不贴出了,读者自己钻研吧。