2017-05-17 12:32:37 +00:00
# -*- coding=utf-8 -*-
import json
import datetime
2017-05-22 14:11:12 +00:00
import random
2017-05-17 12:32:37 +00:00
import re
import urllib
2017-05-21 13:39:31 +00:00
import sys
import time
2018-01-08 02:22:20 +00:00
from collections import OrderedDict
2018-01-07 01:54:36 +00:00
2018-01-08 07:28:10 +00:00
from config . ticketConf import _get_yaml
from myException . PassengerUserException import PassengerUserException
from myException . ticketConfigException import ticketConfigException
from myException . ticketIsExitsException import ticketIsExitsException
from myException . ticketNumOutException import ticketNumOutException
from myUrllib import myurllib2
2018-01-07 01:54:36 +00:00
2017-05-21 13:39:31 +00:00
reload ( sys )
sys . setdefaultencoding ( ' utf-8 ' )
2017-05-17 12:32:37 +00:00
2018-01-07 01:54:36 +00:00
2017-05-17 12:32:37 +00:00
class select :
2018-01-07 01:54:36 +00:00
def __init__ ( self ) :
2018-01-07 05:21:25 +00:00
self . from_station , self . to_station , self . station_date , self . _station_seat , self . is_more_ticket , self . ticke_peoples , self . select_refresh_interval , self . station_trains , self . expect_refresh_interval = self . get_ticket_info ( )
2017-05-21 08:48:34 +00:00
self . order_request_params = { } # 订单提交时的参数
self . ticketInfoForPassengerForm = { } # 初始化当前页面参数
self . current_seats = { } # 席别信息
2017-05-22 14:11:12 +00:00
self . token = " "
self . set_type = " "
self . user_info = " "
2018-01-07 01:54:36 +00:00
self . secretStr = " "
def get_ticket_info ( self ) :
"""
获取配置信息
: return :
"""
ticket_info_config = _get_yaml ( )
from_station = ticket_info_config [ " set " ] [ " from_station " ] . encode ( " utf8 " )
to_station = ticket_info_config [ " set " ] [ " to_station " ] . encode ( " utf8 " )
station_date = ticket_info_config [ " set " ] [ " station_date " ] . encode ( " utf8 " )
set_type = ticket_info_config [ " set " ] [ " set_type " ]
is_more_ticket = ticket_info_config [ " set " ] [ " is_more_ticket " ] . encode ( " utf8 " )
ticke_peoples = ticket_info_config [ " ticke_peoples " ]
select_refresh_interval = ticket_info_config [ " set " ] [ " select_refresh_interval " ]
2018-01-07 04:36:44 +00:00
station_trains = ticket_info_config [ " set " ] [ " station_trains " ]
2018-01-07 05:21:25 +00:00
expect_refresh_interval = ticket_info_config [ " set " ] [ " expect_refresh_interval " ]
2018-01-07 01:54:36 +00:00
print " * " * 20
2018-01-07 05:21:25 +00:00
print " 当前配置:出发站: {0} \n 到达站: {1} \n 乘车日期: {2} \n 坐席: {3} \n 是否有票自动提交: {4} \n 乘车人: {5} \n 刷新间隔: {6} \n 候选购买车次: {7} \n 未开始刷票间隔时间: {8} " . format \
2018-01-07 04:36:44 +00:00
(
from_station ,
2018-01-07 01:54:36 +00:00
to_station ,
station_date ,
" , " . join ( set_type ) ,
is_more_ticket ,
2018-01-07 04:36:44 +00:00
" , " . join ( ticke_peoples ) ,
select_refresh_interval ,
2018-01-07 05:21:25 +00:00
" , " . join ( station_trains ) ,
expect_refresh_interval ,
)
2018-01-07 01:54:36 +00:00
print " * " * 20
2018-01-07 05:21:25 +00:00
return from_station , to_station , station_date , set_type , is_more_ticket , ticke_peoples , select_refresh_interval , station_trains , expect_refresh_interval
2017-05-21 08:48:34 +00:00
def get_order_request_params ( self ) :
return self . order_request_params
def get_ticketInfoForPassengerForm ( self ) :
return self . ticketInfoForPassengerForm
def get_current_seats ( self ) :
return self . current_seats
def get_token ( self ) :
return self . token
def get_set_type ( self ) :
return self . set_type
2017-05-17 12:32:37 +00:00
def station_seat ( self , index ) :
"""
获取车票对应坐席
: param seat_type :
: return :
"""
2018-01-07 01:54:36 +00:00
seat = { ' 商务座 ' : 32 ,
' 一等座 ' : 31 ,
' 二等座 ' : 30 ,
' 特等座 ' : 25 ,
' 软卧 ' : 23 ,
' 硬卧 ' : 28 ,
' 硬座 ' : 29 ,
' 无座 ' : 26 ,
2017-05-17 12:32:37 +00:00
}
return seat [ index ]
2017-05-21 08:48:34 +00:00
def station_table ( self , from_station , to_station ) :
2017-05-17 12:32:37 +00:00
"""
读取车站信息
: param station :
: return :
"""
result = open ( ' station_name.txt ' )
info = result . read ( ) . split ( ' = ' ) [ 1 ] . strip ( " ' " ) . split ( ' @ ' )
del info [ 0 ]
station_name = { }
for i in range ( 0 , len ( info ) ) :
n_info = info [ i ] . split ( ' | ' )
station_name [ n_info [ 1 ] ] = n_info [ 2 ]
2018-01-07 01:54:36 +00:00
from_station = station_name [ from_station . encode ( " utf8 " ) ]
to_station = station_name [ to_station . encode ( " utf8 " ) ]
2017-05-17 12:32:37 +00:00
return from_station , to_station
def time ( self ) :
2018-01-07 01:54:36 +00:00
"""
获取日期
: return :
"""
2017-05-17 12:32:37 +00:00
today = datetime . date . today ( )
tomorrow = today + datetime . timedelta ( 1 )
return tomorrow . strftime ( ' % Y- % m- %d ' )
def getRepeatSubmitToken ( self ) :
"""
获取提交车票请求token
: return : token
"""
initdc_url = ' https://kyfw.12306.cn/otn/confirmPassenger/initDc '
initdc_result = myurllib2 . get ( initdc_url )
2017-05-21 08:48:34 +00:00
token_name = re . compile ( r " var globalRepeatSubmitToken = ' ( \ S+) ' " )
ticketInfoForPassengerForm_name = re . compile ( r ' var ticketInfoForPassengerForm=( \ { .+ \ })? ' )
order_request_params_name = re . compile ( r ' var orderRequestDTO=( \ { .+ \ })? ' )
# if token_name and ticketInfoForPassengerForm_name and order_request_params_name:
self . token = re . search ( token_name , initdc_result ) . group ( 1 )
re_tfpf = re . findall ( ticketInfoForPassengerForm_name , initdc_result )
re_orp = re . findall ( order_request_params_name , initdc_result )
if re_tfpf :
self . ticketInfoForPassengerForm = json . loads ( re_tfpf [ 0 ] . replace ( " ' " , ' " ' ) )
else :
2018-01-07 01:54:36 +00:00
pass
2017-05-21 08:48:34 +00:00
if re_orp :
self . order_request_params = json . loads ( re_orp [ 0 ] . replace ( " ' " , ' " ' ) )
else :
2018-01-07 01:54:36 +00:00
pass
2017-05-17 12:32:37 +00:00
2017-05-21 08:48:34 +00:00
def getPassengerDTOs ( self ) :
2017-05-17 12:32:37 +00:00
"""
获取乘客信息
: return :
"""
get_passengerDTOs = ' https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs '
get_data = {
' _json_att ' : None ,
2017-05-21 08:48:34 +00:00
' REPEAT_SUBMIT_TOKEN ' : self . token
2017-05-17 12:32:37 +00:00
}
jsonData = json . loads ( myurllib2 . Post ( get_passengerDTOs , get_data ) )
if ' data ' in jsonData and jsonData [ ' data ' ] and ' normal_passengers ' in jsonData [ ' data ' ] and jsonData [ ' data ' ] [
' normal_passengers ' ] :
2018-01-07 01:54:36 +00:00
# return jsonData['data']['normal_passengers']
normal_passengers = jsonData [ ' data ' ] [ ' normal_passengers ' ]
2018-01-08 02:22:20 +00:00
_normal_passenger = [ normal_passengers [ i ] for i in range ( len ( normal_passengers ) ) if normal_passengers [ i ] [ " passenger_name " ] in self . ticke_peoples ]
2018-01-07 01:54:36 +00:00
return _normal_passenger if _normal_passenger else normal_passengers [ 0 ] # 如果配置乘车人没有在账号,则默认返回第一个用户
2017-05-17 12:32:37 +00:00
else :
if ' data ' in jsonData and ' exMsg ' in jsonData [ ' data ' ] and jsonData [ ' data ' ] [ ' exMsg ' ] :
print ( jsonData [ ' data ' ] [ ' exMsg ' ] )
elif ' messages ' in jsonData and jsonData [ ' messages ' ] :
2017-05-23 15:09:51 +00:00
print ( jsonData [ ' messages ' ] [ 0 ] )
2017-05-17 12:32:37 +00:00
else :
print ( " 未查找到常用联系人 " )
2018-01-07 01:54:36 +00:00
raise PassengerUserException ( " 未查找到常用联系人,请先添加联系人在试试 " )
2017-05-17 12:32:37 +00:00
2018-01-08 10:46:23 +00:00
def submitOrderRequest ( self , from_station , to_station ) :
2017-05-21 08:48:34 +00:00
"""
提交车次信息
2018-01-07 01:54:36 +00:00
车次对应字典
{ 32 : ' 商务座 ' ,
31 : ' 一等座 ' ,
30 : ' 二等座 ' ,
25 : ' 特等座 ' ,
23 : ' 软卧 ' ,
28 : ' 硬卧 ' ,
29 : ' 硬座 ' ,
26 : ' 无座 '
} 参照station_seat ( ) 方法
: return :
2017-05-21 08:48:34 +00:00
"""
2018-01-07 03:12:35 +00:00
select_url = ' https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date= {0} &leftTicketDTO.from_station= {1} &leftTicketDTO.to_station= {2} &purpose_codes=ADULT ' . format ( self . station_date , from_station , to_station )
2018-01-07 01:54:36 +00:00
leftTicketLogUrl = ' https://kyfw.12306.cn/otn/leftTicket/log?leftTicketDTO.train_date= {0} &leftTicketDTO.from_station= {1} &leftTicketDTO.to_station= {2} &purpose_codes=ADULT ' . format ( self . station_date , from_station , to_station )
leftTicketLog = json . loads ( myurllib2 . get ( leftTicketLogUrl ) , encoding = ' utf-8 ' )
if " status " in leftTicketLog and leftTicketLog [ " status " ] is True :
station_ticket = json . loads ( myurllib2 . get ( select_url ) , encoding = ' utf-8 ' )
value = station_ticket [ ' data ' ]
if not value :
print ( ' {0} - {1} 车次坐席查询为空... ' . format ( self . from_station , self . to_station ) )
else :
if value [ ' result ' ] :
for i in value [ ' result ' ] :
ticket_info = i . split ( ' | ' )
2018-01-07 06:06:48 +00:00
if ticket_info [ 11 ] == " Y " and ticket_info [ 1 ] == " 预订 " : # 筛选未在开始时间内的车次
2018-01-07 05:04:25 +00:00
for j in range ( len ( self . _station_seat ) ) :
2018-01-08 10:38:17 +00:00
is_ticket_pass = ticket_info [ self . station_seat ( self . _station_seat [ j ] . encode ( " utf8 " ) ) ]
if is_ticket_pass != ' ' and is_ticket_pass != ' 无 ' and ticket_info [ 3 ] in self . station_trains and is_ticket_pass != ' * ' : # 过滤有效目标车次
2018-01-07 05:04:25 +00:00
# tiket_values = [k for k in value['map'].values()]
self . secretStr = ticket_info [ 0 ]
print ( ' 车次: ' + ticket_info [ 3 ] + ' 始发车站: ' + self . to_station + ' 终点站: ' +
self . to_station + ' ' + self . _station_seat [ j ] . encode ( " utf8 " ) + ' : ' + ticket_info [ self . station_seat ( self . _station_seat [ j ] . encode ( " utf8 " ) ) ] )
print ( ' 正在尝试提交订票... ' )
2018-01-08 05:52:15 +00:00
if self . check_user ( ) :
self . submit_station ( )
self . getPassengerTicketStr ( self . _station_seat [ j ] . encode ( " utf8 " ) )
self . getRepeatSubmitToken ( )
self . user_info = self . getPassengerDTOs ( )
if self . checkOrderInfo ( ) :
if self . getQueueCount ( ) :
break
2018-01-07 05:04:25 +00:00
else :
pass
2018-01-07 06:06:48 +00:00
print " 当前车次 {0} 查询无符合条件坐席,正在重新查询 " . format ( ticket_info [ 3 ] )
elif ticket_info [ 11 ] == " N " :
print ( " 当前车次 {0} 无票 " . format ( ticket_info [ 3 ] ) )
2018-01-07 05:04:25 +00:00
else :
print ( " 当前这次还处于待售状态,请耐心等待 " )
2018-01-07 05:21:25 +00:00
time . sleep ( self . expect_refresh_interval )
2018-01-07 01:54:36 +00:00
else :
raise ticketConfigException ( " 车次配置信息有误,请检查 " )
else :
if " message " in leftTicketLog and leftTicketLog [ " message " ] :
print leftTicketLog [ " message " ]
elif " validateMessages " in leftTicketLog and leftTicketLog [ " validateMessages " ] :
print leftTicketLog [ " validateMessages " ]
2017-05-21 08:48:34 +00:00
2018-01-07 01:54:36 +00:00
def check_user ( self ) :
"""
检查用户是否达到订票条件
: return :
"""
2017-05-17 12:32:37 +00:00
check_user_url = ' https://kyfw.12306.cn/otn/login/checkUser '
2018-01-07 01:54:36 +00:00
data = dict ( _json_att = None )
check_user = json . loads ( myurllib2 . Post ( check_user_url , data ) , encoding = ' utf-8 ' )
check_user_flag = check_user [ ' data ' ] [ ' flag ' ]
if check_user_flag is True :
print ( ' 订票成功! ' )
print ( ' 尝试提交订单... ' )
return True
2017-05-17 12:32:37 +00:00
else :
2018-01-07 01:54:36 +00:00
if check_user [ ' messages ' ] :
2018-01-07 05:21:25 +00:00
print ( ' 用户检查失败: %s , 可能未登录, 可能session已经失效' % check_user [ ' messages ' ] [ 0 ] )
2018-01-07 01:54:36 +00:00
else :
2018-01-07 05:21:25 +00:00
print ( ' 用户检查失败: %s , 可能未登录, 可能session已经失效' % check_user )
2018-01-07 01:54:36 +00:00
def submit_station ( self ) :
"""
提交车次
预定的请求参数 , 注意参数顺序
注意这里为了防止secretStr被urllib . parse过度编码 , 在这里进行一次解码
否则调用HttpTester类的post方法将会将secretStr编码成为无效码 , 造成提交预定请求失败
: param self :
: param secretStr : 提交车次加密
: return :
"""
submit_station_url = ' https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest '
data = [ ( ' secretStr ' , urllib . unquote ( self . secretStr ) ) , # 字符串加密
( ' train_date ' , self . time ( ) ) , # 出发时间
( ' back_train_date ' , self . time ( ) ) , # 返程时间
( ' tour_flag ' , ' dc ' ) , # 旅途类型
( ' purpose_codes ' , ' ADULT ' ) , # 成人票还是学生票
( ' query_from_station_name ' , self . from_station ) , # 起始车站
( ' query_to_station_name ' , self . to_station ) , # 终点车站
]
submitResult = json . loads ( myurllib2 . Post ( submit_station_url , data ) , encoding = ' utf-8 ' )
if ' data ' in submitResult and submitResult [ ' data ' ] :
if submitResult [ ' data ' ] == ' N ' :
print ( ' 出票成功 ' )
else :
print ( ' 出票失败 ' )
elif ' messages ' in submitResult and submitResult [ ' messages ' ] :
print ( submitResult [ ' messages ' ] [ 0 ] )
raise ticketIsExitsException ( " 检查到有未支付的订单,程序自动停止 " )
2017-05-17 12:32:37 +00:00
2017-05-21 08:48:34 +00:00
def getPassengerTicketStr ( self , set_type ) :
2017-05-17 12:32:37 +00:00
"""
获取getPassengerTicketStr 提交对应的代号码
: param str : 坐席
: return :
"""
passengerTicketStr = {
' 一等座 ' : ' M ' ,
' 特等座 ' : ' P ' ,
' 二等座 ' : ' O ' ,
' 商务座 ' : 9 ,
' 硬座 ' : 1 ,
' 无座 ' : 1 ,
' 软卧 ' : 4 ,
' 硬卧 ' : 3 ,
}
2017-05-21 08:48:34 +00:00
self . set_type = str ( passengerTicketStr [ set_type . replace ( ' ' , ' ' ) ] )
def ticket_type ( self ) :
""" 订单票的类型,目前只考虑成人票,此方法暂时搁置,做备案 """
ticket_type = { ' adult ' : " 1 " , ' child ' : " 2 " , ' student ' : " 3 " , ' disability ' : " 4 " }
return ticket_type
2017-05-17 12:32:37 +00:00
2018-01-08 02:22:20 +00:00
def getPassengerTicketStrListAndOldPassengerStr ( self ) :
"""
获取提交车次人内容格式
passengerTicketStr O , 0 , 1 , 文贤平 , 1 , 43052419950223 XXXX , 15618715583 , N_O , 0 , 1 , 梁敏 , 1 , 43052719920118 XXXX , , N
oldPassengerStr 文贤平 , 1 , 43052719920118 XXXX , 1 _梁敏 , 1 , 43052719920118 XXXX , 1 _
: return :
"""
passengerTicketStrList = [ ]
oldPassengerStr = [ ]
if len ( self . user_info ) is 1 :
passengerTicketStrList . append (
self . set_type + ' ,0, ' + self . user_info [ 0 ] [ ' passenger_id_type_code ' ] + " , " + self . user_info [ 0 ] [
" passenger_name " ] + " , " +
self . user_info [ 0 ] [ ' passenger_type ' ] + " , " + self . user_info [ 0 ] [ ' passenger_id_no ' ] + " , " +
self . user_info [ 0 ] [ ' mobile_no ' ] + ' ,N ' )
oldPassengerStr . append (
self . user_info [ 0 ] [ ' passenger_name ' ] + " , " + self . user_info [ 0 ] [ ' passenger_type ' ] + " , " +
self . user_info [ 0 ] [ ' passenger_id_no ' ] + " , " + self . user_info [ 0 ] [ ' passenger_type ' ] + ' _ ' )
else :
for i in range ( len ( self . user_info ) ) :
passengerTicketStrList . append (
' 0, ' + self . user_info [ i ] [ ' passenger_id_type_code ' ] + " , " + self . user_info [ i ] [
" passenger_name " ] + " , " + self . user_info [ i ] [ ' passenger_type ' ] + " , " + self . user_info [ i ] [
' passenger_id_no ' ] + " , " + self . user_info [ i ] [ ' mobile_no ' ] + ' ,N_ ' + self . set_type )
oldPassengerStr . append (
self . user_info [ i ] [ ' passenger_name ' ] + " , " + self . user_info [ i ] [ ' passenger_type ' ] + " , " +
self . user_info [ i ] [ ' passenger_id_no ' ] + " , " + self . user_info [ i ] [ ' passenger_type ' ] + ' _ ' )
return passengerTicketStrList , oldPassengerStr
2017-05-22 14:11:12 +00:00
def checkOrderInfo ( self ) :
2017-05-17 12:32:37 +00:00
"""
检查支付订单 , 需要提交REPEAT_SUBMIT_TOKEN
2017-05-21 08:48:34 +00:00
passengerTicketStr : 座位编号 , 0 , 票类型 , 乘客名 , 证件类型 , 证件号 , 手机号码 , 保存常用联系人 ( Y或N )
oldPassengersStr : 乘客名 , 证件类型 , 证件号 , 乘客类型
2017-05-17 12:32:37 +00:00
: return :
"""
2018-01-08 02:22:20 +00:00
passengerTicketStrList , oldPassengerStr = self . getPassengerTicketStrListAndOldPassengerStr ( )
2017-05-17 12:32:37 +00:00
checkOrderInfoUrl = ' https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo '
2018-01-08 02:22:20 +00:00
data = OrderedDict ( )
data [ ' cancel_flag ' ] = 2
data [ ' bed_level_order_num ' ] = " 000000000000000000000000000000 "
# 'passengerTicketStr': self.set_type+',0,'+self.user_info[0]['passenger_id_type_code']+","+self.user_info[0]["passenger_name"]+","+self.user_info[0]['passenger_type']+","+self.user_info[0]['passenger_id_no']+","+self.user_info[0]['mobile_no']+',N',
# 'oldPassengerStr': self.user_info[0]['passenger_name']+","+self.user_info[0]['passenger_type']+","+self.user_info[0]['passenger_id_no']+","+self.user_info[0]['passenger_type']+'_',
data [ ' passengerTicketStr ' ] = self . set_type + " , " + " , " . join ( passengerTicketStrList ) . rstrip ( " _ {0} " . format ( self . set_type ) )
data [ ' oldPassengerStr ' ] = " " . join ( oldPassengerStr )
data [ ' tour_flag ' ] = ' dc '
data [ ' whatsSelect ' ] = 1
data [ ' REPEAT_SUBMIT_TOKEN ' ] = self . token
2017-05-21 13:39:31 +00:00
checkOrderInfo = json . loads ( myurllib2 . Post ( checkOrderInfoUrl , data , ) )
2018-01-08 02:22:20 +00:00
if ' data ' in checkOrderInfo :
if checkOrderInfo [ ' data ' ] [ ' submitStatus ' ] is True :
print ( ' 车票提交通过,正在尝试排队 ' )
return True
else :
if " errMsg " in checkOrderInfo [ ' data ' ] and checkOrderInfo [ ' data ' ] [ " errMsg " ] :
print checkOrderInfo [ ' data ' ] [ " errMsg " ]
else :
print checkOrderInfo
2017-05-21 08:48:34 +00:00
elif ' messages ' in checkOrderInfo and checkOrderInfo [ ' messages ' ] :
2018-01-08 02:22:20 +00:00
print ( checkOrderInfo [ ' messages ' ] [ 0 ] )
2018-01-07 01:54:36 +00:00
print ( " 排队失败,重新刷票中 " )
2017-05-17 12:32:37 +00:00
2017-05-21 08:48:34 +00:00
def getQueueCount ( self ) :
"""
# 模拟查询当前的列车排队人数的方法
# 返回信息组成的提示字符串
: param token :
: return :
"""
2017-05-21 13:39:31 +00:00
old_train_date = self . get_ticketInfoForPassengerForm ( ) [ ' queryLeftTicketRequestDTO ' ] [ ' train_date ' ] + " 00:00:00 " # 模仿12306格式 Sun May 21 2017 00:00:00 GMT+0800 (中国标准时间)
m_time = time . mktime ( time . strptime ( old_train_date , " % Y % m %d % H: % M: % S " ) )
l_time = time . localtime ( m_time )
new_train_date = time . strftime ( " %a % b %d % Y % H: % M: % S " , l_time )
2017-05-21 08:48:34 +00:00
getQueueCountUrl = ' https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount '
data = {
2017-05-21 13:39:31 +00:00
' train_date ' : new_train_date ,
' train_no ' : self . get_ticketInfoForPassengerForm ( ) [ ' queryLeftTicketRequestDTO ' ] [ ' train_no ' ] ,
' stationTrainCode ' : self . get_ticketInfoForPassengerForm ( ) [ ' queryLeftTicketRequestDTO ' ] [ ' station_train_code ' ] ,
2017-05-21 08:48:34 +00:00
' seatType ' : self . set_type ,
2017-05-21 13:39:31 +00:00
' fromStationTelecode ' : self . get_ticketInfoForPassengerForm ( ) [ ' queryLeftTicketRequestDTO ' ] [ ' from_station ' ] ,
' toStationTelecode ' : self . get_ticketInfoForPassengerForm ( ) [ ' queryLeftTicketRequestDTO ' ] [ ' to_station ' ] ,
' leftTicket ' : self . get_ticketInfoForPassengerForm ( ) [ ' leftTicketStr ' ] ,
' purpose_codes ' : self . get_ticketInfoForPassengerForm ( ) [ ' purpose_codes ' ] ,
' train_location ' : self . get_ticketInfoForPassengerForm ( ) [ ' train_location ' ] ,
2017-05-22 14:11:12 +00:00
' REPEAT_SUBMIT_TOKEN ' : self . get_token ( ) ,
2017-05-17 12:32:37 +00:00
}
2017-05-21 08:48:34 +00:00
getQueueCountResult = json . loads ( myurllib2 . Post ( getQueueCountUrl , data ) )
2017-05-21 13:39:31 +00:00
if " status " in getQueueCountResult and getQueueCountResult [ " status " ] is True :
if " countT " in getQueueCountResult [ " data " ] :
2018-01-08 02:22:20 +00:00
ticket = getQueueCountResult [ " data " ] [ " ticket " ]
2017-05-21 13:39:31 +00:00
countT = getQueueCountResult [ " data " ] [ " countT " ]
if int ( countT ) is 0 :
2018-01-08 02:22:20 +00:00
print ( " 排队成功, 当前余票还剩余: " + ticket + " 张 " )
if int ( ticket ) < len ( self . user_info ) :
print ( " 当前余票数小于乘车人数,放弃订票 " )
else :
2018-01-08 07:28:10 +00:00
if self . checkQueueOrder ( ) :
return True
2017-05-21 13:39:31 +00:00
else :
2017-05-22 14:11:12 +00:00
print ( " 正在排队,当前排队人数: " + str ( countT ) + " 当前余票还剩余: " + getQueueCountResult [ " data " ] [ " ticket " ] + " 张 " )
2017-05-21 13:39:31 +00:00
else :
print ( " 排队发现未知错误 " )
elif " messages " in getQueueCountResult and getQueueCountResult [ " messages " ] :
2017-05-24 10:50:17 +00:00
print ( " 排队异常,错误信息: " + getQueueCountResult [ " messages " ] [ 0 ] )
2017-05-21 13:39:31 +00:00
else :
2017-05-24 10:50:17 +00:00
print ( str ( getQueueCountResult [ " validateMessages " ] ) )
2017-05-17 12:32:37 +00:00
2017-05-22 14:11:12 +00:00
def checkQueueOrder ( self ) :
"""
模拟提交订单是确认按钮 , 参数获取方法还是get_ticketInfoForPassengerForm 中获取
: return :
"""
2018-01-08 02:22:20 +00:00
passengerTicketStrList , oldPassengerStr = self . getPassengerTicketStrListAndOldPassengerStr ( )
2017-05-22 14:11:12 +00:00
checkQueueOrderUrl = " https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue "
data = {
2018-01-08 02:22:20 +00:00
" passengerTicketStr " : self . set_type + " , " + " , " . join ( passengerTicketStrList ) . rstrip ( " _ {0} " . format ( self . set_type ) ) ,
" oldPassengerStr " : " " . join ( oldPassengerStr ) ,
2017-05-22 14:11:12 +00:00
" purpose_codes " : self . get_ticketInfoForPassengerForm ( ) [ " purpose_codes " ] ,
" key_check_isChange " : self . get_ticketInfoForPassengerForm ( ) [ " key_check_isChange " ] ,
" leftTicketStr " : self . get_ticketInfoForPassengerForm ( ) [ " leftTicketStr " ] ,
" train_location " : self . get_ticketInfoForPassengerForm ( ) [ " train_location " ] ,
" seatDetailType " : " 000 " , # 开始需要选择座位, 但是目前12306不支持自动选择作为, 那这个参数为默认
" roomType " : " 00 " , # 好像是根据一个id来判断选中的, 两种 第一种是00, 第二种是10, 但是我在12306的页面没找到该id, 目前写死是00, 不知道会出什么错
" dwAll " : " N " ,
" REPEAT_SUBMIT_TOKEN " : self . get_token ( ) ,
}
checkQueueOrderResult = json . loads ( myurllib2 . Post ( checkQueueOrderUrl , data ) )
2017-05-23 15:09:51 +00:00
if " status " in checkQueueOrderResult and checkQueueOrderResult [ " status " ] :
c_data = checkQueueOrderResult [ " data " ] if " data " in checkQueueOrderResult else { }
2017-05-22 14:11:12 +00:00
if ' submitStatus ' in c_data and c_data [ ' submitStatus ' ] :
print ( " 出票成功! " )
2018-01-08 07:28:10 +00:00
if self . queryOrderWaitTime ( ) :
return True
2017-05-22 14:11:12 +00:00
else :
if ' errMsg ' in c_data and c_data [ ' errMsg ' ] :
print ( " 出票失败, " + c_data [ ' errMsg ' ] + " 请重新选择。 " )
else :
print ( c_data )
print ( ' 订票失败!很抱歉,请重试提交预订功能! ' )
elif " messages " in checkQueueOrderResult and checkQueueOrderResult [ " messages " ] :
print ( " 提交订单失败,错误信息: " + checkQueueOrderResult [ " messages " ] )
else :
2017-05-23 15:09:51 +00:00
print ( " 未知错误: " + str ( checkQueueOrderResult [ " validateMessages " ] ) )
2017-05-22 14:11:12 +00:00
def queryOrderWaitTime ( self ) :
"""
2018-01-07 01:54:36 +00:00
排队获取订单等待信息 , 每隔3秒请求一次 , 最高请求次数为20次 !
2017-05-22 14:11:12 +00:00
: return :
"""
queryOrderWaitTimeUrl = " https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime "
data = {
" random " : " 149545481029 " + str ( random . randint ( 1 , 9 ) ) ,
" tourFlag " : " dc " ,
" REPEAT_SUBMIT_TOKEN " : self . get_token ( ) ,
}
num = 1
while True :
num + = 1
if num > 20 :
2018-01-08 02:22:20 +00:00
print ( " 超出排队时间,自动放弃,正在重新刷票 " )
2017-05-22 14:11:12 +00:00
break
queryOrderWaitTimeResult = json . loads ( myurllib2 . Post ( queryOrderWaitTimeUrl , data ) )
2017-05-23 15:09:51 +00:00
if " status " in queryOrderWaitTimeResult and queryOrderWaitTimeResult [ " status " ] :
if " orderId " in queryOrderWaitTimeResult [ " data " ] and queryOrderWaitTimeResult [ " data " ] [ " orderId " ] != " null " :
2018-01-07 01:54:36 +00:00
self . initNoComplete ( )
orderId = self . queryMyOrderNoComplete ( )
if orderId :
print ( " 恭喜您订票成功,订单号为: {0} , 请立即打开浏览器登录12306, 访问‘ 未完成订单’ , 在30分钟内完成支付! " . format ( orderId ) )
2018-01-08 07:28:10 +00:00
return True
2018-01-07 01:54:36 +00:00
else :
print ( " 正在排队中,请耐心等待... " )
2017-05-23 15:09:51 +00:00
elif " msg " in queryOrderWaitTimeResult [ " data " ] and queryOrderWaitTimeResult [ " data " ] [ " msg " ] :
print ( " 订单提交失败: " + queryOrderWaitTimeResult [ " data " ] [ " msg " ] )
break
elif " messages " in queryOrderWaitTimeResult and queryOrderWaitTimeResult [ " messages " ] :
print ( " 订单提交失败: " + queryOrderWaitTimeResult [ " messages " ] )
2017-05-22 14:11:12 +00:00
break
2018-01-08 06:16:49 +00:00
else :
print ( " 订单提交中,请耐心等待 " )
time . sleep ( 3 )
2018-01-07 01:54:36 +00:00
def queryMyOrderNoComplete ( self ) :
"""
获取订单列表信息
: return :
"""
queryMyOrderNoCompleteUrl = " https://kyfw.12306.cn/otn/queryOrder/queryMyOrderNoComplete "
data = { " _json_att " : None }
queryMyOrderNoCompleteResult = json . loads ( myurllib2 . Post ( queryMyOrderNoCompleteUrl , data ) )
2018-01-08 07:28:10 +00:00
if " data " in queryMyOrderNoCompleteResult and queryMyOrderNoCompleteResult [ " data " ] and " orderDBList " in queryMyOrderNoCompleteResult [ " data " ] and queryMyOrderNoCompleteResult [ " data " ] [ " orderDBList " ] :
2018-01-07 01:54:36 +00:00
orderId = queryMyOrderNoCompleteResult [ " data " ] [ " orderDBList " ] [ 0 ] [ " sequence_no " ]
return orderId
2018-01-08 07:28:10 +00:00
elif " orderCacheDTO " in queryMyOrderNoCompleteResult [ " data " ] and queryMyOrderNoCompleteResult [ " data " ] [ " orderCacheDTO " ] :
if " message " in queryMyOrderNoCompleteResult [ " data " ] [ " orderCacheDTO " ] and queryMyOrderNoCompleteResult [ " data " ] [ " orderCacheDTO " ] [ " message " ] :
print ( queryMyOrderNoCompleteResult [ " data " ] [ " orderCacheDTO " ] [ " message " ] [ " message " ] )
raise ticketNumOutException ( queryMyOrderNoCompleteResult [ " data " ] [ " orderCacheDTO " ] [ " message " ] [ " message " ] )
2018-01-07 01:54:36 +00:00
else :
if " message " in queryMyOrderNoCompleteResult and queryMyOrderNoCompleteResult [ " message " ] :
print queryMyOrderNoCompleteResult [ " message " ]
return False
else :
return False
def initNoComplete ( self ) :
"""
获取订单前需要进入订单列表页 , 获取订单列表页session
: return :
"""
initNoCompleteUrl = " https://kyfw.12306.cn/otn/queryOrder/initNoComplete "
data = { " _json_att " : None }
myurllib2 . Post ( initNoCompleteUrl , data )
# def call_submit_ticket(self, function_name=None):
# """
# 订票失败回调方法, 默认执行submitOrderRequest()
# 此方法暂不使用
# :param function_name:
# :return:
# """
# if function_name:
# self.function_name()
# else:
# self.submitOrderRequest()
2017-05-22 14:11:12 +00:00
2017-05-17 12:32:37 +00:00
def main ( self ) :
2018-01-08 10:46:23 +00:00
from_station , to_station = self . station_table ( self . from_station , self . to_station )
2018-01-07 01:54:36 +00:00
num = 1
while 1 :
try :
print " 正在执行第 {0} 次查询 " . format ( num )
2018-01-07 06:19:32 +00:00
num + = 1
2018-01-07 01:54:36 +00:00
time . sleep ( self . select_refresh_interval )
if time . strftime ( ' % H: % M: % S ' , time . localtime ( time . time ( ) ) ) > " 23:00:00 " :
print " 12306休息时间, 本程序自动停止,明天早上七点运行 "
break
2018-01-08 10:46:23 +00:00
self . submitOrderRequest ( from_station , to_station )
2018-01-07 01:54:36 +00:00
except PassengerUserException as e :
print e . message
break
except ticketConfigException as e :
print e . message
break
except ticketIsExitsException as e :
print e . message
break
2018-01-08 07:28:10 +00:00
except ticketNumOutException as e :
print e . message
break
2018-01-08 06:16:49 +00:00
except ValueError as e :
if e . message == " No JSON object could be decoded " :
print ( " 12306接口无响应, 正在重试 " )
else :
print ( e . message )
2018-01-07 06:19:32 +00:00
except Exception as e :
print e . message
2018-01-07 01:54:36 +00:00
2017-05-17 12:32:37 +00:00
if __name__ == ' __main__ ' :
a = select ( ' 上海 ' , ' 北京 ' )
a . main ( )