Esempio n. 1
0
class select:
    def __init__(self):
        self.from_station, self.to_station, self.station_dates, self._station_seat, self.is_more_ticket, self.ticke_peoples, self.select_refresh_interval, self.station_trains, self.ticket_black_list_time = self.get_ticket_info()
        self.is_aotu_code = _get_yaml()["is_aotu_code"]
        self.aotu_code_type = _get_yaml()["aotu_code_type"]
        self.order_request_params = {}  # 订单提交时的参数
        self.ticketInfoForPassengerForm = {}  # 初始化当前页面参数
        self.current_seats = {}  # 席别信息
        self.token = ""
        self.set_type = ""
        self.user_info = ""
        self.secretStr = ""
        self.ticket_black_list = dict()
        self.is_check_user = dict()
        self.httpClint = HTTPClient()
        self.confUrl = urlConf.urls
        self.login = GoLogin(self.httpClint, self.confUrl, self.is_aotu_code, self.aotu_code_type)

    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_dates = ticket_info_config["set"]["station_dates"]
        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"]
        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".format\
                                                                                      (
                                                                                      from_station,
                                                                                      to_station,
                                                                                      station_dates,
                                                                                      ",".join(set_type),
                                                                                      is_more_ticket,
                                                                                      ",".join(ticke_peoples),
                                                                                      select_refresh_interval,
                                                                                      ",".join(station_trains),
                                                                                      ticket_black_list_time,
            )
        print "*"*20
        return from_station, to_station, station_dates, set_type, is_more_ticket, ticke_peoples, select_refresh_interval, station_trains, 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 = self.confUrl["initdc_url"]["req_url"]
        initdc_result = self.httpClint.send(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=(\{.+\})?')
        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 = self.confUrl["get_passengerDTOs"]["req_url"]
        get_data = {
            '_json_att': None,
            'REPEAT_SUBMIT_TOKEN': self.token
        }
        jsonData = self.httpClint.send(get_passengerDTOs, get_data)
        if 'data' in jsonData and jsonData['data'] and 'normal_passengers' in jsonData['data'] and 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 submitOrderRequestFunc(self, from_station, to_station, station_date=None):
        select_url = self.confUrl["select_url"]["req_url"].format(
            station_date, from_station, to_station)
        station_ticket = self.httpClint.send(select_url, is_logger=False)
        return json.loads(station_ticket)

    def submitOrderRequestImplement(self, from_station, to_station,):
        """
        提交车次信息
        车次对应字典
        {32: '商务座 ',
            31: '一等座 ',
            30: '二等座 ',
            25: '特等座 ',
            23: '软卧 ',
            28: '硬卧 ',
            29: '硬座 ',
            26: '无座 '
        } 参照station_seat()方法
        :return:
        """
        station_tickets = [self.submitOrderRequestFunc(from_station, to_station, station_date) for station_date in self.station_dates]
        for station_ticket in station_tickets:
            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 ('正在尝试提交订票...')
                                        # self.submitOrderRequestFunc(from_station, to_station, self.time())
                                        self.submit_station()
                                        self.getPassengerTicketStr(self._station_seat[j].encode("utf8"))
                                        self.getRepeatSubmitToken()
                                        if not self.user_info:  # 修改每次都调用用户接口导致用户接口不能用
                                            self.user_info = self.getPassengerDTOs()
                                        if self.checkOrderInfo(train_no, self._station_seat[j].encode("utf8")):
                                                break
                                else:
                                    pass
                        else:
                            pass
                else:
                    print "车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket)

    def check_user(self):
        """
        检查用户是否达到订票条件
        :return:
        """
        check_user_url = self.confUrl["check_user_url"]["req_url"]
        data = {"_json_att": ""}
        check_user = self.httpClint.send(check_user_url, data)

        check_user_flag = check_user['data']['flag']
        if check_user_flag is True:
            self.is_check_user["user_time"] = datetime.datetime.now()
        else:
            if check_user['messages']:
                print ('用户检查失败:%s,可能未登录,可能session已经失效' % check_user['messages'][0])
                print ('正在尝试重新登录')
                self.call_login()
                self.is_check_user["user_time"] = datetime.datetime.now()
            else:
                print ('用户检查失败: %s,可能未登录,可能session已经失效' % check_user)
                print ('正在尝试重新登录')
                self.call_login()
                self.is_check_user["user_time"] = datetime.datetime.now()


    def submit_station(self):
        """
        提交车次
        预定的请求参数,注意参数顺序
        注意这里为了防止secretStr被urllib.parse过度编码,在这里进行一次解码
        否则调用HttpTester类的post方法将会将secretStr编码成为无效码,造成提交预定请求失败
        :param self:
        :param secretStr: 提交车次加密
        :return:
        """

        submit_station_url = self.confUrl["submit_station_url"]["req_url"]
        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 = self.httpClint.send(submit_station_url, data)
        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_type'] + "," + self.user_info[0][
                    "passenger_name"] + "," +
                self.user_info[0]['passenger_id_type_code'] + "," + 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_id_type_code'] + "," +
                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_type'] + "," + self.user_info[i][
                        "passenger_name"] + "," + self.user_info[i]['passenger_id_type_code'] + "," + 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_id_type_code'] + "," +
                    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 = self.confUrl["checkOrderInfoUrl"]["req_url"]
        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 = self.httpClint.send(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:
        """
        l_time = time.localtime(time.time())
        new_train_date = time.strftime("%a %b %d %Y", l_time)
        getQueueCountUrl = self.confUrl["getQueueCountUrl"]["req_url"]
        data = {
            'train_date': str(new_train_date) + " 00:00:00 GMT+0800 (中国标准时间)",
            '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 = self.httpClint.send(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
                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 = self.confUrl["checkQueueOrderUrl"]["req_url"]
        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",
            "whatsSelect": 1,
            "_json_at": "",
            "REPEAT_SUBMIT_TOKEN": self.get_token(),
        }
        try:
            for i in range(3):
                if is_node_code:
                    print("正在使用自动识别验证码功能")
                    checkRandCodeAnsyn = self.confUrl["checkRandCodeAnsyn"]["req_url"]
                    codeImgByOrder = self.confUrl["codeImgByOrder"]["req_url"]
                    randCode = self.login.readImg(codeImgByOrder)
                    randData = {
                        "randCode": randCode,
                        "rand": "randp",
                        "_json_att": None,
                        "REPEAT_SUBMIT_TOKEN": self.get_token()
                    }
                    fresult = self.httpClint.send(checkRandCodeAnsyn, randData)  # 校验验证码是否正确
                    checkcode = fresult['data']['msg']
                    if checkcode == 'TRUE':
                        print("验证码通过,正在提交订单")
                        data['randCode'] = randCode
                        break
                    else:
                        print ("验证码有误, 接口返回{0} 第{1}次尝试重试".format(fresult, i))
                else:
                    print("不需要验证码")
                    break
            checkQueueOrderResult = self.httpClint.send(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: 
        """
        num = 1
        while True:
            _random = int(round(time.time() * 1000))
            num += 1
            if num > 30:
                print("超出排队时间,自动放弃,正在重新刷票")
                order_id = self.queryMyOrderNoComplete()  # 排队失败,自动取消排队订单
                if order_id:
                    self.cancelNoCompleteMyOrder(order_id)
                break
            try:
                data = {"random": _random, "tourFlag": "dc"}
                queryOrderWaitTimeUrl = self.confUrl["queryOrderWaitTimeUrl"]["req_url"]
                queryOrderWaitTimeResult = self.httpClint.send(queryOrderWaitTimeUrl, data)
            except ValueError:
                queryOrderWaitTimeResult = {}
            if queryOrderWaitTimeResult:
                if "status" in queryOrderWaitTimeResult and queryOrderWaitTimeResult["status"]:
                    if "orderId" in queryOrderWaitTimeResult["data"] and queryOrderWaitTimeResult["data"]["orderId"] is not None:
                        sendEmail("恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!".format(queryOrderWaitTimeResult["data"]["orderId"]))
                        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+1))
            else:
                print("排队中")
            time.sleep(2)

        else:
            print(ticketNumOutException("订单提交失败!,正在重新刷票"))

    def queryMyOrderNoComplete(self):
        """
        获取订单列表信息
        :return:
        """
        self.initNoComplete()
        queryMyOrderNoCompleteUrl = self.confUrl["queryMyOrderNoCompleteUrl"]["req_url"]
        data = {"_json_att": ""}
        try:
            queryMyOrderNoCompleteResult = self.httpClint.send(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:
        """
        self.httpClint.set_cookies(acw_tc="AQAAAEnFJnekLwwAtGHjZZCr79B6dpXk", current_captcha_type="Z")
        initNoCompleteUrl = self.confUrl["initNoCompleteUrl"]["req_url"]
        data = {"_json_att": ""}
        self.httpClint.send(initNoCompleteUrl, data)

    def cancelNoCompleteMyOrder(self, sequence_no):
        """
        取消订单
        :param sequence_no: 订单编号
        :return:
        """
        cancelNoCompleteMyOrderUrl = self.confUrl["cancelNoCompleteMyOrder"]["req_url"]
        cancelNoCompleteMyOrderData = {
            "sequence_no": sequence_no,
            "cancel_flag": "cancel_order",
            "_json_att": ""
        }
        cancelNoCompleteMyOrderResult = self.httpClint.send(cancelNoCompleteMyOrderUrl, cancelNoCompleteMyOrderData)
        if "data" in cancelNoCompleteMyOrderResult and "existError" in cancelNoCompleteMyOrderResult["data"] and cancelNoCompleteMyOrderResult["data"]["existError"] == "N":
            print("排队超时,已为您自动取消订单,订单编号: {0}".format(sequence_no))
            time.sleep(2)
            return True
        else:
            print("排队超时,取消订单失败, 订单号{0}".format(sequence_no))

    # def call_submit_ticket(self, function_name=None):
    #     """
    #     订票失败回调方法,默认执行submitOrderRequest()
    #     此方法暂不使用
    #     :param function_name:
    #     :return:
    #     """
    #     if function_name:
    #         self.function_name()
    #     else:
    #         self.submitOrderRequest()

    def call_login(self, auth=False):
        """
        登录回调方法
        :return:
        """
        if auth:
            return self.login.auth()
        else:
            self.login.go_login()

    def main(self):
        self.call_login()
        from_station, to_station = self.station_table(self.from_station, self.to_station)
        self.check_user()
        time.sleep(0.1)
        num = 1
        while 1:
            try:
                num += 1
                if "user_time" in self.is_check_user and (datetime.datetime.now() - self.is_check_user["user_time"]).seconds/60 > 5:
                    # 5分钟检查一次用户是否登录
                    self.check_user()
                time.sleep(self.select_refresh_interval)
                if time.strftime('%H:%M:%S', time.localtime(time.time())) > "23:00:00":
                    print "12306休息时间,本程序自动停止,明天早上6点将自动运行"
                    time.sleep(60 * 60 * 7)
                    self.call_login()
                start_time = datetime.datetime.now()
                self.submitOrderRequestImplement(from_station, to_station)
                print "正在第{0}次查询  乘车日期: {1}  车次{2} 查询无票  代理设置 无  总耗时{3}ms".format(num, ",".join(self.station_dates), ",".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 UserPasswordException 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)
            except TypeError as e:
                print("12306接口无响应,正在重试 {0}".format(e.message))
            except socket.error as e:
                print(e.message)
Esempio n. 2
0
class select:
    """
    快速提交车票通道
    """
    def __init__(self):
        self.cdn_list = open_cdn_file("filter_cdn_list")
        self.get_ticket_info()
        self._station_seat = [seat_conf[x] for x in TickerConfig.SET_TYPE]
        self.auto_code_type = TickerConfig.AUTO_CODE_TYPE
        self.httpClint = HTTPClient(TickerConfig.IS_PROXY, self.cdn_list)
        self.httpClint.cdn = self.cdn_list[random.randint(0, 4)]
        self.urls = urlConf.urls
        self.login = GoLogin(self, TickerConfig.IS_AUTO_CODE,
                             self.auto_code_type)
        self.cookies = ""
        self.queryUrl = "leftTicket/queryO"
        self.passengerTicketStrList = ""
        self.passengerTicketStrByAfterLate = ""
        self.oldPassengerStr = ""
        self.set_type = ""
        self.flag = True

    @staticmethod
    def get_ticket_info():
        """
        获取配置信息
        :return:
        """

        print(u"*" * 50)
        print(f"检查当前版本为: {TickerConfig.RE_VERSION}")
        version = sys.version.split(" ")[0]
        print(u"检查当前python版本为:{},目前版本只支持3.6以上".format(version))
        if version < "3.6.0":
            raise Exception
        print(u"12306刷票小助手,最后更新于2019.09.18,请勿作为商业用途,交流群号:"
              u" 1群:286271084(已满)\n"
              u" 2群:649992274(已满)\n"
              u" 3群:632501142(已满)\n"
              u" 4群: 606340519(已满)\n"
              u" 5群: 948526733(已满)\n"
              u" 7群: 660689659(已满)\n"
              u" 8群: 620629239(已满)\n"
              u" 6群: 608792930(未满)\n"
              u" 9群: 693035807(未满)\n")
        print(
            f"当前配置:\n出发站:{TickerConfig.FROM_STATION}\n到达站:{TickerConfig.TO_STATION}\n车次: {','.join(TickerConfig.STATION_TRAINS) or '所有车次'}\n乘车日期:{','.join(TickerConfig.STATION_DATES)}\n坐席:{','.join(TickerConfig.SET_TYPE)}\n是否有票优先提交:{TickerConfig.IS_MORE_TICKET}\n乘车人:{TickerConfig.TICKET_PEOPLES}\n" \
            f"刷新间隔: 随机(1-3S)\n僵尸票关小黑屋时长: {TickerConfig.TICKET_BLACK_LIST_TIME}\n下单接口: {TickerConfig.ORDER_TYPE}\n下单模式: {TickerConfig.ORDER_MODEL}\n预售踩点时间:{TickerConfig.OPEN_TIME}")
        print(u"*" * 50)

    def station_table(self, from_station, to_station):
        """
        读取车站信息
        :param station:
        :return:
        """
        path = os.path.join(os.path.dirname(__file__), '../station_name.txt')
        try:
            with open(path, encoding="utf-8") as result:
                info = result.read().split('=')[1].strip("'").split('@')
        except Exception:
            with open(path) as result:
                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]
        try:
            from_station = station_name[from_station.encode("utf8")]
            to_station = station_name[to_station.encode("utf8")]
        except KeyError:
            from_station = station_name[from_station]
            to_station = station_name[to_station]
        return from_station, to_station

    def call_login(self, auth=False):
        """
        登录回调方法
        :return:
        """
        if auth:
            return self.login.auth()
        else:
            configCommon.checkSleepTime(self)  # 防止网上启动晚上到点休眠
            self.login.go_login()

    def main(self):
        l = liftTicketInit(self)
        l.reqLiftTicketInit()
        getDrvicesID(self)
        self.call_login()
        check_user = checkUser(self)
        t = threading.Thread(target=check_user.sendCheckUser)
        t.setDaemon(True)
        t.start()
        from_station, to_station = self.station_table(
            TickerConfig.FROM_STATION, TickerConfig.TO_STATION)
        num = 0
        s = getPassengerDTOs(selectObj=self,
                             ticket_peoples=TickerConfig.TICKET_PEOPLES)
        passenger = s.sendGetPassengerDTOs()
        wrapcache.set("user_info", passenger, timeout=9999999)

        now = datetime.datetime.now()
        if TickerConfig.ORDER_MODEL is 1:
            print(
                f"预售还未开始,阻塞中,预售时间为{TickerConfig.OPEN_TIME}, 当前时间为: {now.strftime('%H:%M:%S')}"
            )
            sleep_time_s = 0.1
            sleep_time_t = 0.3
            # 测试了一下有微妙级的误差,应该不影响,测试结果:2019-01-02 22:30:00.004555,预售还是会受到前一次刷新的时间影响,暂时没想到好的解决方案
            while now.strftime("%H:%M:%S") < TickerConfig.OPEN_TIME:
                now = datetime.datetime.now()
                time.sleep(0.0001)
            print(f"预售开始,开启时间为: {now.strftime('%H:%M:%S')}")
        else:
            sleep_time_s = TickerConfig.MIN_TIME
            sleep_time_t = TickerConfig.MAX_TIME

        while 1:
            try:
                num += 1
                now = datetime.datetime.now()  # 感谢群里大佬提供整点代码
                configCommon.checkSleepTime(self)  # 晚上到点休眠
                q = query(
                    selectObj=self,
                    from_station=from_station,
                    to_station=to_station,
                    from_station_h=TickerConfig.FROM_STATION,
                    to_station_h=TickerConfig.TO_STATION,
                    _station_seat=self._station_seat,
                    station_trains=TickerConfig.STATION_TRAINS,
                    station_dates=TickerConfig.STATION_DATES,
                    ticke_peoples_num=len(TickerConfig.TICKET_PEOPLES),
                )
                queryResult = q.sendQuery()
                # 查询接口
                if queryResult.get("status"):
                    train_no = queryResult.get("train_no", "")
                    train_date = queryResult.get("train_date", "")
                    stationTrainCode = queryResult.get("stationTrainCode", "")
                    secretStr = queryResult.get("secretStr", "")
                    secretList = queryResult.get("secretList", "")
                    seat = queryResult.get("seat", "")
                    leftTicket = queryResult.get("leftTicket", "")
                    query_from_station_name = queryResult.get(
                        "query_from_station_name", "")
                    query_to_station_name = queryResult.get(
                        "query_to_station_name", "")
                    is_more_ticket_num = queryResult.get(
                        "is_more_ticket_num", len(TickerConfig.TICKET_PEOPLES))
                    if wrapcache.get(train_no):
                        print(ticket.QUEUE_WARNING_MSG.format(train_no))
                    else:
                        # 获取联系人
                        s = getPassengerDTOs(
                            selectObj=self,
                            ticket_peoples=TickerConfig.TICKET_PEOPLES,
                            set_type=""
                            if isinstance(seat, list) else seat_conf_2[seat],
                            # 候补订单需要设置多个坐席
                            is_more_ticket_num=is_more_ticket_num)
                        getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr(
                            secretStr, secretList)
                        if getPassengerDTOsResult.get("status", False):
                            self.passengerTicketStrList = getPassengerDTOsResult.get(
                                "passengerTicketStrList", "")
                            self.passengerTicketStrByAfterLate = getPassengerDTOsResult.get(
                                "passengerTicketStrByAfterLate", "")
                            self.oldPassengerStr = getPassengerDTOsResult.get(
                                "oldPassengerStr", "")
                            self.set_type = getPassengerDTOsResult.get(
                                "set_type", "")
                        # 提交订单
                        # 订单分为两种,一种为抢单,一种为候补订单
                        if secretStr:  # 正常下单
                            if TickerConfig.ORDER_TYPE == 1:  # 快速下单
                                a = autoSubmitOrderRequest(
                                    selectObj=self,
                                    secretStr=secretStr,
                                    train_date=train_date,
                                    passengerTicketStr=self.
                                    passengerTicketStrList,
                                    oldPassengerStr=self.oldPassengerStr,
                                    train_no=train_no,
                                    stationTrainCode=stationTrainCode,
                                    leftTicket=leftTicket,
                                    set_type=self.set_type,
                                    query_from_station_name=
                                    query_from_station_name,
                                    query_to_station_name=query_to_station_name,
                                )
                                a.sendAutoSubmitOrderRequest()
                            elif TickerConfig.ORDER_TYPE == 2:  # 普通下单
                                sor = submitOrderRequest(
                                    self, secretStr, from_station, to_station,
                                    train_no, self.set_type,
                                    self.passengerTicketStrList,
                                    self.oldPassengerStr, train_date,
                                    TickerConfig.TICKET_PEOPLES)
                                sor.sendSubmitOrderRequest()
                        elif secretList:  # 候补订单
                            c = chechFace(self, secretList, train_no)
                            c.sendChechFace()
                else:
                    random_time = round(
                        random.uniform(sleep_time_s, sleep_time_t), 2)
                    nateMsg = ' 无候补机会' if TickerConfig.ORDER_TYPE == 2 else ""
                    print(
                        f"正在第{num}次查询 停留时间:{random_time} 乘车日期: {','.join(TickerConfig.STATION_DATES)} 车次:{','.join(TickerConfig.STATION_TRAINS) or '所有车次'} 下单无票{nateMsg} 耗时:{(datetime.datetime.now() - now).microseconds / 1000} {queryResult.get('cdn')}"
                    )
                    time.sleep(random_time)
            except PassengerUserException as e:
                print(e)
                break
            except ticketConfigException as e:
                print(e)
                break
            except ticketIsExitsException as e:
                print(e)
                break
            except ticketNumOutException as e:
                print(e)
                break
            except UserPasswordException as e:
                print(e)
                break
            except ValueError as e:
                if e == "No JSON object could be decoded":
                    print(u"12306接口无响应,正在重试")
                else:
                    print(e)
            except KeyError as e:
                print(e)
            except TypeError as e:
                print(u"12306接口无响应,正在重试 {0}".format(e))
            except socket.error as e:
                print(e)
Esempio n. 3
0
class payorder:
    """
    快速提交车票通道
    """
    def __init__(self):
        self.from_station, self.to_station, self.station_dates, self._station_seat, self.is_more_ticket, \
        self.ticke_peoples, self.station_trains, self.ticket_black_list_time, \
        self.order_type, self.is_by_time, self.train_types, self.departure_time, \
        self.arrival_time, self.take_time, self.order_model, self.open_time, self.is_proxy = self.get_ticket_info()
        self.is_auto_code = _get_yaml()["is_auto_code"]
        self.auto_code_type = _get_yaml()["auto_code_type"]
        self.is_cdn = _get_yaml()["is_cdn"]
        self.httpClint = HTTPClient(self.is_proxy)
        self.urls = urlConf.urls
        self.login = GoLogin(self, self.is_auto_code, self.auto_code_type)
        self.cdn_list = []
        self.queryUrl = "leftTicket/queryZ"
        self.passengerTicketStrList = ""
        self.oldPassengerStr = ""
        self.set_type = ""

    def get_ticket_info(self):
        """
        获取配置信息
        :return:
        """
        ticket_info_config = _get_yaml()
        from_station = ticket_info_config["set"]["from_station"]
        to_station = ticket_info_config["set"]["to_station"]
        station_dates = ticket_info_config["set"]["station_dates"]
        set_names = ticket_info_config["set"]["set_type"]
        set_type = [
            seat_conf[x.encode("utf-8")]
            for x in ticket_info_config["set"]["set_type"]
        ]
        is_more_ticket = ticket_info_config["set"]["is_more_ticket"]
        ticke_peoples = ticket_info_config["set"]["ticke_peoples"]
        station_trains = ticket_info_config["set"]["station_trains"]
        ticket_black_list_time = ticket_info_config["ticket_black_list_time"]
        order_type = ticket_info_config["order_type"]

        # by time
        is_by_time = ticket_info_config["set"]["is_by_time"]
        train_types = ticket_info_config["set"]["train_types"]
        departure_time = time_to_minutes(
            ticket_info_config["set"]["departure_time"])
        arrival_time = time_to_minutes(
            ticket_info_config["set"]["arrival_time"])
        take_time = time_to_minutes(ticket_info_config["set"]["take_time"])

        # 下单模式
        order_model = ticket_info_config["order_model"]
        open_time = ticket_info_config["open_time"]

        # 代理模式
        is_proxy = ticket_info_config["is_proxy"]

        print(u"*" * 50)
        print(u"检查当前python版本为:{},目前版本只支持2.7.10-2.7.15".format(
            sys.version.split(" ")[0]))
        print(
            u"12306刷票小助手,最后更新于2019.01.08,请勿作为商业用途,交流群号:286271084(已满), 2群:649992274(已满),请加3群(未满), 群号:632501142、4群(未满), 群号:606340519"
        )
        if is_by_time:
            method_notie = u"购票方式:根据时间区间购票\n可接受最早出发时间:{0}\n可接受最晚抵达时间:{1}\n可接受最长旅途时间:{2}\n可接受列车类型:{3}\n" \
                .format(minutes_to_time(departure_time), minutes_to_time(arrival_time), minutes_to_time(take_time),
                        " , ".join(train_types))
        else:
            method_notie = u"购票方式:根据候选车次购买\n候选购买车次:{0}".format(
                ",".join(station_trains))
        print (u"当前配置:\n出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票优先提交:{4}\n乘车人:{5}\n" \
               u"刷新间隔: 随机(1-3S)\n{6}\n僵尸票关小黑屋时长: {7}\n下单接口: {8}\n下单模式: {9}\n预售踩点时间:{10} ".format \
                (
                from_station,
                to_station,
                station_dates,
                ",".join(set_names),
                is_more_ticket,
                ",".join(ticke_peoples),
                method_notie,
                ticket_black_list_time,
                order_type,
                order_model,
                open_time,
            ))
        print(u"*" * 50)
        return from_station, to_station, station_dates, set_type, is_more_ticket, ticke_peoples, station_trains, \
               ticket_black_list_time, order_type, is_by_time, train_types, departure_time, arrival_time, take_time, \
               order_model, open_time, is_proxy

    def station_table(self, from_station, to_station):
        """
        读取车站信息
        :param station:
        :return:
        """
        path = os.path.join(os.path.dirname(__file__), '../station_name.txt')
        result = open(path)
        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 call_login(self, auth=False):
        """
        登录回调方法
        :return:
        """
        if auth:
            return self.login.auth()
        else:
            self.login.go_login()

    def cdn_req(self, cdn):
        for i in range(len(cdn) - 1):
            http = HTTPClient(0)
            urls = self.urls["loginInitCdn"]
            http._cdn = cdn[i].replace("\n", "")
            start_time = datetime.datetime.now()
            rep = http.send(urls)
            if rep and "message" not in rep and (datetime.datetime.now(
            ) - start_time).microseconds / 1000 < 500:
                if cdn[i].replace("\n",
                                  "") not in self.cdn_list:  # 如果有重复的cdn,则放弃加入
                    # print(u"加入cdn {0}".format(cdn[i].replace("\n", "")))
                    self.cdn_list.append(cdn[i].replace("\n", ""))
        print(u"所有cdn解析完成...")

    def cdn_certification(self):
        """
        cdn 认证
        :return:
        """
        if self.is_cdn == 1:
            CDN = CDNProxy()
            all_cdn = CDN.open_cdn_file()
            if all_cdn:
                # print(u"由于12306网站策略调整,cdn功能暂时关闭。")
                print(u"开启cdn查询")
                print(u"本次待筛选cdn总数为{}, 筛选时间大约为5-10min".format(len(all_cdn)))
                t = threading.Thread(target=self.cdn_req, args=(all_cdn, ))
                t.setDaemon(True)
                # t2 = threading.Thread(target=self.set_cdn, args=())
                t.start()
                # t2.start()
            else:
                raise ticketConfigException(u"cdn列表为空,请先加载cdn")

    def main(self):
        autoSynchroTime()  # 同步时间
        self.cdn_certification()
        l = liftTicketInit(self)
        l.reqLiftTicketInit()
        self.call_login()
        #检查用户登录, 检查间隔为2分钟
        check_user = checkUser(self)
        t = threading.Thread(target=check_user.sendCheckUser)
        t.setDaemon(True)
        t.start()
        from_station, to_station = self.station_table(self.from_station,
                                                      self.to_station)

        print("********OKOKOKOKOKO******")
        driver.get("https://kyfw.12306.cn/otn/view/train_order.html")
        #获取页面名为wraper的id标签的文本内容
        data = driver.page_source
        print data
        driver.quit()
        #打印数据内容
        print(data)

        num = 0
        while 1:
            try:
                num += 1
                now = datetime.datetime.now()  # 感谢群里大佬提供整点代码
                configCommon.checkSleepTime(self)  # 晚上到点休眠
                if self.order_model is 1:
                    sleep_time_s = 0.5
                    sleep_time_t = 0.6
                    # 测试了一下有微妙级的误差,应该不影响,测试结果:2019-01-02 22:30:00.004555,预售还是会受到前一次刷新的时间影响,暂时没想到好的解决方案
                    while not now.strftime("%H:%M:%S") == self.open_time:
                        now = datetime.datetime.now()
                        if now.strftime("%H:%M:%S") > self.open_time:
                            break
                        time.sleep(0.0001)
                else:
                    sleep_time_s = 0.5
                    sleep_time_t = 3
                # pay = payOrder(self)
                # pay.reqPayorder()

            except PassengerUserException as e:
                print(e)
                break
            except ticketConfigException as e:
                print(e)
                break
            except ticketIsExitsException as e:
                print(e)
                break
            except ticketNumOutException as e:
                print(e)
                break
            except UserPasswordException as e:
                print(e)
                break
            except ValueError as e:
                if e == "No JSON object could be decoded":
                    print(u"12306接口无响应,正在重试")
                else:
                    print(e)
            except KeyError as e:
                print(e)
            except TypeError as e:
                print(u"12306接口无响应,正在重试 {0}".format(e))
            except socket.error as e:
                print(e)
Esempio n. 4
0
class select:
    """
    快速提交车票通道
    """
    def __init__(self):
        self.from_station, self.to_station, self.station_dates, self._station_seat, self.is_more_ticket, \
        self.ticke_peoples, self.station_trains, self.ticket_black_list_time, \
        self.order_type, self.is_by_time, self.train_types, self.departure_time, \
        self.arrival_time, self.take_time, self.order_model, self.open_time, self.is_proxy = self.get_ticket_info()
        self.is_auto_code = _get_yaml()["is_auto_code"]
        self.auto_code_type = _get_yaml()["auto_code_type"]
        self.is_cdn = _get_yaml()["is_cdn"]
        self.httpClint = HTTPClient(self.is_proxy)
        self.urls = urlConf.urls
        self.login = GoLogin(self, self.is_auto_code, self.auto_code_type)
        self.cdn_list = []
        self.queryUrl = "leftTicket/queryZ"
        self.passengerTicketStrList = ""
        self.oldPassengerStr = ""
        self.set_type = ""

    def get_ticket_info(self):
        """
        获取配置信息
        :return:
        """
        ticket_info_config = _get_yaml()
        from_station = ticket_info_config["set"]["from_station"]
        to_station = ticket_info_config["set"]["to_station"]
        station_dates = ticket_info_config["set"]["station_dates"]
        set_names = ticket_info_config["set"]["set_type"]
        try:
            set_type = [
                seat_conf[x.encode("utf-8")]
                for x in ticket_info_config["set"]["set_type"]
            ]
        except KeyError:
            set_type = [
                seat_conf[x] for x in ticket_info_config["set"]["set_type"]
            ]
        is_more_ticket = ticket_info_config["set"]["is_more_ticket"]
        ticke_peoples = ticket_info_config["set"]["ticke_peoples"]
        station_trains = ticket_info_config["set"]["station_trains"]
        ticket_black_list_time = ticket_info_config["ticket_black_list_time"]
        order_type = ticket_info_config["order_type"]

        # by time
        is_by_time = ticket_info_config["set"]["is_by_time"]
        train_types = ticket_info_config["set"]["train_types"]
        departure_time = time_to_minutes(
            ticket_info_config["set"]["departure_time"])
        arrival_time = time_to_minutes(
            ticket_info_config["set"]["arrival_time"])
        take_time = time_to_minutes(ticket_info_config["set"]["take_time"])

        # 下单模式
        order_model = ticket_info_config["order_model"]
        open_time = ticket_info_config["open_time"]

        # 代理模式
        is_proxy = ticket_info_config["is_proxy"]

        print(u"*" * 50)
        print(u"检查当前python版本为:{},目前版本只支持2.7.10-2.7.15".format(
            sys.version.split(" ")[0]))
        print(u"12306刷票小助手,最后更新于2019.01.08,请勿作为商业用途,交流群号:286271084(已满),"
              u" 2群:649992274(已满)\n"
              u" 3群:632501142(已满)\n"
              u" 4群: 606340519(已满)\n"
              u" 5群: 948526733(已满)\n"
              u" 6群: 444101020(未满)\n"
              u" 7群: 660689659(未满)\n")
        if is_by_time:
            method_notie = u"购票方式:根据时间区间购票\n可接受最早出发时间:{0}\n可接受最晚抵达时间:{1}\n可接受最长旅途时间:{2}\n可接受列车类型:{3}\n" \
                .format(minutes_to_time(departure_time), minutes_to_time(arrival_time), minutes_to_time(take_time),
                        " , ".join(train_types))
        else:
            method_notie = u"购票方式:根据候选车次购买\n候选购买车次:{0}".format(
                ",".join(station_trains))
        print (u"当前配置:\n出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票优先提交:{4}\n乘车人:{5}\n" \
               u"刷新间隔: 随机(1-3S)\n{6}\n僵尸票关小黑屋时长: {7}\n下单接口: {8}\n下单模式: {9}\n预售踩点时间:{10} ".format \
                (
                from_station,
                to_station,
                station_dates,
                ",".join(set_names),
                is_more_ticket,
                ",".join(ticke_peoples),
                method_notie,
                ticket_black_list_time,
                order_type,
                order_model,
                open_time,
            ))
        print(u"*" * 50)
        return from_station, to_station, station_dates, set_type, is_more_ticket, ticke_peoples, station_trains, \
               ticket_black_list_time, order_type, is_by_time, train_types, departure_time, arrival_time, take_time, \
               order_model, open_time, is_proxy

    def station_table(self, from_station, to_station):
        """
        读取车站信息
        :param station:
        :return:
        """
        path = os.path.join(os.path.dirname(__file__), '../station_name.txt')
        try:
            with open(path, encoding="utf-8") as result:
                info = result.read().split('=')[1].strip("'").split('@')
        except Exception:
            with open(path) as result:
                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]
        try:
            from_station = station_name[from_station.encode("utf8")]
            to_station = station_name[to_station.encode("utf8")]
        except KeyError:
            from_station = station_name[from_station]
            to_station = station_name[to_station]
        return from_station, to_station

    def call_login(self, auth=False):
        """
        登录回调方法
        :return:
        """
        if auth:
            return self.login.auth()
        else:
            configCommon.checkSleepTime(self)  # 防止网上启动晚上到点休眠
            self.login.go_login()

    def cdn_req(self, cdn):
        for i in range(len(cdn) - 1):
            http = HTTPClient(0)
            urls = self.urls["loginInitCdn"]
            http._cdn = cdn[i].replace("\n", "")
            start_time = datetime.datetime.now()
            rep = http.send(urls)
            if rep and "message" not in rep and (datetime.datetime.now(
            ) - start_time).microseconds / 1000 < 500:
                if cdn[i].replace("\n",
                                  "") not in self.cdn_list:  # 如果有重复的cdn,则放弃加入
                    # print(u"加入cdn {0}".format(cdn[i].replace("\n", "")))
                    self.cdn_list.append(cdn[i].replace("\n", ""))
        print(u"所有cdn解析完成...")

    def cdn_certification(self):
        """
        cdn 认证
        :return:
        """
        if self.is_cdn == 1:
            CDN = CDNProxy()
            all_cdn = CDN.open_cdn_file()
            if all_cdn:
                # print(u"由于12306网站策略调整,cdn功能暂时关闭。")
                print(u"开启cdn查询")
                print(u"本次待筛选cdn总数为{}, 筛选时间大约为5-10min".format(len(all_cdn)))
                t = threading.Thread(target=self.cdn_req, args=(all_cdn, ))
                t.setDaemon(True)
                # t2 = threading.Thread(target=self.set_cdn, args=())
                t.start()
                # t2.start()
            else:
                raise ticketConfigException(u"cdn列表为空,请先加载cdn")

    def main(self):
        # autoSynchroTime()  # 同步时间
        self.cdn_certification()
        l = liftTicketInit(self)
        l.reqLiftTicketInit()
        self.call_login()
        check_user = checkUser(self)
        t = threading.Thread(target=check_user.sendCheckUser)
        t.setDaemon(True)
        t.start()
        from_station, to_station = self.station_table(self.from_station,
                                                      self.to_station)
        num = 0
        s = getPassengerDTOs(session=self, ticket_peoples=self.ticke_peoples)
        passenger = s.sendGetPassengerDTOs()
        wrapcache.set("user_info", passenger, timeout=9999999)
        while 1:
            try:
                num += 1
                now = datetime.datetime.now()  # 感谢群里大佬提供整点代码
                configCommon.checkSleepTime(self)  # 晚上到点休眠
                if self.order_model is 1:
                    sleep_time_s = 0.5
                    sleep_time_t = 0.6
                    # 测试了一下有微妙级的误差,应该不影响,测试结果:2019-01-02 22:30:00.004555,预售还是会受到前一次刷新的时间影响,暂时没想到好的解决方案
                    while not now.strftime("%H:%M:%S") == self.open_time:
                        now = datetime.datetime.now()
                        if now.strftime("%H:%M:%S") > self.open_time:
                            break
                        time.sleep(0.0001)
                else:
                    sleep_time_s = 0.5
                    sleep_time_t = 3
                q = query(
                    session=self,
                    from_station=from_station,
                    to_station=to_station,
                    from_station_h=self.from_station,
                    to_station_h=self.to_station,
                    _station_seat=self._station_seat,
                    station_trains=self.station_trains,
                    station_dates=self.station_dates,
                    ticke_peoples_num=len(self.ticke_peoples),
                )
                queryResult = q.sendQuery()
                # 查询接口
                if queryResult.get("status", False):
                    train_no = queryResult.get("train_no", "")
                    train_date = queryResult.get("train_date", "")
                    stationTrainCode = queryResult.get("stationTrainCode", "")
                    secretStr = queryResult.get("secretStr", "")
                    seat = queryResult.get("seat", "")
                    leftTicket = queryResult.get("leftTicket", "")
                    query_from_station_name = queryResult.get(
                        "query_from_station_name", "")
                    query_to_station_name = queryResult.get(
                        "query_to_station_name", "")
                    is_more_ticket_num = queryResult.get(
                        "is_more_ticket_num", len(self.ticke_peoples))
                    if wrapcache.get(train_no):
                        print(ticket.QUEUE_WARNING_MSG.format(train_no))
                    else:
                        # 获取联系人
                        s = getPassengerDTOs(
                            session=self,
                            ticket_peoples=self.ticke_peoples,
                            set_type=seat_conf_2[seat],
                            is_more_ticket_num=is_more_ticket_num)
                        getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr(
                        )
                        if getPassengerDTOsResult.get("status", False):
                            self.passengerTicketStrList = getPassengerDTOsResult.get(
                                "passengerTicketStrList", "")
                            self.oldPassengerStr = getPassengerDTOsResult.get(
                                "oldPassengerStr", "")
                            self.set_type = getPassengerDTOsResult.get(
                                "set_type", "")
                        # 提交订单
                        if self.order_type == 1:  # 快读下单
                            a = autoSubmitOrderRequest(
                                session=self,
                                secretStr=secretStr,
                                train_date=train_date,
                                passengerTicketStr=self.passengerTicketStrList,
                                oldPassengerStr=self.oldPassengerStr,
                                train_no=train_no,
                                stationTrainCode=stationTrainCode,
                                leftTicket=leftTicket,
                                set_type=self.set_type,
                                query_from_station_name=query_from_station_name,
                                query_to_station_name=query_to_station_name,
                            )
                            a.sendAutoSubmitOrderRequest()
                        elif self.order_type == 2:  # 普通下单
                            sor = submitOrderRequest(
                                self, secretStr, from_station, to_station,
                                train_no, self.set_type,
                                self.passengerTicketStrList,
                                self.oldPassengerStr, train_date,
                                self.ticke_peoples)
                            sor.sendSubmitOrderRequest()
                else:
                    random_time = round(
                        random.uniform(sleep_time_s, sleep_time_t), 2)
                    print(
                        u"正在第{0}次查询 随机停留时长:{6} 乘车日期: {1} 车次:{2} 查询无票 cdn轮询IP:{4}当前cdn总数:{5} 总耗时:{3}ms"
                        .format(num, ",".join(self.station_dates),
                                ",".join(self.station_trains),
                                (datetime.datetime.now() - now).microseconds /
                                1000, queryResult.get("cdn", None),
                                len(self.cdn_list), random_time))
                    time.sleep(random_time)
            except PassengerUserException as e:
                print(e)
                break
            except ticketConfigException as e:
                print(e)
                break
            except ticketIsExitsException as e:
                print(e)
                break
            except ticketNumOutException as e:
                print(e)
                break
            except UserPasswordException as e:
                print(e)
                break
            except ValueError as e:
                if e == "No JSON object could be decoded":
                    print(u"12306接口无响应,正在重试")
                else:
                    print(e)
            except KeyError as e:
                print(e)
            except TypeError as e:
                print(u"12306接口无响应,正在重试 {0}".format(e))
            except socket.error as e:
                print(e)
Esempio n. 5
0
class select:
    """
    快速提交车票通道
    """

    def __init__(self):
        self.from_station, self.to_station, self.station_dates, self._station_seat, self.is_more_ticket, \
        self.ticke_peoples, self.station_trains, self.ticket_black_list_time, \
        self.order_type = self.get_ticket_info()
        self.is_auto_code = _get_yaml()["is_auto_code"]
        self.auto_code_type = _get_yaml()["auto_code_type"]
        self.is_cdn = _get_yaml()["is_cdn"]
        self.httpClint = HTTPClient()
        self.urls = urlConf.urls
        self.login = GoLogin(self, self.is_auto_code, self.auto_code_type)
        self.cdn_list = []
        self.passengerTicketStrList = ""
        self.oldPassengerStr = ""

    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_dates = ticket_info_config["set"]["station_dates"]
        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"]
        station_trains = ticket_info_config["set"]["station_trains"]
        ticket_black_list_time = ticket_info_config["ticket_black_list_time"]
        order_type = ticket_info_config["order_type"]
        print u"*" * 20
        print u"12306刷票小助手,最后更新于2018.8.31,请勿作为商业用途,交流群号:286271084"
        print u"如果有好的margin,请联系作者,表示非常感激\n"
        print u"当前配置:出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票自动提交:{4}\n乘车人:{5}\n" \
              u"刷新间隔:随机(1-4S)\n候选购买车次:{6}\n僵尸票关小黑屋时长:{7}\n 下单接口:{8}\n".format \
                (
                from_station,
                to_station,
                station_dates,
                ",".join(set_type),
                is_more_ticket,
                ",".join(ticke_peoples),
                ",".join(station_trains),
                ticket_black_list_time,
                order_type,
            )
        print u"*" * 20
        return from_station, to_station, station_dates, set_type, is_more_ticket, ticke_peoples, station_trains, ticket_black_list_time, order_type

    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 call_login(self, auth=False):
        """
        登录回调方法
        :return:
        """
        if auth:
            return self.login.auth()
        else:
            self.login.go_login()

    def set_cdn(self):
        """
        设置cdn
        :return:
        """
        if self.is_cdn == 1:
            while True:
                if self.cdn_list:
                    self.httpClint.cdn = self.cdn_list[random.randint(0, len(self.cdn_list) - 1)]

    def cdn_req(self, cdn):
        for i in range(len(cdn) - 1):
            http = HTTPClient()
            urls = self.urls["loginInit"]
            start_time = datetime.datetime.now()
            http.cdn = cdn[i].replace("\n", "")
            rep = http.send(urls)
            if rep and "message" not in rep and (datetime.datetime.now() - start_time).microseconds / 1000 < 500:
                print("加入cdn {0}".format(cdn[i].replace("\n", "")))
                self.cdn_list.append(cdn[i].replace("\n", ""))
        print(u"所有cdn解析完成...")

    def cdn_certification(self):
        """
        cdn 认证
        :return:
        """
        if self.is_cdn == 1:
            CDN = CDNProxy()
            all_cdn = CDN.all_cdn()
            if all_cdn:
                print(u"开启cdn查询")
                print(u"本次待筛选cdn总数为{}".format(len(all_cdn)))
                t = threading.Thread(target=self.cdn_req, args=(all_cdn,))
                t2 = threading.Thread(target=self.set_cdn, args=())
                t.start()
                t2.start()
            else:
                raise ticketConfigException(u"cdn列表为空,请先加载cdn")
        else:
            pass

    def query_train_ticket(self, from_station, to_station, station_dates, train_no=None):
        """查询车次余票
        """
        self.cdn_certification()
        l = liftTicketInit(session=self)
        l.reqLiftTicketInit()
        checkUser(self).sendCheckUser()
        num = 0
        while num < 5:
            try:
                num += 1
                # checkUser(self).sendCheckUser()
                q = QueryTecket(session=self, station_dates=station_dates)
                # queryResult = q.sendQuery(from_station, to_station, train_no)
                queryResult = q.get_trains_status(from_station, to_station, train_no, True)
                # if len(queryResult) == 1:
                #     continue
                col_name = [u'车次', u'发站', u'到站', u'发车', u'到达', u'耗时', u'出发日期', u'无座', u'硬座', u'硬卧', u'软卧', u'高软', u'二等',
                            u'一等', u'商务', u'动卧']
                print json.dumps(col_name, ensure_ascii=False)
                for ret in queryResult:
                    for en in ret:
                        print json.dumps(en, ensure_ascii=False)

                return queryResult
            except Exception as ex:
                logging.error(traceback.format_exc())

    def main(self):
        self.cdn_certification()
        l = liftTicketInit(session=self)
        l.reqLiftTicketInit()
        self.call_login()
        checkUser(self).sendCheckUser()
        from_station, to_station = self.station_table(self.from_station, self.to_station)
        num = 0
        while 1:
            try:
                num += 1
                checkUser(self).sendCheckUser()
                if time.strftime('%H:%M:%S', time.localtime(time.time())) > "23:00:00" or time.strftime('%H:%M:%S',
                                                                                                        time.localtime(
                                                                                                            time.time())) < "06:00:00":
                    print(ticket.REST_TIME)
                    # while 1:
                    #     time.sleep(1)
                    #     if "06:00:00" < time.strftime('%H:%M:%S', time.localtime(time.time())) < "23:00:00":
                    #         print(ticket.REST_TIME_PAST)
                    #         self.call_login()
                    #         break
                start_time = datetime.datetime.now()

                q = query(session=self,
                          from_station=from_station,
                          to_station=to_station,
                          from_station_h=self.from_station,
                          to_station_h=self.to_station,
                          _station_seat=self._station_seat,
                          station_trains=self.station_trains,
                          station_dates=self.station_dates, )
                queryResult = q.sendQuery()
                # 查询接口
                # tmp = queryResult.get("status", False)
                # assert tmp == False
                if queryResult.get("status", False):
                    train_no = queryResult.get("train_no", "")
                    train_date = queryResult.get("train_date", "")
                    stationTrainCode = queryResult.get("stationTrainCode", "")
                    set_type = queryResult.get("set_type", "")
                    secretStr = queryResult.get("secretStr", "")
                    leftTicket = queryResult.get("leftTicket", "")
                    query_from_station_name = queryResult.get("query_from_station_name", "")
                    query_to_station_name = queryResult.get("query_to_station_name", "")
                    if wrapcache.get(train_no):
                        print(ticket.QUEUE_WARNING_MSG.format(train_no))
                    else:
                        # 获取联系人
                        if not self.passengerTicketStrList and not self.oldPassengerStr:
                            s = getPassengerDTOs(session=self, ticket_peoples=self.ticke_peoples, set_type=set_type)
                            #
                            getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr()
                            if getPassengerDTOsResult.get("status", False):
                                self.passengerTicketStrList = getPassengerDTOsResult.get("passengerTicketStrList", "")
                                self.oldPassengerStr = getPassengerDTOsResult.get("oldPassengerStr", "")
                                set_type = getPassengerDTOsResult.get("set_type", "")
                        # 提交订单
                        if self.order_type == 1:  # 快读下单
                            a = autoSubmitOrderRequest(session=self,
                                                       secretStr=secretStr,
                                                       train_date=train_date,
                                                       passengerTicketStr=self.passengerTicketStrList,
                                                       oldPassengerStr=self.oldPassengerStr,
                                                       train_no=train_no,
                                                       stationTrainCode=stationTrainCode,
                                                       leftTicket=leftTicket,
                                                       set_type=set_type,
                                                       query_from_station_name=query_from_station_name,
                                                       query_to_station_name=query_to_station_name,
                                                       )
                            a.sendAutoSubmitOrderRequest()
                        elif self.order_type == 2:  # 普通下单
                            sor = submitOrderRequest(self, secretStr, from_station, to_station, train_no, set_type,
                                                     self.passengerTicketStrList, self.oldPassengerStr, train_date,
                                                     self.ticke_peoples)
                            sor.sendSubmitOrderRequest()


                else:
                    random_time = round(random.uniform(1, 4), 2)
                    time.sleep(random_time)
                    print u"正在第{0}次查询 随机停留时长:{6} 乘车日期: {1} 车次:{2} 查询无票 cdn轮询IP:{4}当前cdn总数:{5} 总耗时:{3}ms".format(num,
                                                                                                                ",".join(
                                                                                                                    self.station_dates),
                                                                                                                ",".join(
                                                                                                                    self.station_trains),
                                                                                                                (datetime.datetime.now() - start_time).microseconds / 1000,
                                                                                                                self.httpClint.cdn,
                                                                                                                len(self.cdn_list),
                                                                                                                random_time)
            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 UserPasswordException as e:
                print e.message
                break
            except ValueError as e:
                if e.message == "No JSON object could be decoded":
                    print(u"12306接口无响应,正在重试")
                else:
                    print(e.message)
            except KeyError as e:
                print(e.message)
            except TypeError as e:
                print(u"12306接口无响应,正在重试 {0}".format(e.message))
            except socket.error as e:
                print(e.message)
Esempio n. 6
0
class select:
    """
    快速提交车票通道
    """
    def __init__(self):
        self.get_ticket_info()
        self._station_seat = [seat_conf[x] for x in TickerConfig.SET_TYPE]
        self.auto_code_type = 2
        self.httpClint = HTTPClient(TickerConfig.IS_PROXY)
        self.urls = urlConf.urls
        self.login = GoLogin(self, TickerConfig.IS_AUTO_CODE,
                             self.auto_code_type)
        self.cdn_list = []
        self.queryUrl = "leftTicket/queryT"
        self.passengerTicketStrList = ""
        self.passengerTicketStrByAfterLate = ""
        self.oldPassengerStr = ""
        self.set_type = ""
        self.flag = True

    @staticmethod
    def get_ticket_info():
        """
        获取配置信息
        :return:
        """
        print(u"*" * 50)
        print(f"检查当前版本为: {TickerConfig.RE_VERSION}")
        print(u"检查当前python版本为:{},目前版本只支持3.6以上".format(
            sys.version.split(" ")[0]))
        print(u"12306刷票小助手,最后更新于2019.09.03,请勿作为商业用途,交流群号:"
              u" 1群:286271084(已满)\n"
              u" 2群:649992274(已满)\n"
              u" 3群:632501142(已满)\n"
              u" 4群: 606340519(已满)\n"
              u" 5群: 948526733(已满)\n"
              u" 6群: 444101020(未满)\n"
              u" 7群: 660689659(未满)\n")
        print(
            f"当前配置:\n出发站:{TickerConfig.FROM_STATION}\n到达站:{TickerConfig.TO_STATION}\n乘车日期:{','.join(TickerConfig.STATION_DATES)}\n坐席:{','.join(TickerConfig.SET_TYPE)}\n是否有票优先提交:{TickerConfig.IS_MORE_TICKET}\n乘车人:{TickerConfig.TICKET_PEOPLES}\n" \
            f"刷新间隔: 随机(1-3S)\n僵尸票关小黑屋时长: {TickerConfig.TICKET_BLACK_LIST_TIME}\n下单接口: {TickerConfig.ORDER_TYPE}\n下单模式: {TickerConfig.ORDER_MODEL}\n预售踩点时间:{TickerConfig.OPEN_TIME}")
        print(u"*" * 50)

    def station_table(self, from_station, to_station):
        """
        读取车站信息
        :param station:
        :return:
        """
        path = os.path.join(os.path.dirname(__file__), '../station_name.txt')
        try:
            with open(path, encoding="utf-8") as result:
                info = result.read().split('=')[1].strip("'").split('@')
        except Exception:
            with open(path) as result:
                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]
        try:
            from_station = station_name[from_station.encode("utf8")]
            to_station = station_name[to_station.encode("utf8")]
        except KeyError:
            from_station = station_name[from_station]
            to_station = station_name[to_station]
        return from_station, to_station

    def call_login(self, auth=False):
        """
        登录回调方法
        :return:
        """
        if auth:
            return self.login.auth()
        else:
            configCommon.checkSleepTime(self)  # 防止网上启动晚上到点休眠
            self.login.go_login()

    def cdn_req(self, cdn):
        for i in range(len(cdn) - 1):
            http = HTTPClient(0)
            urls = self.urls["loginInitCdn"]
            http._cdn = cdn[i].replace("\n", "")
            start_time = datetime.datetime.now()
            rep = http.send(urls)
            if rep and "message" not in rep and (datetime.datetime.now(
            ) - start_time).microseconds / 1000 < 500:
                if cdn[i].replace("\n",
                                  "") not in self.cdn_list:  # 如果有重复的cdn,则放弃加入
                    # print(u"加入cdn {0}".format(cdn[i].replace("\n", "")))
                    self.cdn_list.append(cdn[i].replace("\n", ""))
        print(u"所有cdn解析完成...")

    def cdn_certification(self):
        """
        cdn 认证
        :return:
        """
        if TickerConfig.IS_CDN == 1:
            CDN = CDNProxy()
            all_cdn = CDN.open_cdn_file()
            if all_cdn:
                # print(u"由于12306网站策略调整,cdn功能暂时关闭。")
                print(u"开启cdn查询")
                print(u"本次待筛选cdn总数为{}, 筛选时间大约为5-10min".format(len(all_cdn)))
                t = threading.Thread(target=self.cdn_req, args=(all_cdn, ))
                t.setDaemon(True)
                # t2 = threading.Thread(target=self.set_cdn, args=())
                t.start()
                # t2.start()
            else:
                raise ticketConfigException(u"cdn列表为空,请先加载cdn")

    def main(self):
        self.cdn_certification()
        l = liftTicketInit(self)
        l.reqLiftTicketInit()
        # getDrvicesID(self)
        self.call_login()
        check_user = checkUser(self)
        t = threading.Thread(target=check_user.sendCheckUser)
        t.setDaemon(True)
        t.start()
        from_station, to_station = self.station_table(
            TickerConfig.FROM_STATION, TickerConfig.TO_STATION)
        num = 0
        s = getPassengerDTOs(session=self,
                             ticket_peoples=TickerConfig.TICKET_PEOPLES)
        passenger = s.sendGetPassengerDTOs()
        wrapcache.set("user_info", passenger, timeout=9999999)
        while 1:
            try:
                num += 1
                now = datetime.datetime.now()  # 感谢群里大佬提供整点代码
                configCommon.checkSleepTime(self)  # 晚上到点休眠
                if TickerConfig.ORDER_MODEL is 1:
                    sleep_time_s = 0.5
                    sleep_time_t = 0.6
                    # 测试了一下有微妙级的误差,应该不影响,测试结果:2019-01-02 22:30:00.004555,预售还是会受到前一次刷新的时间影响,暂时没想到好的解决方案
                    while not now.strftime(
                            "%H:%M:%S") == TickerConfig.OPEN_TIME:
                        now = datetime.datetime.now()
                        if now.strftime("%H:%M:%S") > TickerConfig.OPEN_TIME:
                            break
                        time.sleep(0.0001)
                else:
                    sleep_time_s = 0.5
                    sleep_time_t = 3
                q = query(
                    session=self,
                    from_station=from_station,
                    to_station=to_station,
                    from_station_h=TickerConfig.FROM_STATION,
                    to_station_h=TickerConfig.TO_STATION,
                    _station_seat=self._station_seat,
                    station_trains=TickerConfig.STATION_TRAINS,
                    station_dates=TickerConfig.STATION_DATES,
                    ticke_peoples_num=len(TickerConfig.TICKET_PEOPLES),
                )
                queryResult = q.sendQuery()
                # 查询接口
                if queryResult.get("status", False):
                    train_no = queryResult.get("train_no", "")
                    train_date = queryResult.get("train_date", "")
                    stationTrainCode = queryResult.get("stationTrainCode", "")
                    secretStr = queryResult.get("secretStr", "")
                    secretList = queryResult.get("secretList", "")
                    seat = queryResult.get("seat", "")
                    leftTicket = queryResult.get("leftTicket", "")
                    query_from_station_name = queryResult.get(
                        "query_from_station_name", "")
                    query_to_station_name = queryResult.get(
                        "query_to_station_name", "")
                    is_more_ticket_num = queryResult.get(
                        "is_more_ticket_num", len(TickerConfig.TICKET_PEOPLES))
                    if wrapcache.get(train_no):
                        print(ticket.QUEUE_WARNING_MSG.format(train_no))
                    else:
                        # 获取联系人
                        s = getPassengerDTOs(
                            session=self,
                            ticket_peoples=TickerConfig.TICKET_PEOPLES,
                            set_type=""
                            if isinstance(seat, list) else seat_conf_2[seat],
                            # 候补订单需要设置多个坐席
                            is_more_ticket_num=is_more_ticket_num)
                        getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr(
                            secretStr, secretList)
                        if getPassengerDTOsResult.get("status", False):
                            self.passengerTicketStrList = getPassengerDTOsResult.get(
                                "passengerTicketStrList", "")
                            self.passengerTicketStrByAfterLate = getPassengerDTOsResult.get(
                                "passengerTicketStrByAfterLate", "")
                            self.oldPassengerStr = getPassengerDTOsResult.get(
                                "oldPassengerStr", "")
                            self.set_type = getPassengerDTOsResult.get(
                                "set_type", "")
                        # 提交订单
                        # 订单分为两种,一种为抢单,一种为候补订单
                        if secretStr:  # 正常下单
                            if TickerConfig.ORDER_TYPE == 1:  # 快速下单
                                a = autoSubmitOrderRequest(
                                    session=self,
                                    secretStr=secretStr,
                                    train_date=train_date,
                                    passengerTicketStr=self.
                                    passengerTicketStrList,
                                    oldPassengerStr=self.oldPassengerStr,
                                    train_no=train_no,
                                    stationTrainCode=stationTrainCode,
                                    leftTicket=leftTicket,
                                    set_type=self.set_type,
                                    query_from_station_name=
                                    query_from_station_name,
                                    query_to_station_name=query_to_station_name,
                                )
                                a.sendAutoSubmitOrderRequest()
                            elif TickerConfig.ORDER_TYPE == 2:  # 普通下单
                                sor = submitOrderRequest(
                                    self, secretStr, from_station, to_station,
                                    train_no, self.set_type,
                                    self.passengerTicketStrList,
                                    self.oldPassengerStr, train_date,
                                    TickerConfig.TICKET_PEOPLES)
                                sor.sendSubmitOrderRequest()
                        elif secretList:  # 候补订单
                            c = chechFace(self, secretList)
                            c.sendChechFace()
                else:
                    random_time = round(
                        random.uniform(sleep_time_s, sleep_time_t), 2)
                    nateMsg = ' 无候补机会' if TickerConfig.ORDER_TYPE == 2 else ""
                    print(
                        f"正在第{num}次查询 随机停留时长:{random_time} 乘车日期: {','.join(TickerConfig.STATION_DATES)} 车次:{'.'.join(TickerConfig.STATION_TRAINS)}  下单无票{nateMsg} 耗时:{(datetime.datetime.now() - now).microseconds / 1000}ms"
                    )
                    time.sleep(random_time)
            except PassengerUserException as e:
                print(e)
                break
            except ticketConfigException as e:
                print(e)
                break
            except ticketIsExitsException as e:
                print(e)
                break
            except ticketNumOutException as e:
                print(e)
                break
            except UserPasswordException as e:
                print(e)
                break
            except ValueError as e:
                if e == "No JSON object could be decoded":
                    print(u"12306接口无响应,正在重试")
                else:
                    print(e)
            except KeyError as e:
                print(e)
            except TypeError as e:
                print(u"12306接口无响应,正在重试 {0}".format(e))
            except socket.error as e:
                print(e)
