書接上回,今天我將把查詢和訂票的整個過程詳細的介紹給大家。
一、查詢余票信息
首先,我們抓下查詢余票的http請求(以下圖的查詢為例子)
完整的http請求如下:
https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=queryLeftTicket&orderRequest.train_date=2013-10-11&orderRequest.from_station_telecode=BJP&orderRequest.to_station_telecode=WHN&orderRequest.train_no=&trainPassType=QB&trainClass=QB%23D%23Z%23T%23K%23QT%23&includeStudent=00&seatTypeAndNum=&orderRequest.start_time_str=00%3A00--24%3A00
請求的參數:
method:queryLeftTicket
orderRequest.train_date:2013-10-11
orderRequest.from_station_telecode:BJP
orderRequest.to_station_telecode:WHN
orderRequest.train_no:
trainPassType:QB
trainClass:QB#D#Z#T#K#QT#
includeStudent:00
seatTypeAndNum:
orderRequest.start_time_str:00:00--24:00
我們看到method這個參數,從字面的意思看出來了,是查詢余票的。接着orderRequest.train_date表示乘車日期,orderRequest.from_station_telecode表示出發地的簡碼,orderRequest.to_station_telecode表示目的地的簡碼,orderRequest.train_no車次編碼,trainPassType表示車的路過的類型,分別是全部:QB,始發:SF,路過:LG,trainClass表示車的類型,分別是:全部:QB,D車:D,Z字頭:Z,T字頭:T,K字頭:K,其他:QT,如果多選中間以#連接。includeStudent表示是否是包含學生票,包含為0X00,不包含為00,seatTypeAndNum席別和數量,在這一步暫時沒什么用。orderRequest.start_time_str表示出發時間。
接着看這個請求響應的結果(結果太長了,就拿一條記錄來分析)
0,<span id='id_330000K5980K' class='base_txtdiv' onmouseover=javascript:onStopHover('330000K5980K#BXP#WCN') onmouseout='onStopOut()'>K599</span>, 北京西 <br> 05:20, 武昌 <br> 20:37,15:17,--,--,--,--,--,9,4,--,8,<font color='#008800'>有</font>,--,<a name='btn130_2' class='btn130_2' style='text-decoration:none;' onclick=javascript:getSelected('K599#15:17#05:20#330000K5980K#BXP#WCN#20:37#北京西#武昌#08#27#1*****30364*****00091*****00083*****0004#MUFFMDhDQTNCNEMzQjMwMTU4Qzg5NjdDODMxREI2MkNFODFDMThEREM3MzM0NDA5NEY0RTUzMTU6Ojo6MTM4MTMwMTIxMTg2MQ==#C1')>預 訂</a>
響應的結果一段字符串,上面是截取的一條記錄,觀察發現響應的結果是返回車次信息,每條記錄以\n結束。
而對於一條記錄來說,是以“,”隔開的各個信息字段,對應於查詢結果表格中的各個字段。
重點說下下面這個數據:
<a name='btn130_2' class='btn130_2' style='text-decoration:none;' onclick=javascript:getSelected('K599#15:17#05:20#330000K5980K#BXP#WCN#20:37#北京西#武昌#08#27#1*****30364*****00091*****00083*****0004#MUFFMDhDQTNCNEMzQjMwMTU4Qzg5NjdDODMxREI2MkNFODFDMThEREM3MzM0NDA5NEY0RTUzMTU6Ojo6MTM4MTMwMTIxMTg2MQ==#C1')>預 訂</a>
這個是當用戶點擊預定的時候,要向服務器發送的數據,數據是以#隔開的,這個我把它稱為orderkey。
OK,當我們點擊預定的時候,看下發生了哪些http請求
post:https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=submutOrderRequest
post的數據:
station_train_code:K599
train_date:2013-10-11
seattype_num: from_station_telecode:BXP
to_station_telecode:WCN
include_student:00
from_station_telecode_name:北京
to_station_telecode_name:武漢
round_train_date:2013-10-09
round_start_time_str:00:00--24:00
single_round_type:1 train_pass_type:QB
train_class_arr:QB#D#Z#T#K#QT#
start_time_str:00:00--24:00
lishi:15:17
train_start_time:05:20
trainno4:330000K5980K
arrive_time:20:37
from_station_name:北京西
to_station_name:武昌
from_station_no:08
to_station_no:27
ypInfoDetail:1*****30364*****00091*****00083*****0004
mmStr:Qzg1NUEzMzUzQTUwQzgzQUVFRkM1MDM0MDk4QkNEMzM4QUU1OUQ0MjNEODMyNERDNENDMjY3QkY6Ojo6MTM4MTMwMTE0Mzk4OQ==
locationCode:C1
OTkwNjU2OA==:YWJjYjU2NDBiOTE0MWViZQ==
myversion:undefined
上面的參數我們大多數都可以通過點擊預定時候的那個"orderkey"獲取到,只是后面的多了一個紅色標注的動態key和動態value,這個在上一面文章已經提到過怎么得到了,這里就不再多說。
返回的結果是一個302,302的地址是:
https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init
打開這個頁面,發現是選擇乘客信息的和提交訂單的頁面。
接着我們選擇乘客人,輸入驗證碼后提交,看發生了哪些請求:
post:https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=checkOrderInfo&rand=x8t6
rand表示驗證碼,從method的字面意思看是檢測訂單信息
post數據:
如上圖所示這個post的數據中,包含了乘車信息,和乘客信息。乘車信息,在上一步預定的時候都可以得到,乘客信息呢,觀察得到,
https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=getpassengerJson 這個地址可以得到用戶的所有乘客人信息,通過選擇的乘客信息,可以構造出我們要提交的數據。
post的數據當中org.apache.struts.taglib.html.TOKEN和leftTicketStr是怎么來的呢,回頭看看預定后的那個302地址,發現源碼里面有這么一段
<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="21f84a6c22c03df66fcd90a5d1eb9818">
<input type="hidden" name="leftTicketStr" id="left_ticket" value="1015253036404275000910152500083027050004" />
對比上面post的數據的值,這個正是我們需要的,所以,從302地址的源碼我們可以得到這些值了。
看看請求的結果:
{"checkHuimd":"Y","check608":"Y","msg":"","errMsg":"Y"}
其中checkHuimd為N的話說明:由於您取消次數過多,今日將不能繼續受理您的訂票請求!
check608為N的話說明:本車為實名制列車,實行一日一車一證一票制!
當上面那2個值有一個為N的話,msg將顯示錯誤信息。
OK,如果這一步無錯誤信息提示,將繼續查詢余票信息
get:https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=getQueueCount&train_date=2013-10-11&train_no=330000K5980K&station=K599&seat=3&from=BXP&to=WCN&ticket=1015253035404275000910152500003027050004
返回的結果是:
{"countT":0,"count":0,"ticket":"1*****30354*****00091*****00003*****0004","op_1":false,"op_2":false}
如果op_2為true的話表示目前排隊人數已經超過余票張數,countT表示目前排隊人數。
ticket表示余票信息。
如果有票的話,我們繼續請求:
post:https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=confirmSingleForQueue
post的數據和檢測訂單的數據大致一樣,只是少了一個tFlag:dc。
響應的結果:{"errMsg":"Y"},這就表示訂單確認成功了。如果errMsg為N的話,響應的結果會出現msg信息來表示錯誤信息。
訂單確認成功了,我們還得取檢測下訂單是否完成
get:https://dynamic.12306.cn/otsweb/order/myOrderAction.do?method=queryOrderWaitTime&tourFlag=dc
響應的結果:{"tourFlag":"dc","waitTime":-1,"waitCount":0,"orderId":"E493113786","requestId":5793605912349971391,"count":0}
waitTime表示排隊等待的時間,如果為-1表示訂單成功了,可以去付款了。orderId表示訂單編號,當訂單成功后這個值才會出現。
至此,整個查詢,下訂單的過程完成了。
最后上一張我寫的查詢訂票的圖: