# -*- coding=utf-8 -*- import json import datetime import random import re import threading import urllib import sys import time from collections import OrderedDict from config.ticketConf import _get_yaml from damatuCode.damatuWeb import DamatuApi from myException.PassengerUserException import PassengerUserException from myException.ticketConfigException import ticketConfigException from myException.ticketIsExitsException import ticketIsExitsException from myException.ticketNumOutException import ticketNumOutException from myUrllib import myurllib2 reload(sys) sys.setdefaultencoding('utf-8') class select: def __init__(self): 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.ticket_black_list_time = self.get_ticket_info() self.order_request_params = {} # 订单提交时的参数 self.ticketInfoForPassengerForm = {} # 初始化当前页面参数 self.current_seats = {} # 席别信息 self.token = "" self.set_type = "" self.user_info = "" self.secretStr = "" self.ticket_black_list = dict() 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"] ticke_peoples = ticket_info_config["set"]["ticke_peoples"] select_refresh_interval = ticket_info_config["select_refresh_interval"] station_trains = ticket_info_config["set"]["station_trains"] expect_refresh_interval = ticket_info_config["expect_refresh_interval"] ticket_black_list_time = ticket_info_config["ticket_black_list_time"] print "*"*20 print "当前配置:出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票自动提交:{4}\n乘车人:{5}\n刷新间隔:{6}\n候选购买车次:{7}\n未开始刷票间隔时间:{8}\n僵尸票关小黑屋时长:{9}\n".format\ ( from_station, to_station, station_date, ",".join(set_type), is_more_ticket, ",".join(ticke_peoples), select_refresh_interval, ",".join(station_trains), expect_refresh_interval, ticket_black_list_time, ) print "*"*20 return from_station, to_station, station_date, set_type, is_more_ticket, ticke_peoples, select_refresh_interval, station_trains, expect_refresh_interval, ticket_black_list_time 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 def conversion_int(self, str): return int(str) def station_seat(self, index): """ 获取车票对应坐席 :param seat_type: :return: """ seat = {'商务座': 32, '一等座': 31, '二等座': 30, '特等座': 25, '软卧': 23, '硬卧': 28, '硬座': 29, '无座': 26, } return seat[index] def station_table(self, from_station, to_station): """ 读取车站信息 :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] from_station = station_name[from_station.encode("utf8")] to_station = station_name[to_station.encode("utf8")] return from_station, to_station def time(self): """ 获取日期 :return: """ 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) 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: pass if re_orp: self.order_request_params = json.loads(re_orp[0].replace("'", '"')) else: pass def getPassengerDTOs(self): """ 获取乘客信息 :return: """ get_passengerDTOs = 'https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs' get_data = { '_json_att': None, 'REPEAT_SUBMIT_TOKEN': self.token } 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']: # return jsonData['data']['normal_passengers'] normal_passengers = jsonData['data']['normal_passengers'] _normal_passenger = [normal_passengers[i] for i in range(len(normal_passengers))if normal_passengers[i]["passenger_name"] in self.ticke_peoples] return _normal_passenger if _normal_passenger else normal_passengers[0] # 如果配置乘车人没有在账号,则默认返回第一个用户 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']: print(jsonData['messages'][0]) else: print("未查找到常用联系人") raise PassengerUserException("未查找到常用联系人,请先添加联系人在试试") def leftTicketLog(self, from_station, to_station): """ 模拟进入车次列表页 :param from_station: :param to_station: :return: """ 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: return True else: if "message" in leftTicketLog and leftTicketLog["message"]: print leftTicketLog["message"] elif "validateMessages" in leftTicketLog and leftTicketLog["validateMessages"]: print leftTicketLog["validateMessages"] def submitOrderRequest(self, from_station, to_station): """ 提交车次信息 车次对应字典 {32: '商务座 ', 31: '一等座 ', 30: '二等座 ', 25: '特等座 ', 23: '软卧 ', 28: '硬卧 ', 29: '硬座 ', 26: '无座 ' } 参照station_seat()方法 :return: """ 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) 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('|') if ticket_info[11] == "Y" and ticket_info[1].encode("utf8") == "预订": # 筛选未在开始时间内的车次 for j in range(len(self._station_seat)): is_ticket_pass = ticket_info[self.station_seat(self._station_seat[j].encode("utf8"))] # print self._station_seat[j] if is_ticket_pass != '' and is_ticket_pass != '无' and ticket_info[3] in self.station_trains and is_ticket_pass != '*': # 过滤有效目标车次 # tiket_values = [k for k in value['map'].values()] self.secretStr = ticket_info[0] train_no = ticket_info[3] print ('车次: ' + train_no + ' 始发车站: ' + self.from_station + ' 终点站: ' + self.to_station + ' ' + self._station_seat[j].encode("utf8") + ':' + ticket_info[self.station_seat(self._station_seat[j].encode("utf8"))]) if self.ticket_black_list.has_key(train_no) and (datetime.datetime.now() - self.ticket_black_list[train_no]).seconds/60 < int(self.ticket_black_list_time): print("该车次{} 正在被关小黑屋,跳过此车次".format(train_no)) break else: print ('正在尝试提交订票...') 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(train_no, self._station_seat[j].encode("utf8")): break else: pass else: pass time.sleep(self.expect_refresh_interval) else: print "车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket) def check_user(self): """ 检查用户是否达到订票条件 :return: """ check_user_url = 'https://kyfw.12306.cn/otn/login/checkUser' 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 ('尝试提交订单...') return True else: if check_user['messages']: print ('用户检查失败:%s,可能未登录,可能session已经失效' % check_user['messages'][0]) else: print ('用户检查失败: %s,可能未登录,可能session已经失效' % check_user) 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']: raise ticketIsExitsException(submitResult['messages'][0]) def getPassengerTicketStr(self, set_type): """ 获取getPassengerTicketStr 提交对应的代号码 :param str: 坐席 :return: """ passengerTicketStr = { '一等座': 'M', '特等座': 'P', '二等座': 'O', '商务座': 9, '硬座': 1, '无座': 1, '软卧': 4, '硬卧': 3, } 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 def getPassengerTicketStrListAndOldPassengerStr(self): """ 获取提交车次人内容格式 passengerTicketStr O,0,1,文贤平,1,43052419950223XXXX,15618715583,N_O,0,1,梁敏,1,43052719920118XXXX,,N oldPassengerStr 文贤平,1,43052719920118XXXX,1_梁敏,1,43052719920118XXXX,1_ :return: """ passengerTicketStrList = [] oldPassengerStr = [] if not self.user_info: raise PassengerUserException("联系人不在列表中,请查证后添加") if len(self.user_info) is 1: passengerTicketStrList.append( '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 def checkOrderInfo(self, train_no, set_type): """ 检查支付订单,需要提交REPEAT_SUBMIT_TOKEN passengerTicketStr : 座位编号,0,票类型,乘客名,证件类型,证件号,手机号码,保存常用联系人(Y或N) oldPassengersStr: 乘客名,证件类型,证件号,乘客类型 :return: """ passengerTicketStrList, oldPassengerStr = self.getPassengerTicketStrListAndOldPassengerStr() checkOrderInfoUrl = 'https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo' data = OrderedDict() data['cancel_flag'] = 2 data['bed_level_order_num'] = "000000000000000000000000000000" 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 checkOrderInfo = json.loads(myurllib2.Post(checkOrderInfoUrl, data, )) if 'data' in checkOrderInfo: if "ifShowPassCode" in checkOrderInfo["data"] and checkOrderInfo["data"]["ifShowPassCode"] == "Y": is_need_code = True if self.getQueueCount(train_no, set_type, is_need_code): return True if "ifShowPassCode" in checkOrderInfo["data"] and checkOrderInfo['data']['submitStatus'] is True: print ('车票提交通过,正在尝试排队') is_need_code = False if self.getQueueCount(train_no, set_type, is_need_code): return True else: if "errMsg" in checkOrderInfo['data'] and checkOrderInfo['data']["errMsg"]: print checkOrderInfo['data']["errMsg"] else: print checkOrderInfo elif 'messages' in checkOrderInfo and checkOrderInfo['messages']: print (checkOrderInfo['messages'][0]) def getQueueCount(self, train_no, set_type, is_need_code): """ # 模拟查询当前的列车排队人数的方法 # 返回信息组成的提示字符串 :param token: :return: """ 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) getQueueCountUrl = 'https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount' data = { 'train_date': new_train_date, 'train_no': self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['train_no'], 'stationTrainCode': self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['station_train_code'], 'seatType': self.set_type, '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'], 'REPEAT_SUBMIT_TOKEN': self.get_token(), } getQueueCountResult = json.loads(myurllib2.Post(getQueueCountUrl, data)) if "status" in getQueueCountResult and getQueueCountResult["status"] is True: if "countT" in getQueueCountResult["data"]: ticket = getQueueCountResult["data"]["ticket"] ticket_split = sum(map(self.conversion_int, ticket.split(","))) if ticket.find(",") != -1 else ticket # ticket_sum = sum([int(ticket_split[0]),int(ticket_split[1])]) # if set_type == "无座": # 修改无座和硬座的座位号提交是个字符串的问题 # ticket = ticket_split[1] # elif set_type == "硬座": # ticket = ticket_split[0] countT = getQueueCountResult["data"]["countT"] if int(countT) is 0: if int(ticket_split) < len(self.user_info): print("当前余票数小于乘车人数,放弃订票") else: print("排队成功, 当前余票还剩余: {0} 张".format(ticket_split)) if self.checkQueueOrder(is_need_code): return True else: print("当前排队人数:" + str(countT) + "当前余票还剩余:{0} 张,继续排队中".format(ticket_split)) else: print("排队发现未知错误{0},将此列车 {1}加入小黑屋".format(getQueueCountResult, train_no)) self.ticket_black_list[train_no] = datetime.datetime.now() elif "messages" in getQueueCountResult and getQueueCountResult["messages"]: print("排队异常,错误信息:{0}, 将此列车 {1}加入小黑屋".format(getQueueCountResult["messages"][0], train_no)) self.ticket_black_list[train_no] = datetime.datetime.now() else: if "validateMessages" in getQueueCountResult and getQueueCountResult["validateMessages"]: print(str(getQueueCountResult["validateMessages"])) self.ticket_black_list[train_no] = datetime.datetime.now() else: print("未知错误 {0}".format("".join(getQueueCountResult))) def checkQueueOrder(self, is_node_code=False): """ 模拟提交订单是确认按钮,参数获取方法还是get_ticketInfoForPassengerForm 中获取 :return: """ passengerTicketStrList, oldPassengerStr = self.getPassengerTicketStrListAndOldPassengerStr() checkQueueOrderUrl = "https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue" data = { "passengerTicketStr": self.set_type + "," + ",".join(passengerTicketStrList).rstrip("_{0}".format(self.set_type)), "oldPassengerStr": "".join(oldPassengerStr), "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(), } try: for i in range(3): if is_node_code: print("正在使用自动识别验证码功能") randurl = 'https://kyfw.12306.cn/otn/passcodeNew/checkRandCodeAnsyn' codeimg = 'https://kyfw.12306.cn/otn/passcodeNew/getPassCodeNew?module=passenger&rand=sjrand&%s' % random.random() result = myurllib2.get(codeimg) img_path = './tkcode' open(img_path, 'wb').write(result) randCode = DamatuApi(_get_yaml()["damatu"]["uesr"], _get_yaml()["damatu"]["pwd"], img_path).main() randData = { "randCode": randCode, "rand": "randp", "_json_att": None, "REPEAT_SUBMIT_TOKEN": self.get_token() } fresult = json.loads(myurllib2.Post(randurl, randData), encoding='utf8') # 校验验证码是否正确 checkcode = fresult['data']['msg'] if checkcode == 'FALSE': print ("验证码有误,第{}次尝试重试".format(i)) else: print("验证码通过,正在提交订单") data['randCode'] = randCode break else: print("不需要验证码") break checkQueueOrderResult = json.loads(myurllib2.Post(checkQueueOrderUrl, data)) if "status" in checkQueueOrderResult and checkQueueOrderResult["status"]: c_data = checkQueueOrderResult["data"] if "data" in checkQueueOrderResult else {} if 'submitStatus' in c_data and c_data['submitStatus'] is True: print("提交订单成功!") self.queryOrderWaitTime() else: if 'errMsg' in c_data and c_data['errMsg']: print("提交订单失败,{0}".format(c_data['errMsg'])) else: print(c_data) print('订票失败!很抱歉,请重试提交预订功能!') elif "messages" in checkQueueOrderResult and checkQueueOrderResult["messages"]: print("提交订单失败,错误信息: " + checkQueueOrderResult["messages"]) else: print("提交订单中,请耐心等待:" + str(checkQueueOrderResult["validateMessages"])) except ValueError: print("接口 {} 无响应".format(checkQueueOrderUrl)) def queryOrderWaitTime(self): """ 排队获取订单等待信息,每隔3秒请求一次,最高请求次数为20次! :return: """ # queryOrderWaitTimeUrl = "https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime" # data = { # "random": "{0}{1}".format(int(time.time()), random.randint(1, 9)), # "tourFlag": "dc", # "REPEAT_SUBMIT_TOKEN": self.get_token(), # } num = 1 while True: _random = int(round(time.time() * 1000)) num += 1 if num > 30: print("超出排队时间,自动放弃,正在重新刷票") break try: queryOrderWaitTimeUrl = "https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime?random={0}&tourFlag=dc&_json_att=&REPEAT_SUBMIT_TOKEN={1}".format(_random, self.get_token()) queryOrderWaitTimeResult = json.loads(myurllib2.get(queryOrderWaitTimeUrl)) except ValueError: queryOrderWaitTimeResult = {} if queryOrderWaitTimeResult: if "status" in queryOrderWaitTimeResult and queryOrderWaitTimeResult["status"]: if "orderId" in queryOrderWaitTimeResult["data"] and queryOrderWaitTimeResult["data"]["orderId"] is not None: raise ticketIsExitsException("恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!".format(queryOrderWaitTimeResult["data"]["orderId"])) elif "msg" in queryOrderWaitTimeResult["data"] and queryOrderWaitTimeResult["data"]["msg"]: print queryOrderWaitTimeResult["data"]["msg"] break elif "waitTime"in queryOrderWaitTimeResult["data"] and queryOrderWaitTimeResult["data"]["waitTime"]: print("排队等待时间预计还剩 {0} ms".format(0-queryOrderWaitTimeResult["data"]["waitTime"])) else: print ("正在等待中") elif "messages" in queryOrderWaitTimeResult and queryOrderWaitTimeResult["messages"]: print("排队等待失败: " + queryOrderWaitTimeResult["messages"]) else: print("第{}排队中,请耐心等待".format(num)) else: print("排队中") time.sleep(2) order_id = self.queryMyOrderNoComplete() # 尝试查看订单列表,如果有订单,则判断成功,不过一般可能性不大 if order_id: raise ticketIsExitsException("恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!".format(order_id)) else: print(ticketNumOutException("订单提交失败!,正在重新刷票")) def queryMyOrderNoComplete(self): """ 获取订单列表信息 :return: """ self.initNoComplete() queryMyOrderNoCompleteUrl = "https://kyfw.12306.cn/otn/queryOrder/queryMyOrderNoComplete" data = {"_json_att": None} try: queryMyOrderNoCompleteResult = json.loads(myurllib2.Post(queryMyOrderNoCompleteUrl, data)) except ValueError: queryMyOrderNoCompleteResult = {} if queryMyOrderNoCompleteResult: if "data" in queryMyOrderNoCompleteResult and queryMyOrderNoCompleteResult["data"] and "orderDBList" in queryMyOrderNoCompleteResult["data"] and queryMyOrderNoCompleteResult["data"]["orderDBList"]: orderId = queryMyOrderNoCompleteResult["data"]["orderDBList"][0]["sequence_no"] return orderId elif "data" in queryMyOrderNoCompleteResult and "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"]) else: if "message" in queryMyOrderNoCompleteResult and queryMyOrderNoCompleteResult["message"]: print queryMyOrderNoCompleteResult["message"] return False else: return False else: print("接口 {} 无响应".format(queryMyOrderNoCompleteUrl)) 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() def main(self): from_station, to_station = self.station_table(self.from_station, self.to_station) if self.leftTicketLog(from_station, to_station): num = 1 while 1: try: num += 1 time.sleep(self.select_refresh_interval) if time.strftime('%H:%M:%S', time.localtime(time.time())) > "23:00:00": print "12306休息时间,本程序自动停止,明天早上七点运行" break start_time = datetime.datetime.now() self.submitOrderRequest(from_station, to_station) print "正在第{0}次查询 乘车日期: {1} 车次{2} 查询无票 代理设置 无 总耗时{3}ms".format(num, self.station_date, ",".join(self.station_trains), (datetime.datetime.now()-start_time).microseconds/1000) except PassengerUserException as e: print e.message break except ticketConfigException as e: print e.message break except ticketIsExitsException as e: print e.message break except ticketNumOutException as e: print e.message break except ValueError as e: if e.message == "No JSON object could be decoded": print("12306接口无响应,正在重试") else: print(e.message) except KeyError as e: print(e.message) # class selectProducer(threading.Thread): # """刷票队列""" # def __init__(self, t_name, queue): # threading.Thread.__init__(self, name=t_name) # self.data = queue # print "{0} 正在运行".format(t_name) # # def run(self): # pass # # # class submitOrderConsumer(threading.Thread): # """订单队列""" # def __init__(self, t_name, queue): # threading.Thread.__init__(self, name=t_name) # self.data = queue # print "{0} 正在运行".format(t_name) # # def run(self): # pass if __name__ == '__main__': a = select('上海', '北京') a.main()