Esempio n. 7
0
class select:
    """
    快速提交车票通道
    """
    def __init__(self):
        self.from_station, self.to_station, self.station_dates, self._station_seat, self.is_more_ticket, \
        self.ticke_peoples, self.station_trains, self.ticket_black_list_time, \
        self.order_type, self.is_by_time, self.train_types, self.departure_time, \
        self.arrival_time, self.take_time = self.get_ticket_info()

        self.is_auto_code = _get_yaml()["is_auto_code"]
        self.auto_code_type = _get_yaml()["auto_code_type"]
        self.is_cdn = _get_yaml()["is_cdn"]
        self.httpClint = HTTPClient()
        self.urls = urlConf.urls
        self.login = GoLogin(self, self.is_auto_code, self.auto_code_type)
        self.cdn_list = []
        self.passengerTicketStrList = ""
        self.oldPassengerStr = ""
        self.set_type = ""

    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_dates = ticket_info_config["set"]["station_dates"]
        set_names = ticket_info_config["set"]["set_type"]
        set_type = [
            seat_conf[x.encode("utf8")]
            for x in ticket_info_config["set"]["set_type"]
        ]
        is_more_ticket = ticket_info_config["set"]["is_more_ticket"]
        ticke_peoples = ticket_info_config["set"]["ticke_peoples"]
        station_trains = ticket_info_config["set"]["station_trains"]
        ticket_black_list_time = ticket_info_config["ticket_black_list_time"]
        order_type = ticket_info_config["order_type"]

        # by time
        is_by_time = ticket_info_config["set"]["is_by_time"]
        train_types = ticket_info_config["set"]["train_types"]
        departure_time = time_to_minutes(
            ticket_info_config["set"]["departure_time"])
        arrival_time = time_to_minutes(
            ticket_info_config["set"]["arrival_time"])
        take_time = time_to_minutes(ticket_info_config["set"]["take_time"])

        print u"*" * 20
        print u"12306刷票小助手,最后更新于2018.9.21,请勿作为商业用途,交流群号:286271084"
        if is_by_time:
            method_notie="购票方式:根据时间区间购票\n可接受最早出发时间:{0}\n可接受最晚抵达时间:{1}\n可接受最长旅途时间:{2}\n可接受列车类型:{3}\n"\
            .format(minutes_to_time(departure_time),minutes_to_time(arrival_time),minutes_to_time(take_time)," , ".join(train_types))
        else:
            method_notie = "购票方式:根据候选车次购买\n候选购买车次:{0}".format(
                ",".join(station_trains))
        print u"当前配置:\n出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票优先提交:{4}\n乘车人:{5}\n" \
              u"刷新间隔:随机(1-3S)\n{6}\n僵尸票关小黑屋时长:{7}\n 下单接口:{8}\n".format \
                (
                from_station,
                to_station,
                station_dates,
                ",".join(set_names),
                is_more_ticket,
                ",".join(ticke_peoples),
                method_notie,
                ticket_black_list_time,
                order_type,
            )
        print u"*" * 20
        return from_station, to_station, station_dates, set_type, is_more_ticket, ticke_peoples, station_trains, ticket_black_list_time, order_type, is_by_time, train_types, departure_time, arrival_time, take_time

    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 call_login(self, auth=False):
        """
        登录回调方法
        :return:
        """
        if auth:
            return self.login.auth()
        else:
            self.login.go_login()

    def set_cdn(self):
        """
        设置cdn
        :return:
        """
        if self.is_cdn == 1:
            while True:
                if self.cdn_list:
                    self.httpClint.cdn = self.cdn_list[random.randint(
                        0,
                        len(self.cdn_list) - 1)]

    def cdn_req(self, cdn):
        for i in range(len(cdn) - 1):
            http = HTTPClient()
            urls = self.urls["loginInit"]
            http.cdn = cdn[i].replace("\n", "")
            start_time = datetime.datetime.now()
            rep = http.send(urls)
            if rep and "message" not in rep and (datetime.datetime.now(
            ) - start_time).microseconds / 1000 < 500:
                print("加入cdn {0}".format(cdn[i].replace("\n", "")))
                self.cdn_list.append(cdn[i].replace("\n", ""))
        print(u"所有cdn解析完成...")

    def cdn_certification(self):
        """
        cdn 认证
        :return:
        """
        if self.is_cdn == 1:
            CDN = CDNProxy()
            all_cdn = CDN.all_cdn()
            if all_cdn:
                print(u"由于12306网站策略调整,cdn功能暂时关闭。")
                # print(u"开启cdn查询")
                # print(u"本次待筛选cdn总数为{}, 筛选时间大约为5-10min".format(len(all_cdn)))
                # t = threading.Thread(target=self.cdn_req, args=(all_cdn,))
                # t2 = threading.Thread(target=self.set_cdn, args=())
                # t.start()
                # t2.start()
            else:
                raise ticketConfigException(u"cdn列表为空,请先加载cdn")

    def main(self):
        self.cdn_certification()
        l = liftTicketInit(self)
        l.reqLiftTicketInit()
        self.call_login()
        check_user = checkUser(self)
        check_user.sendCheckUser()
        from_station, to_station = self.station_table(self.from_station,
                                                      self.to_station)
        num = 0
        while 1:
            try:
                num += 1
                check_user.sendCheckUser()
                if time.strftime('%H:%M:%S', time.localtime(
                        time.time())) > "23:00:00" or time.strftime(
                            '%H:%M:%S', time.localtime(
                                time.time())) < "06:00:00":
                    print(ticket.REST_TIME)
                    while 1:
                        time.sleep(1)
                        if "06:00:00" < time.strftime(
                                '%H:%M:%S', time.localtime(
                                    time.time())) < "23:00:00":
                            print(ticket.REST_TIME_PAST)
                            self.call_login()
                            break
                start_time = datetime.datetime.now()

                q = query(
                    session=self,
                    from_station=from_station,
                    to_station=to_station,
                    from_station_h=self.from_station,
                    to_station_h=self.to_station,
                    _station_seat=self._station_seat,
                    station_trains=self.station_trains,
                    station_dates=self.station_dates,
                    ticke_peoples_num=len(self.ticke_peoples),
                )
                queryResult = q.sendQuery()
                # 查询接口
                if queryResult.get("status", False):
                    train_no = queryResult.get("train_no", "")
                    train_date = queryResult.get("train_date", "")
                    stationTrainCode = queryResult.get("stationTrainCode", "")
                    secretStr = queryResult.get("secretStr", "")
                    seat = queryResult.get("seat", "")
                    leftTicket = queryResult.get("leftTicket", "")
                    query_from_station_name = queryResult.get(
                        "query_from_station_name", "")
                    query_to_station_name = queryResult.get(
                        "query_to_station_name", "")
                    is_more_ticket_num = queryResult.get(
                        "is_more_ticket_num", len(self.ticke_peoples))
                    if wrapcache.get(train_no):
                        print(ticket.QUEUE_WARNING_MSG.format(train_no))
                    else:
                        # 获取联系人
                        s = getPassengerDTOs(
                            session=self,
                            ticket_peoples=self.ticke_peoples,
                            set_type=seat_conf_2[seat],
                            is_more_ticket_num=is_more_ticket_num)
                        getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr(
                        )
                        if getPassengerDTOsResult.get("status", False):
                            self.passengerTicketStrList = getPassengerDTOsResult.get(
                                "passengerTicketStrList", "")
                            self.oldPassengerStr = getPassengerDTOsResult.get(
                                "oldPassengerStr", "")
                            self.set_type = getPassengerDTOsResult.get(
                                "set_type", "")
                        # 提交订单
                        if self.order_type == 1:  # 快读下单
                            a = autoSubmitOrderRequest(
                                session=self,
                                secretStr=secretStr,
                                train_date=train_date,
                                passengerTicketStr=self.passengerTicketStrList,
                                oldPassengerStr=self.oldPassengerStr,
                                train_no=train_no,
                                stationTrainCode=stationTrainCode,
                                leftTicket=leftTicket,
                                set_type=self.set_type,
                                query_from_station_name=query_from_station_name,
                                query_to_station_name=query_to_station_name,
                            )
                            a.sendAutoSubmitOrderRequest()
                        elif self.order_type == 2:  # 普通下单
                            sor = submitOrderRequest(
                                self, secretStr, from_station, to_station,
                                train_no, self.set_type,
                                self.passengerTicketStrList,
                                self.oldPassengerStr, train_date,
                                self.ticke_peoples)
                            sor.sendSubmitOrderRequest()
                else:
                    random_time = round(random.uniform(1, 3), 2)
                    time.sleep(random_time)
                    print u"正在第{0}次查询 随机停留时长:{6} 乘车日期: {1} 车次:{2} 查询无票 cdn轮询IP:{4}当前cdn总数:{5} 总耗时:{3}ms".format(
                        num, ",".join(self.station_dates),
                        ",".join(self.station_trains),
                        (datetime.datetime.now() - start_time).microseconds /
                        1000, wrapcache.get("cdn"), len(self.cdn_list),
                        random_time)
            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 UserPasswordException as e:
                print e.message
                break
            except ValueError as e:
                if e.message == "No JSON object could be decoded":
                    print(u"12306接口无响应,正在重试")
                else:
                    print(e.message)
            except KeyError as e:
                print(e.message)
            except TypeError as e:
                print(u"12306接口无响应,正在重试 {0}".format(e.message))
            except socket.error as e:
                print(e.message)
Esempio n. 8
0
class QiangPiao(object):
    """
    快速提交车票通道
    """
    def __init__(self, qiangpiao_info=None):
        if qiangpiao_info is None:
            self.from_station, self.to_station, self.station_dates, self._station_seat, self.is_more_ticket, \
            self.ticke_peoples, self.station_trains, self.ticket_black_list_time, \
            self.order_type = self.get_ticket_info()
        else:
            pass
        self.is_auto_code = _get_yaml()["is_auto_code"]
        self.auto_code_type = _get_yaml()["auto_code_type"]
        self.is_cdn = _get_yaml()["is_cdn"]
        self.httpClint = HTTPClient()
        self.urls = urlConf.urls
        self.login = GoLogin(self, self.is_auto_code, self.auto_code_type)
        self.cdn_list = []
        self.passengerTicketStrList = ""
        self.oldPassengerStr = ""
        self.station_name_map = self.station_table(
            '../config/station_name.format')

    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_dates = ticket_info_config["set"]["station_dates"]
        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"]
        station_trains = ticket_info_config["set"]["station_trains"]
        ticket_black_list_time = ticket_info_config["ticket_black_list_time"]
        order_type = ticket_info_config["order_type"]
        print u"*" * 20
        print u"12306刷票小助手,最后更新于2018.12.12,请勿作为商业用途!"
        print u"*" * 20
        return from_station, to_station, station_dates, set_type, is_more_ticket, ticke_peoples, station_trains, ticket_black_list_time, order_type

    def station_table(self, files):
        """
        读取车站信息
        :param station:
        :return:
        """
        # result = open(files)
        station_name = {}
        with open(files) as fp:
            for line in fp:
                if line.startswith('#') or len(line.strip()) < 2:
                    continue
                line_arr = line.strip().decode('utf8').split('\t')
                station_name[line_arr[1]] = line_arr[2]

        # 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 station_name

    def call_login(self, auth=False):
        """
        登录回调方法
        :return:
        """
        if auth:
            return self.login.auth()
        else:
            self.login.go_login()

    def set_cdn(self):
        """
        设置cdn
        :return:
        """
        if self.is_cdn == 1:
            while True:
                if self.cdn_list:
                    self.httpClint.cdn = self.cdn_list[random.randint(
                        0,
                        len(self.cdn_list) - 1)]

    def cdn_req(self, cdn):
        for i in range(len(cdn) - 1):
            http = HTTPClient()
            urls = self.urls["loginInit"]
            start_time = datetime.datetime.now()
            http.cdn = cdn[i].replace("\n", "")
            rep = http.send(urls)
            if rep and "message" not in rep and (datetime.datetime.now(
            ) - start_time).microseconds / 1000 < 500:
                print("加入cdn {0}".format(cdn[i].replace("\n", "")))
                self.cdn_list.append(cdn[i].replace("\n", ""))
        print(u"所有cdn解析完成...")

    def cdn_certification(self):
        """
        cdn 认证
        :return:
        """
        if self.is_cdn == 1:
            CDN = CDNProxy()
            all_cdn = CDN.all_cdn()
            if all_cdn:
                print(u"开启cdn查询")
                print(u"本次待筛选cdn总数为{}".format(len(all_cdn)))
                t = threading.Thread(target=self.cdn_req, args=(all_cdn, ))
                t2 = threading.Thread(target=self.set_cdn, args=())
                t.start()
                t2.start()
            else:
                raise ticketConfigException(u"cdn列表为空,请先加载cdn")
        else:
            pass

    def query_train_ticket(self,
                           from_station,
                           to_station,
                           station_dates,
                           train_no=None):
        """查询车次余票
        """
        self.cdn_certification()
        l = liftTicketInit(session=self)
        l.reqLiftTicketInit()
        checkUser(self).sendCheckUser()
        num = 0
        while num < 5:
            try:
                num += 1
                # checkUser(self).sendCheckUser()
                q = QueryTecket(session=self, station_dates=station_dates)
                # queryResult = q.sendQuery(from_station, to_station, train_no)
                queryResult = q.get_trains_status(from_station, to_station,
                                                  train_no, True)
                # if len(queryResult) == 1:
                #     continue
                col_name = [
                    u'车次', u'发站', u'到站', u'发车', u'到达', u'耗时', u'出发日期', u'无座',
                    u'硬座', u'硬卧', u'软卧', u'高软', u'二等', u'一等', u'商务', u'动卧'
                ]
                print json.dumps(col_name, ensure_ascii=False)
                for ret in queryResult:
                    for en in ret:
                        print json.dumps(en, ensure_ascii=False)

                return queryResult
            except Exception as ex:
                logging.error(traceback.format_exc())

    def init_login(self):
        self.cdn_certification()
        l = liftTicketInit(session=self)
        l.reqLiftTicketInit()
        self.call_login()
        checkUser(self).sendCheckUser()

    def go_qiangpiao(self, tricket_info, log_info=[], num=1):
        try:
            from_station_h = tricket_info['from_station']
            to_station_h = tricket_info['to_station']
            from_station, to_station = self.station_name_map[
                from_station_h], self.station_name_map[to_station_h]
        except:
            return log_info.append(u'站点输入有误,请检查!')
        try:
            checkUser(self).sendCheckUser()
            now_time = time.strftime('%H:%M:%S', time.localtime(time.time()))
            while now_time > "23:00:00" or now_time < "06:00:00":
                time.sleep(5)
                now_time = time.strftime('%H:%M:%S',
                                         time.localtime(time.time()))
                if "06:00:00" < now_time < "23:00:00":
                    log_info.append(ticket.REST_TIME_PAST)
                    print(ticket.REST_TIME_PAST)
                    self.call_login()
                    break

            start_time = datetime.datetime.now()
            q = query(session=self,
                      from_station=from_station,
                      to_station=to_station,
                      from_station_h=from_station_h,
                      to_station_h=to_station_h,
                      _station_seat=tricket_info['seat'],
                      station_trains=tricket_info['trains'],
                      station_dates=tricket_info['date'])

            queryResult = q.sendQuery(log_info)
            # 查询接口
            # tmp = queryResult.get("status", False)
            # assert tmp == False
            if queryResult.get("status", False):
                train_no = queryResult.get("train_no", "")
                train_date = queryResult.get("train_date", "")
                stationTrainCode = queryResult.get("stationTrainCode", "")
                set_type = queryResult.get("set_type", "")
                secretStr = queryResult.get("secretStr", "")
                leftTicket = queryResult.get("leftTicket", "")
                query_from_station_name = queryResult.get(
                    "query_from_station_name", "")
                query_to_station_name = queryResult.get(
                    "query_to_station_name", "")
                if wrapcache.get(train_no):
                    print(ticket.QUEUE_WARNING_MSG.format(train_no))
                    log_info.append(ticket.QUEUE_WARNING_MSG.format(train_no))
                else:
                    # 获取联系人
                    if not self.passengerTicketStrList and not self.oldPassengerStr:
                        s = getPassengerDTOs(
                            session=self,
                            ticket_peoples=tricket_info['person_name'],
                            set_type=set_type)
                        #
                        getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr(
                        )
                        if getPassengerDTOsResult.get("status", False):
                            self.passengerTicketStrList = getPassengerDTOsResult.get(
                                "passengerTicketStrList", "")
                            self.oldPassengerStr = getPassengerDTOsResult.get(
                                "oldPassengerStr", "")
                            set_type = getPassengerDTOsResult.get(
                                "set_type", "")
                    self.order_type = 2
                    # 提交订单
                    if self.order_type == 1:  # 快读下单
                        a = autoSubmitOrderRequest(
                            session=self,
                            secretStr=secretStr,
                            train_date=train_date,
                            passengerTicketStr=self.passengerTicketStrList,
                            oldPassengerStr=self.oldPassengerStr,
                            train_no=train_no,
                            stationTrainCode=stationTrainCode,
                            leftTicket=leftTicket,
                            set_type=set_type,
                            query_from_station_name=query_from_station_name,
                            query_to_station_name=query_to_station_name,
                        )
                        a.sendAutoSubmitOrderRequest(log_info)
                    elif self.order_type == 2:  # 普通下单
                        sor = submitOrderRequest(
                            self, secretStr, from_station, to_station,
                            train_no, set_type, self.passengerTicketStrList,
                            self.oldPassengerStr, train_date,
                            self.ticke_peoples)
                        sor.sendSubmitOrderRequest(log_info)
            else:
                random_time = round(random.uniform(1, 4), 2)
                time.sleep(random_time)
                mess = u"正在第{0}次查询 随机停留时长:{6}s 乘车日期: {1} 车次:{2} 查询无票 cdn轮询IP:{4}当前cdn总数:{5} 总耗时:{3}ms".format(
                    num, ",".join(tricket_info['date']),
                    tricket_info['trains'],
                    (datetime.datetime.now() - start_time).microseconds / 1000,
                    self.httpClint.cdn, len(self.cdn_list), random_time)
                print mess
                log_info.append(mess)
        except PassengerUserException as e:
            print e.message
            log_info.append(e.message)
            # break
        except ticketConfigException as e:
            print e.message
            log_info.append(e.message)
            # break
        except ticketIsExitsException as e:
            print e.message
            log_info.append(e.message)
            # break
        except ticketNumOutException as e:
            print e.message
            log_info.append(e.message)
            # break
        except UserPasswordException as e:
            print e.message
            log_info.append(e.message)
            # break
        except ValueError as e:
            if e.message == "No JSON object could be decoded":
                print(u"12306接口无响应,正在重试")
                log_info.append(u"12306接口无响应,正在重试")
            else:
                print(e.message)
                log_info.append(e.message)
        except KeyError as e:
            print(e.message)
            log_info.append(e.message)
        except TypeError as e:
            print(u"12306接口无响应,正在重试 {0}".format(e.message))
            log_info.append(u"12306接口无响应,正在重试 {0}".format(e.message))
        except socket.error as e:
            print e
            log_info.append(e.message)

    def main(self):
        from_station, to_station = self.station_table(self.from_station,
                                                      self.to_station)
        num = 0
        while 1:
            try:
                num += 1
                checkUser(self).sendCheckUser()
                if time.strftime('%H:%M:%S', time.localtime(
                        time.time())) > "23:00:00" or time.strftime(
                            '%H:%M:%S', time.localtime(
                                time.time())) < "06:00:00":
                    print(ticket.REST_TIME)
                    # while 1:
                    #     time.sleep(1)
                    #     if "06:00:00" < time.strftime('%H:%M:%S', time.localtime(time.time())) < "23:00:00":
                    #         print(ticket.REST_TIME_PAST)
                    #         self.call_login()
                    #         break
                start_time = datetime.datetime.now()

                q = query(
                    session=self,
                    from_station=from_station,
                    to_station=to_station,
                    from_station_h=self.from_station,
                    to_station_h=self.to_station,
                    _station_seat=self._station_seat,
                    station_trains=self.station_trains,
                    station_dates=self.station_dates,
                )
                queryResult = q.sendQuery()
                # 查询接口
                # tmp = queryResult.get("status", False)
                # assert tmp == False
                if queryResult.get("status", False):
                    train_no = queryResult.get("train_no", "")
                    train_date = queryResult.get("train_date", "")
                    stationTrainCode = queryResult.get("stationTrainCode", "")
                    set_type = queryResult.get("set_type", "")
                    secretStr = queryResult.get("secretStr", "")
                    leftTicket = queryResult.get("leftTicket", "")
                    query_from_station_name = queryResult.get(
                        "query_from_station_name", "")
                    query_to_station_name = queryResult.get(
                        "query_to_station_name", "")
                    if wrapcache.get(train_no):
                        print(ticket.QUEUE_WARNING_MSG.format(train_no))
                    else:
                        # 获取联系人
                        if not self.passengerTicketStrList and not self.oldPassengerStr:
                            s = getPassengerDTOs(
                                session=self,
                                ticket_peoples=self.ticke_peoples,
                                set_type=set_type)
                            #
                            getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr(
                            )
                            if getPassengerDTOsResult.get("status", False):
                                self.passengerTicketStrList = getPassengerDTOsResult.get(
                                    "passengerTicketStrList", "")
                                self.oldPassengerStr = getPassengerDTOsResult.get(
                                    "oldPassengerStr", "")
                                set_type = getPassengerDTOsResult.get(
                                    "set_type", "")
                        # 提交订单
                        if self.order_type == 1:  # 快读下单
                            a = autoSubmitOrderRequest(
                                session=self,
                                secretStr=secretStr,
                                train_date=train_date,
                                passengerTicketStr=self.passengerTicketStrList,
                                oldPassengerStr=self.oldPassengerStr,
                                train_no=train_no,
                                stationTrainCode=stationTrainCode,
                                leftTicket=leftTicket,
                                set_type=set_type,
                                query_from_station_name=query_from_station_name,
                                query_to_station_name=query_to_station_name,
                            )
                            a.sendAutoSubmitOrderRequest()
                        elif self.order_type == 2:  # 普通下单
                            sor = submitOrderRequest(
                                self, secretStr, from_station, to_station,
                                train_no, set_type,
                                self.passengerTicketStrList,
                                self.oldPassengerStr, train_date,
                                self.ticke_peoples)
                            sor.sendSubmitOrderRequest()

                else:
                    random_time = round(random.uniform(1, 4), 2)
                    time.sleep(random_time)
                    print u"正在第{0}次查询 随机停留时长:{6}s 乘车日期: {1} 车次:{2} 查询无票 cdn轮询IP:{4}当前cdn总数:{5} 总耗时:{3}ms".format(
                        num, ",".join(self.station_dates),
                        ",".join(self.station_trains),
                        (datetime.datetime.now() - start_time).microseconds /
                        1000, self.httpClint.cdn, len(self.cdn_list),
                        random_time)
            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 UserPasswordException as e:
                print e.message
                break
            except ValueError as e:
                if e.message == "No JSON object could be decoded":
                    print(u"12306接口无响应,正在重试")
                else:
                    print(e.message)
            except KeyError as e:
                print(e.message)
            except TypeError as e:
                print(u"12306接口无响应,正在重试 {0}".format(e.message))
            except socket.error as e:
                print(e.message)
