書接上回,今天我將把查詢和訂票的整個過程詳細的介紹給你們。javascript
1、查詢餘票信息html
首先,咱們抓下查詢餘票的http請求(如下圖的查詢爲例子)java
完整的http請求以下:web
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%3A00apache
請求的參數:服務器
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:00post
咱們看到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表示出發時間。ui
接着看這個請求響應的結果(結果太長了,就拿一條記錄來分析)編碼
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>spa
響應的結果一段字符串,上面是截取的一條記錄,觀察發現響應的結果是返回車次信息,每條記錄以\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表示訂單編號,當訂單成功後這個值纔會出現。
至此,整個查詢,下訂單的過程完成了。
最後上一張我寫的查詢訂票的圖: