spanmysql lc messagess

AngularJS - 表单验证
虽然我不是前端程序员,但明白前端做好验证是多么重要。因为这样后端就可以多喘口气了,而且相比后端什么的果然还是前端可以提高用户的幸福感。AngularJS提供了很方便的表单验证功能,在此记录一番。首先从下面这段代码开始&form ng-app=&myApp& ng-controller=&validationController& name=&mainForm& novalidate& &p&Email:
&input type=&email& name=&email& ng-model=&email& required&
&span style=&color:red& ng-show=&mainForm.email.$dirty && mainForm.email.$invalid&&
&span ng-show=&mainForm.email.$error.required&&Email is required.&/span&
&span ng-show=&mainForm.email.$error.email&&Invalid email address.&/span&
&/span& &/p& &p&
&input type=&submit& ng-disabled=&mainForm.$invalid&& &/p&&/form&&script&angular.module('myApp',[]).controller('validationController', ['$scope',function($scope) { $scope.user = 'Kavlez'; $scope.email = 'sweet_';}]);&/script&input标签的一些验证选项,通常和HTML5标记搭配使用。必填&input type=&text& required /&长度使用指令ng-minlength/ng-maxlength&input type=&text& ng-minlength=&5& /&特定格式例如电子邮件、URL、数字,将type设置为相应类型即可,例如:&input type=&email& name=&email& ng-model=&user.email& /&&input type=&number& name=&age& ng-model=&user.age& /&&input type=&url& name=&homepage& ng-model=&user.facebook_url& /&模式匹配使用指令ng-pattern,例如:&input type=&text& ng-pattern=&[a-z]& /&表单属性,通过这些属性可以更容易地对表单进行操作$pristine / $dirty表示是否已修改,例如&form name=&mainForm& ng-controller=&orderController&&&input type=&email& name=&userEmail& ng-model=&myEmail& /&{{mainForm.userEmail.$pristine}}{{mainForm.userEmail.$dirty}}&/form&以formName.fieldName.$pristine方式访问,input必须有ng-model声明。$valid / $invalid表示是否通过验证。$error表单验证信息,验证不通过时返回相应信息。AngularJS为表单状态提供了相应地css class.ng-pristine.ng-dirty.ng-valid.ng-invalid例如,让验证通过为绿色,失败为红色:input.ng-valid {color:}input.ng-invalid {color:}给出的例子中仅仅是一个email的验证就写了这么多,如果再加几个field,再加几种不同的提示,再加上几个事件,代码会变得杂乱不堪。事实上并不推荐这样做,我们有更好的方法。就是使用angular-messages.js首先,不要忘了这两步&script src=&angular-messages.js&&&/script&angular.module('myApp', ['ngMessages'])好,先用ng-messages和ng-message替换掉那些重复的东西,上面的例子变成:&form ng-controller=&validationController& name=&mainForm& & &p&Email:
type=&email& name=&email& ng-model=&myEmail& ng-minlength=&3& ng-maxlength=&50& required /&
&div style=&color:red& ng-messages=&mainForm.email.$error& ng-messages-multiple&
&p class=&error& ng-message=&required&&Email is required.&/p&
&p class=&error& ng-message=&email&&Invalid email address.&/p&
&p class=&error& ng-message=&minlength&&min length 10&/p&
&p class=&error& ng-message=&maxlength&&max length 50&/p&
&/div& &/p& &p&
&input type=&submit& ng-disabled=&mainForm.$invalid& /& &/p&&/form&功能上没有任何变化,只是把重复的代码全部去掉了。注意区分ng-messasges和ng-message,有没有感觉有点像with()? 后面的ng-messages-multiple,这里用作同时让多个提示出现。但这样仍然不够好,就算省去了ng-message中的内容,但是多个field中都存在required验证时仍然会有重复。而且,如果不同页面中的表单都涉及到相同的内容时重复的验证提示会越来越多。为了解决这个问题,我们可以使用ng-messages-include指令。该指令用来引用模板,比如上面的例子变为:&form ng-controller=&validationController& name=&mainForm& & &p&Email:
type=&email& name=&email& ng-model=&myEmail& ng-minlength=&3& ng-maxlength=&50& required /&
&div style=&color:red& ng-messages=&mainForm.email.$error& ng-messages-multiple ng-messages-include=&validateTemplate/email.html&&
&/div& &/p& &p&
&input type=&submit& ng-disabled=&mainForm.$invalid& /& &/p&&/form& 并不复杂,我们再加点东西。为了让提示更友好(?)一些,我们试试实现光标离开后出现提示的效果。这时候用指令(directive)会方便很多,在这里先涉及一点和指令相关的内容。先运行起来再说:var myApp = angular.module('myApp',[]) .controller('validationController', ['$scope',function($scope) {
$scope.user = 'Kavlez';
$scope.email = 'sweet_'; }]) .directive('hintOnBlur', [function() {
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
ctrl.focused =
element.bind('focus', function(evt) {
scope.$apply(function() {ctrl.focused =});
}).bind('blur', function(evt) {
scope.$apply(function() {ctrl.focused =});
} }]);此处我们用focused来判断光标是否在某个属性上,当使用了hintOnBlur指令的对象上发生focus或blur事件时focused的状态发生变化。表单也跟着改变一下,使用方法如下:&form ng-controller=&validationController& name=&mainForm& & &p&Email:
type=&email& name=&email& ng-model=&myEmail& ng-minlength=&3& ng-maxlength=&50& required hint-on-blur /&
&div style=&color:red& ng-messages=&mainForm.email.$error& ng-show=&!mainForm.email.focused& ng-messages-multiple ng-messages-include=&validateTemplate/email.html&&
&/div& &/p& &p&
&input type=&submit& ng-disabled=&mainForm.$invalid& /& &/p&&/form& 在ng-show中再加入对focused的判断,false时出现提示。现在看起来像那么回事了。自定义验证方式与有效性(validity),这个也用到指令(directive)。验证填写的email是否已占用,这里简单模拟一下:.directive('isAlreadyTaken', function() { return {
require: 'ngModel',
link: function(scope, ele, attrs, ctrl) {
ctrl.$parsers.push(function(val) {
ctrl.$setValidity('emailAvailable', false);
var emailTable = [
for (var i=0;i&emailTable.i+=1)
if(val==emailTable[i])
ctrl.$setValidity('emailAvailable', true);
} }})Input元素中加上is-already-taken属性,并且再加一个ng-message:&p class=&error& ng-message=&emailAvailable&&Already taken! try other email addresses!&/p&
最新教程周点击榜
微信扫一扫随笔 - 2146&
文章 - 94&评论 - 11656&trackbacks - 253
随笔分类 - 25.时间操作及相关函数
摘要: //相关函数:SysUtils.DateTimeToFileDate();SysUtils.FileDateToDateTime();SysUtils.DateTimeToSystemTime();SysUtils.SystemTimeToDateTime();Windows.SystemTimeToFileTime();Windows.FileTimeToSystemTime();Windows...
万一 阅读(3606) |
摘要: //相关函数:SysUtils.DateTimeToTimeStamp();SysUtils.TimeStampToDateTime();SysUtils.TimeStampToMSecs();SysUtils.MSecsToTimeStamp();Windows.GetTickCWindows.GetCurrentT {GetCurrentTime 和 GetTickCount...
万一 阅读(3046) |
摘要: //相关函数:SysUtils.FloatToDateTime();SysUtils.TryFloatToDateTime();在 System 单元定义有: TDateTime = type D看来 TDateTime 是一个 8 字节 64 位数据, 不过是 Double 的别名.{测试: TDateTime 就是一个 Double}var
万一 阅读(4081) |
摘要: SysUtils.StrToDate();SysUtils.StrToDateDef();SysUtils.TryStrToDate();SysUtils.StrToTime();SysUtils.StrToTimeDef();SysUtils.TryStrToTime();SysUtils.StrToDateTime();SysUtils.StrToDateTimeDef();SysUtils....
万一 阅读(3085) |
摘要: SysUtils.NSysUtils.DSysUtils.TSysUtils.CurrentYunit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
TForm1 = class(TForm) ...
万一 阅读(2748) |
摘要: unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
TForm1 = class(TForm) procedure FormCreate(Sender: TObject);var
Form1: TForm1...
万一 阅读(2013) |
摘要: unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtype
TForm1 = class(TForm) procedure FormCreate(Sender: TObject);var
万一 阅读(2007) |
摘要: unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtype
TForm1 = class(TForm) procedure FormCreate(Sender: TObject);var
万一 阅读(1538) |
摘要: SysUtils.IsLeapYear();DateUtils.IsInLeapYear();unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtype
TForm1 = class(TForm) proce...
万一 阅读(1643) |
摘要: DateUtils.IsValidDateTimeDateUtils.IsValidDateDateUtils.IsValidTimeDateUtils.IsValidDateDayDateUtils.IsValidDateWeekDateUtils.IsValidDateMonthWeek//可用下面几个过程抛出异常:DateUtils.InvalidDateDayErrorDateUtils....
万一 阅读(2107) |
摘要: DateUtils.RecodeDateTime();DateUtils.RecodeDate();DateUtils.RecodeTime();DateUtils.RecodeYear();DateUtils.RecodeMonth();DateUtils.RecodeDay();DateUtils.RecodeHour();DateUtils.RecodeMinute();DateUtils....
万一 阅读(1586) |
摘要: SysUtils.DecodeDate();SysUtils.DecodeDateFully();SysUtils.DecodeTime();DateUtils.DecodeDateTime();DateUtils.DecodeDateDay();DateUtils.DecodeDateWeek();DateUtils.DecodeDateMonthWeek();DateUtils.DecodeD...
万一 阅读(3486) |
摘要: SysUtils.EncodeDateTimeSysUtils.EncodeDateSysUtils.EncodeTimeDateUtils.EncodeDateDayDateUtils.EncodeDateMonthWeekDateUtils.EncodeDateTimeDateUtils.EncodeDateWeekDateUtils.EncodeDayOfWeekInMonthDateUti...
万一 阅读(2150) |
摘要: DateUtils.WithinPastYears();DateUtils.WithinPastMonths();DateUtils.WithinPastWeeks();DateUtils.WithinPastDays();DateUtils.WithinPastHours();DateUtils.WithinPastMinutes();DateUtils.WithinPastSeconds();...
万一 阅读(1647) |
摘要: {参数是指定的年、月、周、日}DateUtils.StartOfAYear DateUtils.StartOfAMonthDateUtils.StartOfAWeek DateUtils.StartOfADay{参数是 TDateTime}DateUtils.StartOfTheYear DateUtils.StartOfTheMonthDateUtils.StartOfTheWeek DateU...
万一 阅读(2188) |
摘要: DateUtils.IncYear();DateUtils.IncMonth();DateUtils.IncWeek();DateUtils.IncDay();DateUtils.IncHour();DateUtils.IncMinute();DateUtils.IncSecond();DateUtils.IncMilliSecond();unit Unit1;interfaceuses
万一 阅读(4615) |
摘要: DateUtils.YearsBetween();DateUtils.MonthsBetween();DateUtils.WeeksBetween();DateUtils.DaysBetween();DateUtils.HoursBetween();DateUtils.MinutesBetween();DateUtils.SecondsBetween();DateUtils.MilliSecond...
万一 阅读(2775) |
摘要: SysUtils.DayOfWeek();DateUtils.MonthOfTheYear();DateUtils.WeekOfTheYear();DateUtils.WeekOfTheMonth();DateUtils.NthDayOfWeek();DateUtils.DayOfTheYear();DateUtils.DayOfTheMonth();DateUtils.DayOfTheWeek(...
万一 阅读(2764) |
摘要: 它们的参数都是一个 TDateTime, DateOf、TimeOf 分别提取日期与时间, 并返回 TDateTime 类型;YearOf、MonthOf、WeekOf、DayOf、HourOf、MinuteOf、SecondOf、MilliSecondOf 返回的都是 Word 类型.unit Unit1;interfaceuses
Windows, Messages, SysUtils, V...
万一 阅读(2445) |
摘要: CompareDateTime、CompareDate、CompareTime 返回的是 -1、0、1;前者 = 后者: 返回 0;前者 & 后者: 返回 1;前者 SameDateTime、SameDate、SameTime 返回的是 True 和 False.unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Cla...
万一 阅读(2301) |
摘要: pareTimeDateUtils.DateOfDateUtils.DateTimeToJulianDateDateUtils.DateTimeToModifiedJulianDateDateUtils.DateTimeToUnixDateUtils.DayOfDateUtils....
万一 阅读(4625) |
万一 阅读(3402) |解析12306订票流程 - 推酷
解析12306订票流程
每当春节临近时,因为网络的方便,访问12306购买火车票回家过年成了很多人的首选。但由于12306的种种不给力,给那些在官网刷票的人带来了很多的不便。从2011年未12306上线起,连续几年回家我都是靠网上购票,今年也不例外;我记得11年时我使用的是官网直接购票,到了12年则使用了新出的木鱼抢票助手,而今年我用了360与猎豹两款主流抢票浏览器,还发动了几位朋友一起帮忙,才买到了一张差强人意的票,现在感觉买票是越来越困难。而就在前几天媒体还曝出了商业黄牛使用假身份证生成器10分钟钞杀1000多张票的新闻,让人吃惊不已。于是就萌生了自己写一个抢票应用的念头,最开始设想的就是本地桌面应用,而非浏览器插件,个人觉得本地应用始终比浏览器插件敏捷,因为本地应用可以精确稳定的请求有用的链接,过滤图片和CSS等前台无用请求,可以节省网络消耗时间。于是我花了一段时间将12306的整体订票流程解析了一遍,其间还经历了一次12306的改版,幸好主体流程改动不是很大,终算有点收获。
粗略的将12306的流程划分为:登录、查询和订票三大模块,下面就这三大模块逐一说明:
登录12306请求的URL是:
,可以使用Firbug抓取一下它的请求头,得到的response响应内容如下:
从中可以看到Set-Cookie信息,也就是说,如果想要登录就必须先请求
这个链接,以获取服务端设置的Cookie信息,而有了该Cookie信息就可以将其保存,以备下步的请求使用。
再来分析一下它的页面HTML与其对应处理登录的Javascript脚本文件(
),得到如下流程:
1.用户点击登录提交时先要验证请求一下:
链接,用于判断当前网络环境是否可以登录,得到JSON数据(通过Firebug抓包):
&validateMessagesShowId&:&_validatorMessage&
&status&:true
&httpstatus&:200,
&loginCheck&:&Y&
&messages&:[],
&validateMessages&:{}
这里通过判断
data.loginCheck
是否为字符串
判断用户是否可以登录,如不能登录,则显示messages中的内容.
2.当用户登录信息检查成功时,则POST请求
,得到登录请求后的HTML,对应请求的参数为:
&loginUserDTO.user_name&:
&userDTO.password&:
&randCode&:
登录图片验证码的获取地址可以从登录页面的HTML中得到为:
3.通过解析获取的HTML可以根据id为login-txt的&span&标签来判断是否登录成功,登录成功的对应的HTML内容为:
&span class=&login-txt& style=&color: #666666&&
&span&意见反馈:
&a class=&cursor colorA& href=&mailto:.cn&&
&/a&您好,
&a id=&login_user& href=&/otn/index/initMy12306&
class=&colorA& style=&margin-left:-0.5&&&span&登录成功用户名&/span&&/a&|
&a id=&regist_out& href=&/otn/login/loginOut&&退出&/a&
失败的内容为:
&span class=&login-txt& style=&color: #666666&&
&span&意见反馈:
&a class=&cursor colorA& href=&mailto:.cn&&
&/a&您好,请
&a id=&login_user& href=&/otn/login/init&
class=&colorA& style=&margin-left:-0.5&&登录&/a& |
&a id=&regist_out& href=&/otn/regist/init&&注册&/a&
如上登录成功即可进行下一步的操作:对于车次的查询。
2,车次查询
新版车次预订的查询(
这里单指单程票查询
)大大减化了请求参数,只接收出发地编码,到达地编码,出发日期与
旅客编码四
个参数,所有的过滤操作都扔给了前台Javascript,这也说明了车次查询流程的简单,只需请求一个链接地址:
查询车次是通过GET:
链接获取的,对应的查询参数为(GET请求注意查询参数的顺序):
leftTicketDTO.train_date=
// 出发日期
leftTicketDTO.from_station=BJP
// 出发站编码
leftTicketDTO.to_station=SHH
// 到达站编码
purpose_codes=ADULT
// 旅客编码:成人为ADULT,学生为:0X00
对应的获取的JSON信息格式如下:
{&validateMessagesShowId&: &_validatorMessage&,
&status&: true,
&httpstatus&: 200,
{&queryLeftNewDTO&: {
&train_no&: &04&,
// 列车编号
&station_train_code&: &G141&,
&start_station_telecode&: &VNP&,
// 始发站编码
&start_station_name&: &北京南&,
// 始发站名
&end_station_telecode&: &AOH&,
// 终到站编码
&end_station_name&: &上海虹桥&,
// 终到站名
&from_station_telecode&: &VNP&,
// 查询输入经过站编码
&from_station_name&: &北京南&,
// 查询输入经过站名
&to_station_telecode&: &AOH&,
// 查询输入到站编码
&to_station_name&: &上海虹桥&,
// 查询输入到站名
&start_time&: &14:16&,
// 出发时间
&arrive_time&: &19:47&,
// 到站时间
&day_difference&: &0&,
// 花费天数
&train_class_name&: &&,
&lishi&: &05:31&,
&canWebBuy&: &Y&,
// 是否可以预定
&lishiValue&: &331&,
&yp_info&: &O00017&,
&control_train_day&: &&,
&start_train_date&: &&,
&seat_feature&: &O3M393&,
&yp_ex&: &O0M090&,
&train_seat_feature&: &3&,
&seat_types&: &OM9&,
&location_code&: &P3&,
&from_station_no&: &01&,
&to_station_no&: &09&,
&control_day&: 19,
&sale_time&: &1400&,
// 出票时间点hhmm
&is_support_card&: &1&,
&gg_num&: &--&,
&gr_num&: &--&,
// 高级软卧座剩余数
&qt_num&: &--&,
// 其他座剩余数
&rw_num&: &--&,
// 软卧座剩余数
&rz_num&: &--&,
// 软座座剩余数
&tz_num&: &--&,
// 特等座剩余数
&wz_num&: &--&,
// 无座座剩余数
&yb_num&: &--&,
&yw_num&: &--&,
// 硬卧座剩余数
&yz_num&: &--&,
// 硬座座剩余数
&ze_num&: &有&,
// 二等座剩余数
&zy_num&: &有&,
// 一等座剩余数
&swz_num&: &17&
// 商务座剩余数
&secretStr&: &预定请求令牌字符串&,
&buttonTextInfo&: &预订或开售日期&
..........
// 省略其它车次,信息同上
&messages&: [],
&validateMessages&: {}
注意这里的
属性,用于标记该趟列车是否可以预订,还有对应列车的
字符,它用于请求预订确认页面的令牌,
对于其中一直提到的列车站点编码,可以通过请求
链接,通过得到JS脚本中的station_names变量获取,对应的站点以@字符分隔,而每一个站点信息如下,这里以北京北为例:
bjb|北京北|VAP|beijingbei|bjb|0
用于提取其中有用的信息是:北京北与VAP,使用查询北京北的编码就是VAP,其它站点的解析同理。
如上即可以查询指定出发地与到达地的车次预定信息,紧接着进行预订流程的分析。
3,车票预订
在12306的解析中,就属车票预订的解析最为费神,也是最核心的一个流程,我现在只掌握了成人单程票的预订流程,其他的比如返程,学生票等都还没有分析出来,如下讲解的就是关于成人单程票的预定基本流程:
3.1,获取预定确认页面
车票预定首先要请求获取车票的预订确认页面,如下流程图所示:
该流程是在用户单击车次的“预订”按钮时触发的,如图所示,获取预订确认页面,先要判断用户是否登录,POST请求的地址是:
,这个请求无参数,然后通过判断得到的JSON信息中的
属性是否为true判断用户是否已登录,接着再根据对应列车查询时所获得的
字符与用户输入的查询信息POST请求
,判断用户是否可以访问预定确认画面,通过得到JSON信息的
属性判断是否允许访问,如果为true说明可以访问,最后依据旅行类型为单程(
)POST跳转获取单程车票的预订确认画面:
。如果登录用户不进行上述判断,直接POST请求
提示非法请求,只有成功获取预订确认页面后才能进行下一步的操作。
该流程可以查看对应JS脚本:
,function L(b4, bX)方法获知。
从请求订单的确认画面还可以得到获取当前登录用户常用联系人的链接地址为:
3.2,预订提交
在车票的预定提交之前必先要获取预定确认画面的原因是因为预订确认HTML中声明的
orderRequestDTO
ticketInfoForPassengerForm
两个Javascript变量,含有预订提交的时的必需参数信息,下面就预订提交给出粗略的流程分析图,如下:
图片可以右击后查看大图
,该流程对应的JS文件地址为:
如上图显示了车票预定提交的大体流程,可以依据请求的链接数将其分为四大块:
1.检查用户选择的乘客信息的合法性,POST请求:
,通过分析得到的JSON中的
data.submitStatus
是否为true判断,同时这一步的JSON信息中还会包含有一个
data.isCheckOrderInfo
属性将会作为下一步判断当前用户是否可排队请求的参数。对应请求参数有如下5个:
cancel_flag: &2&,
bed_level_order_num: &000000&,
passengerTicketStr: getpassengerTickets(),
// 旅客信息字符串
oldPassengerStr: getOldPassengers(),
// 旅客信息字符串
tour_flag: ticketInfoForPassengerForm.tour_flag,
// 从ticketInfoForPassengerForm中获取
randCode: $(&#randCode&).val()
// 前台输入验证码
这五个参数中,有两个参数需要注意
passengerTicketStr
oldPassengersStr
passengerTicketStr
是以下划线&_&分隔当每一个乘客信息组成的字符串,对应每个乘客信息字符串组成如下:
座位编号,0,票类型,乘客名,证件类型,证件号,手机号码,保存常用联系人(Y或N)
oldPassengersStr
也是以下划线&_&分隔每个乘客信息组成的字符串,对应每个乘客信息字符串组成如下:
乘客名,证件类型,证件号,乘客类型
在上面的信息中座位编号指的是,一等座、二等座等的编码,从
ticketInfoForPassengerForm.limitBuySeatTicketDTO.seat_type_codes
属性中选择获取。
票类型指的是,成人票,学生票等的编码,可以从
ticketInfoForPassengerForm.limitBuySeatTicketDTO.ticket_type_codes
属性中选择获取。
证件类型指的是二代身份证,学生证,签证等的编码,可以从
ticketInfoForPassengerForm.cardTypes
属性中选择获取。
oldPassengersStr
中的乘客类型主要有如下信息:
adult: &1&,
child: &2&,
student: &3&,
disability: &4&
取上面对应的数字编码。
oldPassengersStr
乘客信息字符串时,未尾会多一个下划线,提交请求是一定要补上,从上也可以看出所有的一些参数都是通过
ticketInfoForPassengerForm
变量获取的,这也是为什么要事先获取预定确认画面HTML的原因。
2.检查乘合信息合法后,接下来就会结合返回的
data.isCheckOrderInfo
属性,POST请求:
,判断当前乘客是否可以排队,对应的参数如下:
train_date: new Date(orderRequestDTO.train_date.time).toString(),
// 列车日期
train_no: orderRequestDTO.train_no,
stationTrainCode: orderRequestDTO.station_train_code,
seatType: limit_tickets[0].seat_type,
// 座位类型
fromStationTelecode: orderRequestDTO.from_station_telecode,
// 发站编号
toStationTelecode: orderRequestDTO.to_station_telecode,
// 到站编号
leftTicket: ticketInfoForPassengerForm.queryLeftTicketRequestDTO.ypInfoDetail,
purpose_codes: n,
// 默认取ADULT,表成人,学生表示为:0X00
isCheckOrderInfo: m
// data.isCheckOrderInfo
这里的参数要注意传递列车日期的方式,及座位类型编码,这里选择的是第一个乘客的座位类型编码。最后还要确保
orderRequestDTO
变量的准确性。
通过返回的JSON信息的data属性值来判断是否允许当前用户进行排队下单,并提示当前的剩余票数。
其中的data属性会包含有两个重要的参数,
1*****30314*****00001*****00003*****0000
表示的是排队人数,而
指的是当前列车对应座位的剩余票数,可以通过
文件中的function L(l, m) 函数解析获取:
function L(l, m) {
seat_1 = -1;
seat_2 = -1;
while (i & l.length) {
s = l.substr(i, 10);
c_seat = s.substr(0, 1);
if (c_seat == m) {
count = s.substr(6, 4);
while (count.length & 1 && count.substr(0, 1) == &0&) {
count = count.substr(1, count.length)
count = parseInt(count);
if (count & 3000) {
seat_1 = count
seat_2 = (count - 3000)
i = i + 10
if (seat_1 & -1) {
rt += seat_1
if (seat_2 & -1) {
rt += &,& + seat_2
函数中的l指的就是
,而m指的是第一位乘客所选择的座位编号。
如果计算的余票信息还有剩余,则会提示用户点击确认按进行订单的提交请求,如果没有充实的票,则会提示用户选择其它车次,处理该请求的方法详情见
文件中的function M(n, m) 方法。
3.当提示的有充足的余票,且用户点击了确定按钮,则接下来会POST请求:
单程票(dc)
类型的排队下单操作,通过判断返回的JSON信息
data.submitStatus
属性判断订单是否以成功提交至服务器,对应的请求参数为:
passengerTicketStr: getpassengerTickets(),
oldPassengerStr: getOldPassengers(),
randCode: $(&#randCode&).val(),
purpose_codes: ticketInfoForPassengerForm.purpose_codes,
key_check_isChange: ticketInfoForPassengerForm.key_check_isChange,
leftTicketStr: ticketInfoForPassengerForm.leftTicketStr,
train_location: ticketInfoForPassengerForm.train_location
这里的参数没有新意,主要是注意获取
ticketInfoForPassengerForm
变量的准确性。
4.订单提交至服务器后不一定说明订单已经成功了,还需要GET请求:
,判断系统是否已根据提交的订单信息为相应的乘客占位成功,并提示预估出票等待时间,这一步只有一个参数,就是旅行类型,由于我们主要考虑的是单程票,故提交时POST dc就行了,如下:
tourFlag: &dc&
这一步占位的操作在12306的官网中是将其封装在了一个名为
OrderQueueWaitTime
的对象中,可以解压
文件获知,对应的如果判断系统占位成功,将会从返的JSON信息中获取
data.orderId
属性,即为下单成功时的订单号。
如上4次请求就可以准确的模拟出12306官网订单提交的整套流程,其中其实还忽略了验证码的获取与判断操作,而这一步仅仅是判断验证码的合法性,与主体流程无关。对应订单确定页面的验证码获取链接为:
,从中与登录页面的验证码链接对比,可知新版12306的验证码管理统一为了一个方法,登录与订单确认的验证码链接只是传递的module和rand参数不一样而已。
4,结束语:
根据上面的操作,基本可以全程模拟官网的订单操作,编写出一个属于自己的抢票助手。在写这篇文章时,我一直在想这样做是否有意义,因为12306随时都有可能变更,由于23:00点~07:00点的维护时间段的设置,也许今天写出来的东西明天马上就会失效过期。但仔细考虑后还是打算将他分享出来,就当是一种学习吧。同时在这里公布GitHub上使用Python3编写的一个订票项目源码:
,对应window下独立运行exe文件下载地址为:
,软件运行效果如下:
已发表评论数()
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
没有分页内容
图片无法显示
视频无法显示
与原文不一致}

我要回帖

更多关于 jsqmessages 详解 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信