Esempio n. 9
0
class select:
    def __init__(self):
        self.from_station, self.to_station, self.station_dates, self._station_seat, self.is_more_ticket, self.ticke_peoples, self.select_refresh_interval, self.station_trains, self.ticket_black_list_time = self.get_ticket_info()
        self.is_aotu_code = _get_yaml()["is_aotu_code"]
        self.aotu_code_type = _get_yaml()["aotu_code_type"]
        self.is_cdn = _get_yaml()["is_cdn"]
        self.order_request_params = {}  # 订单提交时的参数
        self.ticketInfoForPassengerForm = {}  # 初始化当前页面参数
        self.current_seats = {}  # 席别信息
        self.token = ""
        self.set_type = ""
        self.user_info = ""
        self.secretStr = ""
        self.ticket_black_list = dict()
        self.is_check_user = dict()
        self.httpClint = HTTPClient()
        self.confUrl = urlConf.urls
        self.login = GoLogin(self.httpClint, self.confUrl, self.is_aotu_code, self.aotu_code_type)
        self.is_download_img = False
        self.randCode = ""
        self.cdn_list = []
        self.buy_ticket_time = ""

    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_dates = ticket_info_config["set"]["station_dates"]
        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"]
        ticket_black_list_time = ticket_info_config["ticket_black_list_time"]
        print u"*"*20
        print u"12306刷票小助手,最后更新于2018.2.28,请勿作为商业用途,交流群号:286271084"
        print u"如果有好的margin,请联系作者,表示非常感激\n"
        print u"当前配置:出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票自动提交:{4}\n乘车人:{5}\n刷新间隔:{6}s(如果想随机刷新,请自行修改)\n候选购买车次:{7}\n僵尸票关小黑屋时长:{8}\n".format\
                                                                                      (
                                                                                      from_station,
                                                                                      to_station,
                                                                                      station_dates,
                                                                                      ",".join(set_type),
                                                                                      is_more_ticket,
                                                                                      ",".join(ticke_peoples),
                                                                                      select_refresh_interval,
                                                                                      ",".join(station_trains),
                                                                                      ticket_black_list_time,
            )
        print u"*"*20
        return from_station, to_station, station_dates, set_type, is_more_ticket, ticke_peoples, select_refresh_interval, station_trains, 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 today.strftime('%Y-%m-%d')

    def callReadImg(self, code_url):
        """
        下载验证码
        :param code_url: 验证码url
        :return:
        """
        self.login.readImg(code_url=code_url)
        self.is_aotu_code = True

    def callRandCode(self):
        """
        识别验证码
        :return:
        """
        while True:
            if self.is_aotu_code:
                self.randCode = self.login.getRandCode()
                self.is_aotu_code = False

    def getRepeatSubmitToken(self):
        """
        获取提交车票请求token
        :return: token
        """
        initdc_url = self.confUrl["initdc_url"]
        initdc_result = self.httpClint.send(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=(\{.+\})?')
        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 GetJS(self):
        getJSUrl = self.confUrl["GetJS"]
        self.httpClint.send(getJSUrl)
        odxmfwgUrl = self.confUrl["odxmfwg"]
        self.httpClint.send(odxmfwgUrl)

    def getPassengerDTOs(self):
        """
        获取乘客信息
        :return: 
        """
        get_passengerDTOs = self.confUrl["get_passengerDTOs"]
        get_data = {
            '_json_att': None,
            'REPEAT_SUBMIT_TOKEN': self.token
        }
        jsonData = self.httpClint.send(get_passengerDTOs, get_data)
        if 'data' in jsonData and jsonData['data'] and 'normal_passengers' in jsonData['data'] and 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(u"未查找到常用联系人")
                raise PassengerUserException(u"未查找到常用联系人,请先添加联系人在试试")

    def submitOrderRequestFunc(self, from_station, to_station, station_date=None):
        self.confUrl["select_url"]["req_url"] = self.confUrl["select_url"]["req_url"].format(
            station_date, from_station, to_station)
        station_ticket = self.httpClint.send(self.confUrl["select_url"])
        return json.loads(station_ticket)

    def submitOrderRequestImplement(self, from_station, to_station,):
        """
        提交车次信息
        车次对应字典
        {32: '商务座 ',
            31: '一等座 ',
            30: '二等座 ',
            25: '特等座 ',
            23: '软卧 ',
            28: '硬卧 ',
            29: '硬座 ',
            26: '无座 '
        } 参照station_seat()方法
        :return:
        """
        station_tickets = [self.submitOrderRequestFunc(from_station, to_station, station_date) for station_date in self.station_dates]
        for station_ticket in station_tickets:
            value = station_ticket['data']
            if not value:
                print (u'{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 (u'车次: ' + 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(u"该车次{} 正在被关小黑屋,跳过此车次".format(train_no))
                                        break
                                    else:
                                        print (u'正在尝试提交订票...')
                                        self.buy_ticket_time = datetime.datetime.now()
                                        # self.submitOrderRequestFunc(from_station, to_station, self.time())
                                        self.submit_station()
                                        self.getPassengerTicketStr(self._station_seat[j].encode("utf8"))
                                        self.getRepeatSubmitToken()
                                        if not self.user_info:  # 修改每次都调用用户接口导致用户接口不能用
                                            self.user_info = self.getPassengerDTOs()
                                        codeImgByOrder = self.confUrl["codeImgByOrder"]
                                        self.login.readImg(codeImgByOrder)
                                        if self.checkOrderInfo(train_no, self._station_seat[j].encode("utf8")):
                                            break
                                else:
                                    pass
                        else:
                            pass
                    # time.sleep(self.expect_refresh_interval)
                else:
                    print u"车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket)

    def check_user(self):
        """
        检查用户是否达到订票条件
        :return:
        """
        check_user_url = self.confUrl["check_user_url"]
        data = {"_json_att": ""}
        check_user = self.httpClint.send(check_user_url, data)
        check_user_flag = check_user['data']['flag']
        if check_user_flag is True:
            self.is_check_user["user_time"] = datetime.datetime.now()
        else:
            if check_user['messages']:
                print (u'用户检查失败:%s,可能未登录,可能session已经失效' % check_user['messages'][0])
                print (u'正在尝试重新登录')
                self.call_login()
                self.is_check_user["user_time"] = datetime.datetime.now()
            else:
                print (u'用户检查失败: %s,可能未登录,可能session已经失效' % check_user)
                print (u'正在尝试重新登录')
                self.call_login()
                self.is_check_user["user_time"] = datetime.datetime.now()

    def submit_station(self):
        """
        提交车次
        预定的请求参数,注意参数顺序
        注意这里为了防止secretStr被urllib.parse过度编码,在这里进行一次解码
        否则调用HttpTester类的post方法将会将secretStr编码成为无效码,造成提交预定请求失败
        :param self:
        :param secretStr: 提交车次加密
        :return:
        """
        submit_station_url = self.confUrl["submit_station_url"]
        data = [('secretStr', urllib.unquote(self.secretStr)),  # 字符串加密
                ('train_date', self.station_dates[0]),  # 出发时间
                ('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 = self.httpClint.send(submit_station_url, data)
        if 'data' in submitResult and submitResult['data']:
            if submitResult['data'] == 'N':
                print (u'出票成功')
            else:
                print (u'出票失败')
        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(u"联系人不在列表中,请查证后添加")
        if len(self.user_info) is 1:
            passengerTicketStrList.append(
                '0,' + self.user_info[0]['passenger_type'] + "," + self.user_info[0][
                    "passenger_name"] + "," +
                self.user_info[0]['passenger_id_type_code'] + "," + 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_id_type_code'] + "," +
                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_type'] + "," + self.user_info[i][
                        "passenger_name"] + "," + self.user_info[i]['passenger_id_type_code'] + "," + 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_id_type_code'] + "," +
                    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 = self.confUrl["checkOrderInfoUrl"]
        data = collections.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 = self.httpClint.send(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 (u'车票提交通过,正在尝试排队')
                    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:
        """
        l_time = time.localtime(time.time())
        new_train_date = time.strftime("%a %b %d %Y", l_time)
        getQueueCountUrl = self.confUrl["getQueueCountUrl"]
        data = collections.OrderedDict()
        data['train_date'] = str(new_train_date) + " 00:00:00 GMT+0800 (中国标准时间)",
        data['train_no'] = self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['train_no'],
        data['stationTrainCode'] = self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['station_train_code'],
        data['seatType'] = self.set_type,
        data['fromStationTelecode'] = self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['from_station'],
        data['toStationTelecode'] = self.get_ticketInfoForPassengerForm()['queryLeftTicketRequestDTO']['to_station'],
        data['leftTicket'] = self.get_ticketInfoForPassengerForm()['leftTicketStr'],
        data['purpose_codes'] = self.get_ticketInfoForPassengerForm()['purpose_codes'],
        data['train_location'] = self.get_ticketInfoForPassengerForm()['train_location'],
        data['REPEAT_SUBMIT_TOKEN'] = self.get_token(),
        getQueueCountResult = self.httpClint.send(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
                countT = getQueueCountResult["data"]["countT"]
                if int(countT) is 0:
                    if int(ticket_split) < len(self.user_info):
                        print(u"当前余票数小于乘车人数,放弃订票")
                    else:
                        print(u"排队成功, 当前余票还剩余: {0} 张".format(ticket_split))
                        if self.checkQueueOrder(is_need_code):
                            return True
                else:
                    print(u"当前排队人数: {1} 当前余票还剩余:{0} 张,继续排队中".format(ticket_split, countT))
            else:
                print(u"排队发现未知错误{0},将此列车 {1}加入小黑屋".format(getQueueCountResult, train_no))
                self.ticket_black_list[train_no] = datetime.datetime.now()
        elif "messages" in getQueueCountResult and getQueueCountResult["messages"]:
            print(u"排队异常,错误信息:{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(u"未知错误 {0}".format("".join(getQueueCountResult)))

    def checkRandCodeAnsyn(self, randCode):
        """
        识别验证码
        :return: 识别结果
        """
        checkRandCodeAnsyn = self.confUrl["checkRandCodeAnsyn"]
        randData = {
            "randCode": randCode,
            "rand": "randp",
            "_json_att": None,
            "REPEAT_SUBMIT_TOKEN": self.get_token()
        }
        fresult = self.httpClint.send(checkRandCodeAnsyn, randData)  # 校验验证码是否正确
        return fresult['data']['msg']

    def checkQueueOrder(self, is_node_code=False):
        """
        模拟提交订单是确认按钮,参数获取方法还是get_ticketInfoForPassengerForm 中获取
        :return: 
        """

        passengerTicketStrList, oldPassengerStr = self.getPassengerTicketStrListAndOldPassengerStr()
        checkQueueOrderUrl = self.confUrl["checkQueueOrderUrl"]
        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",
            "whatsSelect": 1,
            "_json_at": "",
            "randCode": "",
            "choose_seats": "",
            "REPEAT_SUBMIT_TOKEN": self.get_token(),
        }
        try:
            if is_node_code:
                print(u"正在使用自动识别验证码功能")
                for i in range(3):
                    randCode = self.login.getRandCode()
                    checkcode = self.checkRandCodeAnsyn(randCode)
                    if checkcode == 'TRUE':
                        print(u"验证码通过,正在提交订单")
                        data['randCode'] = randCode
                        break
                    else:
                        print (u"验证码有误, {0}次尝试重试".format(i+1))
                print(u"验证码超过限定次数3次,放弃此次订票机会!")
            else:
                print(u"不需要验证码")
            buy_end_time = (datetime.datetime.now() - self.buy_ticket_time).seconds
            print(u"总共花费时长{0}S".format(buy_end_time))
            time.sleep(8-buy_end_time if buy_end_time<8 else 0)
            checkQueueOrderResult = self.httpClint.send(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(u"提交订单成功!")
                    self.queryOrderWaitTime()
                else:
                    if 'errMsg' in c_data and c_data['errMsg']:
                        print(u"提交订单失败,{0}".format(c_data['errMsg']))
                    else:
                        print(c_data)
                        print(u'订票失败!很抱歉,请重试提交预订功能!')
            elif "messages" in checkQueueOrderResult and checkQueueOrderResult["messages"]:
                print(u"提交订单失败,错误信息: " + checkQueueOrderResult["messages"])
            else:
                print(u"提交订单中,请耐心等待:" + checkQueueOrderResult["message"])
        except ValueError:
            print(u"接口 {} 无响应".format(checkQueueOrderUrl))

    def queryOrderWaitTime(self):
        """
        排队获取订单等待信息,每隔3秒请求一次,最高请求次数为20次!
        :return: 
        """
        num = 1
        while True:
            _random = int(round(time.time() * 1000))
            num += 1
            if num > 30:
                print(u"超出排队时间,自动放弃,正在重新刷票")
                order_id = self.queryMyOrderNoComplete()  # 排队失败,自动取消排队订单
                if order_id:
                    self.cancelNoCompleteMyOrder(order_id)
                break
            try:
                data = {"random": _random, "tourFlag": "dc"}
                queryOrderWaitTimeUrl = self.confUrl["queryOrderWaitTimeUrl"]
                queryOrderWaitTimeResult = self.httpClint.send(queryOrderWaitTimeUrl, data)
            except ValueError:
                queryOrderWaitTimeResult = {}
            if queryOrderWaitTimeResult:
                if "status" in queryOrderWaitTimeResult and queryOrderWaitTimeResult["status"]:
                    if "orderId" in queryOrderWaitTimeResult["data"] and queryOrderWaitTimeResult["data"]["orderId"] is not None:
                        sendEmail(u"恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!".format(queryOrderWaitTimeResult["data"]["orderId"]))
                        raise ticketIsExitsException(u"恭喜您订票成功,订单号为:{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(u"排队等待时间预计还剩 {0} ms".format(0-queryOrderWaitTimeResult["data"]["waitTime"]))
                    else:
                        print ("正在等待中")
                elif "messages" in queryOrderWaitTimeResult and queryOrderWaitTimeResult["messages"]:
                    print(u"排队等待失败: " + queryOrderWaitTimeResult["messages"])
                else:
                    print(u"第{}次排队中,请耐心等待".format(num+1))
            else:
                print(u"排队中")
            time.sleep(2)

        else:
            print(ticketNumOutException(u"订单提交失败!,正在重新刷票"))

    def queryMyOrderNoComplete(self):
        """
        获取订单列表信息
        :return:
        """
        self.initNoComplete()
        queryMyOrderNoCompleteUrl = self.confUrl["queryMyOrderNoCompleteUrl"]
        data = {"_json_att": ""}
        try:
            queryMyOrderNoCompleteResult = self.httpClint.send(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(u"接口 {} 无响应".format(queryMyOrderNoCompleteUrl))

    def initNoComplete(self):
        """
        获取订单前需要进入订单列表页,获取订单列表页session
        :return:
        """
        self.httpClint.set_cookies(acw_tc="AQAAAEnFJnekLwwAtGHjZZCr79B6dpXk", current_captcha_type="Z")
        initNoCompleteUrl = self.confUrl["initNoCompleteUrl"]
        data = {"_json_att": ""}
        self.httpClint.send(initNoCompleteUrl, data)

    def cancelNoCompleteMyOrder(self, sequence_no):
        """
        取消订单
        :param sequence_no: 订单编号
        :return:
        """
        cancelNoCompleteMyOrderUrl = self.confUrl["cancelNoCompleteMyOrder"]
        cancelNoCompleteMyOrderData = {
            "sequence_no": sequence_no,
            "cancel_flag": "cancel_order",
            "_json_att": ""
        }
        cancelNoCompleteMyOrderResult = self.httpClint.send(cancelNoCompleteMyOrderUrl, cancelNoCompleteMyOrderData)
        if "data" in cancelNoCompleteMyOrderResult and "existError" in cancelNoCompleteMyOrderResult["data"] and cancelNoCompleteMyOrderResult["data"]["existError"] == "N":
            print(u"排队超时,已为您自动取消订单,订单编号: {0}".format(sequence_no))
            time.sleep(2)
            return True
        else:
            print(u"排队超时,取消订单失败, 订单号{0}".format(sequence_no))

    def set_cdn(self):
        """
        设置cdn
        :return:
        """
        if self.is_cdn == 1:
            while True:
                if self.cdn_list:
                    self.httpClint.cdn = self.cdn_list[random.randint(0, len(self.cdn_list)-1)]
                    break
                else:
                    pass

    def call_login(self, auth=False):
        """
        登录回调方法
        :return:
        """
        if auth:
            return self.login.auth()
        else:
            self.login.go_login()

    def cdn_req(self, cdn):
        for i in range(len(cdn)-1):
            http = HTTPClient()
            urls = self.confUrl["loginInit"]
            start_time = datetime.datetime.now()
            http.cdn = cdn[i].replace("\n", "")
            rep = http.send(urls)
            if rep and "message" not in rep and (datetime.datetime.now() - start_time).microseconds / 1000 < 200:
                self.cdn_list.append(cdn[i].replace("\n", ""))
        print(u"所有cdn解析完成...")

    def cdn_certification(self):
        """
        cdn 认证
        :return:
        """
        if self.is_cdn == 1:
            CDN = CDNProxy()
            all_cdn = CDN.all_cdn()
            if all_cdn:
                print(u"开启cdn查询")
                print(u"本次待筛选cdn总数为{}".format(len(all_cdn)))
                t = threading.Thread(target=self.cdn_req, args=(all_cdn,))
                t.start()
            else:
                raise ticketConfigException(u"cdn列表为空,请先加载cdn")
        else:
            pass

    def main(self):
        self.cdn_certification()
        self.set_cdn()
        self.call_login()
        from_station, to_station = self.station_table(self.from_station, self.to_station)
        self.check_user()
        time.sleep(0.1)
        num = 1
        while 1:
            try:
                num += 1
                if "user_time" in self.is_check_user and (datetime.datetime.now() - self.is_check_user["user_time"]).seconds/60 > 5:
                    # 5分钟检查一次用户是否登录
                    self.check_user()
                time.sleep(self.select_refresh_interval)
                if time.strftime('%H:%M:%S', time.localtime(time.time())) > "23:00:00" or time.strftime('%H:%M:%S', time.localtime(time.time())) < "06:00:00":
                    print(u"12306休息时间,本程序自动停止,明天早上6点将自动运行")
                    while 1:
                        time.sleep(1)
                        if time.strftime('%H:%M:%S', time.localtime(time.time())) > "06:00:00":
                            print(u"休息时间已过,重新开启检票功能")
                            self.call_login()
                            break
                start_time = datetime.datetime.now()
                self.submitOrderRequestImplement(from_station, to_station)
                print u"正在第{0}次查询  乘车日期: {1}  车次{2} 查询无票  cdn轮询IP {4} 当前cdn总数{5} 总耗时{3}ms".format(num,
                                                                                                 ",".join(self.station_dates),
                                                                                                 ",".join(self.station_trains),
                                                                                                 (datetime.datetime.now()-start_time).microseconds/1000, self.httpClint.cdn,
                                                                                                 len(self.cdn_list))
                self.set_cdn()
            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 UserPasswordException as e:
                print e.message
                break
            except ValueError as e:
                if e.message == "No JSON object could be decoded":
                    print(u"12306接口无响应,正在重试")
                else:
                    print(e.message)
            except KeyError as e:
                print(e.message)
            except TypeError as e:
                print(u"12306接口无响应,正在重试 {0}".format(e.message))
            except socket.error as e:
                print(e.message)