diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.idea/dictionaries/wenxianping.xml b/.idea/dictionaries/wenxianping.xml old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/__init__.py b/__init__.py old mode 100644 new mode 100755 diff --git a/agency/__init__.py b/agency/__init__.py old mode 100644 new mode 100755 diff --git a/agency/agency_tools.py b/agency/agency_tools.py old mode 100644 new mode 100755 diff --git a/agency/cdn_utils.py b/agency/cdn_utils.py old mode 100644 new mode 100755 diff --git a/cdn_list b/cdn_list old mode 100644 new mode 100755 diff --git a/config/TicketEnmu.py b/config/TicketEnmu.py new file mode 100644 index 0000000..21958a8 --- /dev/null +++ b/config/TicketEnmu.py @@ -0,0 +1,35 @@ +# coding=utf-8 + + +class ticket(object): + QUERY_C = u"查询到有余票,尝试提交订单" + QUERY_IN_BLACK_LIST = u"该车次{} 正在被关小黑屋,跳过此车次" + + SUCCESS_CODE = 000000 + FAIL_CODE = 999999 + AUTO_SUBMIT_ORDER_REQUEST_C = u"提交订单成功" + AUTO_SUBMIT_ORDER_REQUEST_F = u"提交订单失败,重新刷票中" + AUTO_SUBMIT_NEED_CODE = u"需要验证码" + AUTO_SUBMIT_NOT_NEED_CODE = u"不需要验证码" + + TICKET_BLACK_LIST_TIME = 5 # 加入小黑屋的等待时间,默认5 min + + DTO_NOT_FOUND = u"未查找到常用联系人" + DTO_NOT_IN_LIST = u"联系人不在列表中,请查证后添加" + + QUEUE_TICKET_SHORT = u"当前余票数小于乘车人数,放弃订票" + QUEUE_TICKET_SUCCESS = u"排队成功, 当前余票还剩余: {0}张" + QUEUE_JOIN_BLACK = u"排队发现未知错误{0},将此列车 {1}加入小黑屋" + QUEUE_WARNING_MSG = u"排队异常,错误信息:{0}, 将此列车 {1}加入小黑屋" + + OUT_NUM = 30 # 排队请求12306的次数 + WAIT_OUT_NUM = u"超出排队时间,自动放弃,正在重新刷票" + WAIT_ORDER_SUCCESS = u"恭喜您订票成功,订单号为:{0}, 请立即打开浏览器登录12306,访问‘未完成订单’,在30分钟内完成支付!" + WAIT_ORDER_CONTINUE = u"排队等待时间预计还剩 {0} ms" + WAIT_ORDER_FAIL = u"排队等待失败,错误消息:{0}" + WAIT_ORDER_NUM = u"第{0}次排队中,请耐心等待" + WAIT_ORDER_SUB_FAIL = u"订单提交失败!,正在重新刷票" + + CANCEL_ORDER_SUCCESS = u"排队超时,已为您自动取消订单,订单编号: {0}" + CANCEL_ORDER_FAIL = u"排队超时,取消订单失败, 订单号{0}" + diff --git a/config/__init__.py b/config/__init__.py old mode 100644 new mode 100755 diff --git a/config/configCommon.py b/config/configCommon.py old mode 100644 new mode 100755 diff --git a/config/emailConf.py b/config/emailConf.py old mode 100644 new mode 100755 diff --git a/config/logger.py b/config/logger.py old mode 100644 new mode 100755 diff --git a/config/ticketConf.py b/config/ticketConf.py old mode 100644 new mode 100755 diff --git a/config/ticket_config.yaml b/config/ticket_config.yaml old mode 100644 new mode 100755 index 5f377bd..e5dc98b --- a/config/ticket_config.yaml +++ b/config/ticket_config.yaml @@ -41,11 +41,11 @@ set: station_dates: - - "2018-03-19" -# - "2018-02-21" + - "2018-06-21" + - "2018-06-22" station_trains: - - "G4831" + - "G1321" from_station: "上海" to_station: "长沙" @@ -60,7 +60,7 @@ set: 12306count: # - uesr: "" # - pwd: "apple1995" - - uesr: "@qq.com" + - uesr: "931128603@qq.com" - pwd: "QWERTY" select_refresh_interval: 1 diff --git a/config/urlConf.py b/config/urlConf.py old mode 100644 new mode 100755 index 9d4f0bb..1a79097 --- a/config/urlConf.py +++ b/config/urlConf.py @@ -1,24 +1,27 @@ +# coding=utf-8 import random import time urls = { - "auth": { + "auth": { # 登录接口 "req_url": "/passport/web/auth/uamtk", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin", "Host": "kyfw.12306.cn", + "Content-Type": 1, "re_try": 10, "re_time": 0.1, "s_time": 0.1, "is_logger": True, "is_json": True, }, - "login": { + "login": { # 登录接口 "req_url": "/passport/web/login", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/login/init", "Host": "kyfw.12306.cn", + "Content-Type": 1, "re_try": 10, "re_time": 0.1, "s_time": 0.1, @@ -26,29 +29,44 @@ urls = { "is_json": True, }, - "getCodeImg": { + "left_ticket_init": { # 登录接口 + "req_url": "/otn/leftTicket/init", + "req_type": "post", + "Referer": "https://kyfw.12306.cn/otn/login/init", + "Host": "kyfw.12306.cn", + "Content-Type": 1, + "re_try": 10, + "re_time": 0.1, + "s_time": 0.1, + "is_logger": False, + "is_json": False, + + }, + "getCodeImg": { # 登录验证码 "req_url": "/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&{0}", "req_type": "get", "Referer": "https://kyfw.12306.cn/otn/login/init", "Host": "kyfw.12306.cn", + "Content-Type": 1, "re_try": 10, "re_time": 0.1, "s_time": 0.1, "is_logger": False, "is_json": False, }, - "codeCheck": { + "codeCheck": { # 验证码校验 "req_url": "/passport/captcha/captcha-check", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/login/init", "Host": "kyfw.12306.cn", + "Content-Type": 1, "re_try": 10, "re_time": 0.1, "s_time": 0.1, "is_logger": True, "is_json": True, }, - "loginInit": { + "loginInit": { # 登录页面 "req_url": "/otn/login/init", "req_type": "get", "Referer": "https://kyfw.12306.cn/otn/index/init", @@ -59,7 +77,7 @@ urls = { "is_logger": False, "is_json": False, }, - "getUserInfo": { + "getUserInfo": { # 获取用户信息 "req_url": "/otn/index/initMy12306", "req_type": "get", "Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin", @@ -70,7 +88,7 @@ urls = { "is_logger": False, "is_json": False, }, - "userLogin": { + "userLogin": { # 用户登录 "req_url": "/otn/login/userLogin", "req_type": "get", "Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin", @@ -81,18 +99,19 @@ urls = { "is_logger": True, "is_json": True, }, - "uamauthclient": { + "uamauthclient": { # 登录 "req_url": "/otn/uamauthclient", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin", "Host": "kyfw.12306.cn", + "Content-Type": 1, "re_try": 10, "re_time": 0.1, "s_time": 0.1, "is_logger": True, "is_json": True, }, - "initdc_url": { + "initdc_url": { # 生成订单页面 "req_url": "/otn/confirmPassenger/initDc", "req_type": "get", "Referer": "https://kyfw.12306.cn/otn/leftTicket/init", @@ -103,7 +122,7 @@ urls = { "is_logger": False, "is_json": False, }, - "GetJS": { + "GetJS": { # 订单页面js "req_url": "/otn/HttpZF/GetJS", "req_type": "get", "Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc", @@ -114,7 +133,7 @@ urls = { "is_logger": False, "is_json": False, }, - "odxmfwg": { + "odxmfwg": { # 订单页面js "req_url": "/otn/dynamicJs/odxmfwg", "req_type": "get", "Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc", @@ -125,7 +144,7 @@ urls = { "is_logger": False, "is_json": False, }, - "get_passengerDTOs": { + "get_passengerDTOs": { # 获取乘车人 "req_url": "/otn/confirmPassenger/getPassengerDTOs", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc", @@ -136,8 +155,8 @@ urls = { "is_logger": True, "is_json": True, }, - "select_url": { - "req_url": "/otn/leftTicket/queryO?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT", + "select_url": { # 查询余票 + "req_url": "/otn/leftTicket/query?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/leftTicket/init", "Host": "kyfw.12306.cn", @@ -147,7 +166,7 @@ urls = { "is_logger": False, "is_json": True, }, - "check_user_url": { + "check_user_url": { # 检查用户登录 "req_url": "/otn/login/checkUser", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/leftTicket/init", @@ -158,7 +177,7 @@ urls = { "is_logger": True, "is_json": True, }, - "submit_station_url": { + "submit_station_url": { # 提交订单 "req_url": "/otn/leftTicket/submitOrderRequest", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/leftTicket/init", @@ -169,7 +188,7 @@ urls = { "is_logger": True, "is_json": True, }, - "checkOrderInfoUrl": { + "checkOrderInfoUrl": { # 检查订单信息规范 "req_url": "/otn/confirmPassenger/checkOrderInfo", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc", @@ -180,7 +199,7 @@ urls = { "is_logger": True, "is_json": True, }, - "getQueueCountUrl": { + "getQueueCountUrl": { # 剩余余票数 "req_url": "/otn/confirmPassenger/getQueueCount", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc", @@ -191,7 +210,7 @@ urls = { "is_logger": True, "is_json": True, }, - "checkQueueOrderUrl": { + "checkQueueOrderUrl": { # 订单队列排队 "req_url": "/otn/confirmPassenger/confirmSingleForQueue", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc", @@ -202,7 +221,7 @@ urls = { "is_logger": True, "is_json": True, }, - "checkRandCodeAnsyn": { + "checkRandCodeAnsyn": { # 暂时没用到 "req_url": "/otn/passcodeNew/checkRandCodeAnsyn", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc", @@ -213,7 +232,7 @@ urls = { "is_logger": True, "is_json": True, }, - "codeImgByOrder": { + "codeImgByOrder": { # 订单页面验证码 "req_url": "/otn/passcodeNew/getPassCodeNew?module=passenger&rand=randp&%s" % random.random(), "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc", @@ -224,9 +243,9 @@ urls = { "is_logger": False, "is_json": False, }, - "queryOrderWaitTimeUrl": { - "req_url": "/otn/confirmPassenger/queryOrderWaitTime", - "req_type": "post", + "queryOrderWaitTimeUrl": { # 订单等待页面 + "req_url": "/otn/confirmPassenger/queryOrderWaitTime?random={0}&tourFlag=dc&_json_att=", + "req_type": "get", "Referer": "https://kyfw.12306.cn/otn/confirmPassenger/initDc", "Host": "kyfw.12306.cn", "re_try": 10, @@ -235,7 +254,7 @@ urls = { "is_logger": True, "is_json": True, }, - "queryMyOrderNoCompleteUrl": { + "queryMyOrderNoCompleteUrl": { # 订单查询页面 "req_url": "/otn/queryOrder/queryMyOrderNoComplete", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete", @@ -246,7 +265,7 @@ urls = { "is_logger": True, "is_json": True, }, - "initNoCompleteUrl": { + "initNoCompleteUrl": { # 获取订单列表 "req_url": "/otn/queryOrder/initNoComplete", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete", @@ -257,7 +276,7 @@ urls = { "is_logger": True, "is_json": True, }, - "cancelNoCompleteMyOrder": { + "cancelNoCompleteMyOrder": { # 取消订单 "req_url": "/otn/queryOrder/cancelNoCompleteMyOrder", "req_type": "post", "Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete", @@ -268,32 +287,35 @@ urls = { "is_logger": True, "is_json": True, }, - "autoSubmitOrderRequest": { + "autoSubmitOrderRequest": { # 快速自动提交订单 "req_url": "/otn/confirmPassenger/autoSubmitOrderRequest", "req_type": "post", - "Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete", + "Referer": "https://kyfw.12306.cn/otn/leftTicket/init", "Host": "kyfw.12306.cn", + "Content-Type": 1, "re_try": 10, "re_time": 0.1, "s_time": 0.1, "is_logger": True, "is_json": True, }, - "getQueueCountAsync": { + "getQueueCountAsync": { # 快速获取订单数据 "req_url": "/otn/confirmPassenger/getQueueCountAsync", "req_type": "post", - "Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete", + "Referer": "https://kyfw.12306.cn/otn/leftTicket/init", "Host": "kyfw.12306.cn", + "Content-Type": 1, "re_try": 10, "re_time": 0.1, "s_time": 0.1, "is_logger": True, "is_json": True, }, - "confirmSingleForQueueAsys": { + "confirmSingleForQueueAsys": { # 快速订单排队 "req_url": "/otn/confirmPassenger/confirmSingleForQueueAsys", "req_type": "post", - "Referer": "https://kyfw.12306.cn/otn/queryOrder/initNoComplete", + "Referer": "https://kyfw.12306.cn/otn/leftTicket/init", + "Content-Type": 1, "Host": "kyfw.12306.cn", "re_try": 10, "re_time": 0.1, diff --git a/damatuCode/__init__.py b/damatuCode/__init__.py old mode 100644 new mode 100755 diff --git a/damatuCode/damatuWeb.py b/damatuCode/damatuWeb.py old mode 100644 new mode 100755 diff --git a/damatuCode/ruokuai.py b/damatuCode/ruokuai.py old mode 100644 new mode 100755 diff --git a/init/SelectTicketInfoFast.py b/init/SelectTicketInfoFast.py new file mode 100755 index 0000000..49cb19b --- /dev/null +++ b/init/SelectTicketInfoFast.py @@ -0,0 +1,293 @@ +# -*- coding=utf-8 -*- +import datetime +import json +import random +import re +import socket +import sys +import threading +import time +import urllib +from collections import OrderedDict + +import collections + +from agency.cdn_utils import CDNProxy +from config import urlConf +from config.emailConf import sendEmail +from config.ticketConf import _get_yaml +from init import login +from init.login import GoLogin +from inter.AutoSubmitOrderRequest import autoSubmitOrderRequest +from inter.ConfirmSingleForQueueAsys import confirmSingleForQueueAsys +from inter.GetPassengerDTOs import getPassengerDTOs +from inter.GetQueueCountAsync import getQueueCountAsync +from inter.LiftTicketInit import liftTicketInit +from inter.Query import query +from inter.QueryOrderWaitTime import queryOrderWaitTime +from myException.PassengerUserException import PassengerUserException +from myException.UserPasswordException import UserPasswordException +from myException.ticketConfigException import ticketConfigException +from myException.ticketIsExitsException import ticketIsExitsException +from myException.ticketNumOutException import ticketNumOutException +from myUrllib.httpUtils import HTTPClient + +reload(sys) +sys.setdefaultencoding('utf-8') + + +class selectFast: + """ + 快速提交车票通道 + """ + + 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.httpClint = HTTPClient() + self.urls = urlConf.urls + self.login = GoLogin(self.httpClint, self.urls, self.is_aotu_code, self.aotu_code_type) + self.is_download_img = False + self.cdn_list = [] + self.is_check_user = dict() + self.ticket_black_list = dict() + self.black_train_no = "" + 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"] + 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刷新间隔:随机(1-4S)\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 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 check_user(self): + """ + 检查用户是否达到订票条件 + :return: + """ + check_user_url = self.urls["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 main(self): + l = liftTicketInit(session=self) + l.reqLiftTicketInit() + self.call_login() + self.check_user() + from_station, to_station = self.station_table(self.from_station, self.to_station) + passengerTicketStrList, oldPassengerStr, set_type = "", "", "" + 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 "06:00:00" < time.strftime('%H:%M:%S', time.localtime(time.time())) < "23:00:00": + print(u"休息时间已过,重新开启检票功能") + 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, + black_train_no=self.black_train_no) + queryResult = q.sendQuery() + self.black_train_no = "" # 重置小黑屋名单 + # 查询接口 + if queryResult.get("status", False): + secretStr = queryResult.get("secretStr", "") + train_no = queryResult.get("train_no", "") + stationTrainCode = queryResult.get("stationTrainCode", "") + train_date = queryResult.get("train_date", "") + query_from_station_name = queryResult.get("query_from_station_name", "") + query_to_station_name = queryResult.get("query_to_station_name", "") + set_type = queryResult.get("set_type", "") + leftTicket = queryResult.get("leftTicket", "") + 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)) + 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", "") + # 提交订单 + a = autoSubmitOrderRequest(session=self, + secretStr=secretStr, + train_date=train_date, + query_from_station_name=self.from_station, + query_to_station_name=self.to_station, + passengerTicketStr=self.passengerTicketStrList, + oldPassengerStr=self.oldPassengerStr + ) + submitResult = a.sendAutoSubmitOrderRequest() + if submitResult.get("status", False): + result = submitResult.get("result", "") + # 订单排队 + time.sleep(submitResult.get("ifShowPassCodeTime", 1)) + g = getQueueCountAsync(session=self, + train_no=train_no, + stationTrainCode=stationTrainCode, + fromStationTelecode=query_from_station_name, + toStationTelecode=query_to_station_name, + leftTicket=leftTicket, + set_type=set_type, + users=len(self.ticke_peoples), + ) + getQueueCountAsyncResult = g.sendGetQueueCountAsync() + time.sleep(submitResult.get("ifShowPassCodeTime", 1)) + if getQueueCountAsyncResult.get("is_black", False): + self.black_train_no = getQueueCountAsyncResult.get("train_no", "") + if getQueueCountAsyncResult.get("status", False): + # 请求订单快读接口 + c = confirmSingleForQueueAsys(session=self, + passengerTicketStr=self.passengerTicketStrList, + oldPassengerStr=self.oldPassengerStr, + result=result, ) + confirmSingleForQueueAsysResult = c.sendConfirmSingleForQueueAsys() + # 排队 + if confirmSingleForQueueAsysResult.get("status", False): + qwt = queryOrderWaitTime(session=self) + qwt.sendQueryOrderWaitTime() + else: + self.httpClint.del_cookies() + + else: + s_time = random.randint(0, 4) + time.sleep(s_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), + s_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) + + +if __name__ == '__main__': + s = selectFast() + s.main() + # a = select('上海', '北京') + # a.main() diff --git a/init/__init__.py b/init/__init__.py old mode 100644 new mode 100755 diff --git a/init/login.py b/init/login.py old mode 100644 new mode 100755 index c66ee55..ccdd82f --- a/init/login.py +++ b/init/login.py @@ -216,10 +216,14 @@ class GoLogin: login_num = 0 while True: self.cookietp() - self.httpClint.set_cookies(_jc_save_showIns="true", - _jc_save_wfdc_flag="dc", - _jc_save_fromDate=_get_yaml()["set"]["station_dates"][0], - _jc_save_toDate=_get_yaml()["set"]["station_dates"][0]) + # self.httpClint.set_cookies(_jc_save_showIns="true", + # _jc_save_wfdc_flag="dc", + # _jc_save_toDate="2018-06-06", + # _jc_save_fromDate=_get_yaml()["set"]["station_dates"][0], + # RAIL_EXPIRATION="1528337042724", + # RAIL_DEVICEID="O6DFHLmFChFrZUI7QyY9xcqj94eZG9JH_kD3zSZt53tkCUq0uqdvlo1fm_CmNxr_QAnMOU79JmHI8jbtj2vaNUnOZKCqcsMNbhCaoDIB3vxgsyzMMGOZF-CknXKEFaCLPGyDNXEknPDs7xgSbanwKqsiSRT41xti", + # + # ) self.urlConf["getCodeImg"]["req_url"] = self.urlConf["getCodeImg"]["req_url"].format(random.random()) self.readImg(self.urlConf["getCodeImg"]) self.randCode = self.getRandCode() diff --git a/init/select_ticket_info.py b/init/select_ticket_info.py old mode 100644 new mode 100755 index 4473414..f670ac3 --- a/init/select_ticket_info.py +++ b/init/select_ticket_info.py @@ -43,6 +43,7 @@ class select: self.user_info = "" self.secretStr = "" self.ticket_black_list = dict() + self.ticket_black_list_time = dict() self.is_check_user = dict() self.httpClint = HTTPClient() self.confUrl = urlConf.urls @@ -204,7 +205,7 @@ class select: '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'][ + if 'data' in jsonData and jsonData['data'] and 'l' 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] @@ -337,7 +338,7 @@ class select: """ 获取getPassengerTicketStr 提交对应的代号码 :param str: 坐席 - :return: + :return: """ passengerTicketStr = { '一等座': 'M', @@ -581,7 +582,7 @@ class select: elif "waitTime"in queryOrderWaitTimeResult["data"] and queryOrderWaitTimeResult["data"]["waitTime"]: print(u"排队等待时间预计还剩 {0} ms".format(0-queryOrderWaitTimeResult["data"]["waitTime"])) else: - print ("正在等待中") + print (u"正在等待中") elif "messages" in queryOrderWaitTimeResult and queryOrderWaitTimeResult["messages"]: print(u"排队等待失败: " + queryOrderWaitTimeResult["messages"]) else: @@ -732,7 +733,8 @@ class select: 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, + (datetime.datetime.now()-start_time).microseconds/1000, + self.httpClint.cdn, len(self.cdn_list)) self.set_cdn() except PassengerUserException as e: diff --git a/inter/AutoSubmitOrderRequest.py b/inter/AutoSubmitOrderRequest.py new file mode 100644 index 0000000..f9a7053 --- /dev/null +++ b/inter/AutoSubmitOrderRequest.py @@ -0,0 +1,108 @@ +# coding=utf-8 +import urllib +from collections import OrderedDict + +from config.TicketEnmu import ticket + + +class autoSubmitOrderRequest: + """ + 快读提交订单通道 + """ + def __init__(self, session, + secretStr, + train_date, + query_from_station_name, + query_to_station_name, + passengerTicketStr, + oldPassengerStr): + self.secretStr = urllib.unquote(secretStr) + self.train_date = train_date + self.query_from_station_name = query_from_station_name + self.query_to_station_name = query_to_station_name + self.passengerTicketStr = passengerTicketStr + self.oldPassengerStr = oldPassengerStr + self.session = session + + def data_par(self): + """ + 参数结构 + 自动提交代码接口-autoSubmitOrderRequest + - 字段说明 + - secretStr 车票代码 + - train_date 乘车日期 + - tour_flag 乘车类型 + - purpose_codes 学生还是成人 + - query_from_station_name 起始车站 + - query_to_station_name 结束车站 + - cancel_flag 默认2,我也不知道干嘛的 + - bed_level_order_num 000000000000000000000000000000 + - passengerTicketStr 乘客乘车代码 + - oldPassengerStr 乘客编号代码 + :return: + """ + data = OrderedDict() + data["secretStr"] = self.secretStr + data["train_date"] = self.train_date + data["tour_flag"] = "dc" + data["purpose_codes"] = "ADULT" + data["query_from_station_name"] = self.query_from_station_name + data["query_to_station_name"] = self.query_to_station_name + data["cancel_flag"] = 2 + data["bed_level_order_num"] = "000000000000000000000000000000" + data["passengerTicketStr"] = self.passengerTicketStr + data["oldPassengerStr"] = self.oldPassengerStr + return data + + def sendAutoSubmitOrderRequest(self): + """ + 请求下单接口 + :return: + """ + urls = self.session.urls["autoSubmitOrderRequest"] + data = self.data_par() + autoSubmitOrderRequestResult = self.session.httpClint.send(urls, data) + if autoSubmitOrderRequestResult and \ + autoSubmitOrderRequestResult.get("status", False) and\ + autoSubmitOrderRequestResult.get("httpstatus", False) == 200: + requestResultData = autoSubmitOrderRequestResult.get("data", {}) + if requestResultData: + result = requestResultData.get("result", "") + ifShowPassCode = requestResultData.get("ifShowPassCode", "N") + print(ticket.AUTO_SUBMIT_ORDER_REQUEST_C) + if ifShowPassCode == "Y": # 如果需要验证码 + print(ticket.AUTO_SUBMIT_NEED_CODE) + return { + "result": result, + "ifShowPassCode": ifShowPassCode, + "code": ticket.SUCCESS_CODE, + "ifShowPassCodeTime": requestResultData.get("requestResultData", 2000) / float(1000), + "status": True, + } + else: + print(ticket.AUTO_SUBMIT_NOT_NEED_CODE) + return { + "result": result, + "ifShowPassCode": ifShowPassCode, + "code": ticket.SUCCESS_CODE, + "ifShowPassCodeTime": requestResultData.get("requestResultData", 2000) / float(1000), + "status": True, + } + else: + print(ticket.AUTO_SUBMIT_ORDER_REQUEST_F) + if autoSubmitOrderRequestResult.get("messages", ""): + print(autoSubmitOrderRequestResult.get("messages", "")) + return { + "code": ticket.FAIL_CODE, + "status": False, + } + elif autoSubmitOrderRequestResult.get("validateMessages", ""): + print(autoSubmitOrderRequestResult.get("validateMessages", "")) + return { + "code": ticket.FAIL_CODE, + "status": False, + } + + + + diff --git a/inter/ConfirmSingleForQueueAsys.py b/inter/ConfirmSingleForQueueAsys.py new file mode 100644 index 0000000..0499dc6 --- /dev/null +++ b/inter/ConfirmSingleForQueueAsys.py @@ -0,0 +1,78 @@ +# coding=utf-8 +import json +import urllib +from collections import OrderedDict + + +class confirmSingleForQueueAsys: + """ + 订单快读排队 + """ + def __init__(self, + session, + passengerTicketStr, + oldPassengerStr, + result, + randCode="", + ): + self.session = session + self.passengerTicketStr = passengerTicketStr + self.oldPassengerStr = oldPassengerStr + self.result = result if isinstance(result, str) else str(result) + self.randCode = randCode + + def data_par(self): + """ + 字段说明 + passengerTicketStr 乘客乘车代码 + oldPassengerStr 乘客编号代码 + randCode 填空 + purpose_codes 学生还是成人 + key_check_isChange autoSubmitOrderRequest返回的result字段做切割即可 + leftTicketStr autoSubmitOrderRequest返回的result字段做切割即可 + train_location autoSubmitOrderRequest返回的result字段做切割即可 + choose_seats + seatDetailType + _json_att + :return: + """ + results = self.result.split("#") + key_check_isChange = results[1] + leftTicketStr = results[2] + train_location = results[0] + data = OrderedDict() + data["passengerTicketStr"] = self.passengerTicketStr + data["oldPassengerStr"] = self.oldPassengerStr + data["randCode"] = self.randCode + data["purpose_codes"] = "ADULT" + data["key_check_isChange"] = key_check_isChange + data["leftTicketStr"] = leftTicketStr + data["train_location"] = train_location + data["choose_seats"] = "" + data["seatDetailType"] = "" + data["_json_att"] = "" + return data + + def sendConfirmSingleForQueueAsys(self): + """ + 请求订单快读排队接口 + :return: + """ + urls = self.session.urls["confirmSingleForQueueAsys"] + data = self.data_par() + confirmSingleForQueueAsysResult = self.session.httpClint.send(urls, data) + if confirmSingleForQueueAsysResult.get("status", False) and confirmSingleForQueueAsysResult.get("data", False): + queueData = confirmSingleForQueueAsysResult.get("data", {}) + if queueData.get("submitStatus", False): + return { + "status": True + } + else: + print(queueData.get("errMsg", "")) + return { + "status": False + } + else: + return { + "status": False + } \ No newline at end of file diff --git a/inter/GetPassengerDTOs.py b/inter/GetPassengerDTOs.py new file mode 100644 index 0000000..a50c572 --- /dev/null +++ b/inter/GetPassengerDTOs.py @@ -0,0 +1,92 @@ +# coding=utf-8 +from config.TicketEnmu import ticket +from myException.PassengerUserException import PassengerUserException + + +class getPassengerDTOs: + """ + 获取乘客信息 + :return: + """ + def __init__(self, session, ticket_peoples, set_type): + """ + :param session: 登录实例 + :param ticket_peoples: 乘客 + :param set_type: 坐席 + """ + self.session = session + self.ticket_peoples = ticket_peoples + self.set_type = set_type.encode("utf8") + + def sendGetPassengerDTOs(self): + getPassengerDTOsResult = self.session.httpClint.send(self.session.urls["get_passengerDTOs"], {}) + getPassengerDTOsResult["data"].get("normal_passengers", False) + if getPassengerDTOsResult.get("data", False) and getPassengerDTOsResult["data"].get("normal_passengers", False): + normal_passengers = getPassengerDTOsResult['data']['normal_passengers'] + _normal_passenger = [normal_passengers[i] for i in range(len(normal_passengers)) if + normal_passengers[i]["passenger_name"] in self.ticket_peoples] + return _normal_passenger if _normal_passenger else [normal_passengers[0]] # 如果配置乘车人没有在账号,则默认返回第一个用户 + else: + if getPassengerDTOsResult.get("data", False) and getPassengerDTOsResult['data'].get("exMsg", False): + print(getPassengerDTOsResult['data'].get("exMsg", False)) + elif getPassengerDTOsResult.get('messages', False): + print(getPassengerDTOsResult.get('messages', False)) + else: + raise PassengerUserException(ticket.DTO_NOT_FOUND) + + def getPassengerTicketStr(self, set_type): + """ + 获取getPassengerTicketStr 提交对应的代号码 + :param str: 坐席 + :return: + """ + passengerTicketStr = { + '一等座': 'M', + '特等座': 'P', + '二等座': 'O', + '商务座': 9, + '硬座': 1, + '无座': 1, + '软卧': 4, + '硬卧': 3, + } + return str(passengerTicketStr[set_type.replace(' ', '')]) + + 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 = [] + user_info = self.sendGetPassengerDTOs() + set_type = self.getPassengerTicketStr(self.set_type) + if not user_info: + raise PassengerUserException(ticket.DTO_NOT_IN_LIST) + if len(user_info) is 1: + passengerTicketStrList.append( + '0,' + user_info[0]['passenger_type'] + "," + user_info[0][ + "passenger_name"] + "," + + user_info[0]['passenger_id_type_code'] + "," + user_info[0]['passenger_id_no'] + "," + + user_info[0]['mobile_no'] + ',N') + oldPassengerStr.append( + user_info[0]['passenger_name'] + "," + user_info[0]['passenger_id_type_code'] + "," + + user_info[0]['passenger_id_no'] + "," + user_info[0]['passenger_type'] + '_') + else: + for i in xrange(len(user_info)): + passengerTicketStrList.append( + '0,' + user_info[i]['passenger_type'] + "," + user_info[i][ + "passenger_name"] + "," + user_info[i]['passenger_id_type_code'] + "," + user_info[i][ + 'passenger_id_no'] + "," + user_info[i]['mobile_no'] + ',N_' + set_type) + oldPassengerStr.append( + user_info[i]['passenger_name'] + "," + user_info[i]['passenger_id_type_code'] + "," + + user_info[i]['passenger_id_no'] + "," + user_info[i]['passenger_type'] + '_') + return { + "passengerTicketStrList": set_type + "," + ",".join(passengerTicketStrList), + "oldPassengerStr": "".join(oldPassengerStr), + "code": ticket.SUCCESS_CODE, + "set_type": set_type, + "status": True, + } diff --git a/inter/GetQueueCountAsync.py b/inter/GetQueueCountAsync.py new file mode 100644 index 0000000..040810f --- /dev/null +++ b/inter/GetQueueCountAsync.py @@ -0,0 +1,102 @@ +# coding=utf-8 +import time +from collections import OrderedDict + +from config.TicketEnmu import ticket + + +class getQueueCountAsync: + """ + 排队 + """ + def __init__(self, + session, + train_no, + stationTrainCode, + fromStationTelecode, + toStationTelecode, + leftTicket, + set_type, + users,): + self.train_no = train_no + self.session = session + self.stationTrainCode = stationTrainCode + self.fromStationTelecode = fromStationTelecode + self.toStationTelecode = toStationTelecode + self.set_type = set_type + self.leftTicket = leftTicket + self.users = users + + def data_par(self): + """ + - 字段说明 + - train_date 时间 + - train_no 列车编号,查询代码里面返回 + - stationTrainCode 列车编号 + - seatType 对应坐席 + - fromStationTelecode 起始城市 + - toStationTelecode 到达城市 + - leftTicket 查询代码里面返回 + - purpose_codes 学生还是成人 + - _json_att 没啥卵用,还是带上吧 + :return: + """ + l_time = time.localtime(time.time()) + new_train_date = time.strftime("%b %d %Y %H:%M:%S", l_time) + data = OrderedDict() + # data["train_date"] = "Fri " + str(new_train_date) + " GMT+0800 (CST)" + data["train_date"] = "Fri Jun 21 2018 18:23:54 GMT+0800 (CST)" + data["train_no"] = self.train_no + data["stationTrainCode"] = self.stationTrainCode + data["seatType"] = self.set_type + data["fromStationTelecode"] = self.fromStationTelecode + data["toStationTelecode"] = self.toStationTelecode + data["leftTicket"] = self.leftTicket + data["purpose_codes"] = "ADULT" + data["_json_att"] = "" + return data + + def conversion_int(self, str): + return int(str) + + def sendGetQueueCountAsync(self): + """ + 请求排队接口 + :return: + """ + urls = self.session.urls["getQueueCountAsync"] + data = self.data_par() + getQueueCountAsyncResult = self.session.httpClint.send(urls, data) + if getQueueCountAsyncResult.get("status", False) and getQueueCountAsyncResult.get("data", False): + if "status" in getQueueCountAsyncResult and getQueueCountAsyncResult["status"] is True: + if "countT" in getQueueCountAsyncResult["data"]: + ticket_data = getQueueCountAsyncResult["data"]["ticket"] + ticket_split = sum(map(self.conversion_int, ticket_data.split(","))) if ticket_data.find( + ",") != -1 else ticket_data + countT = getQueueCountAsyncResult["data"]["countT"] + if int(countT) is 0: + if int(ticket_split) < self.users: + print(ticket.QUEUE_TICKET_SHORT) + return {"status": False, "is_black": False} + else: + print(ticket.QUEUE_TICKET_SUCCESS.format(ticket_split)) + return {"status": True, "is_black": False} + else: + return {"status": False, "is_black": True} + else: + print(ticket.QUEUE_JOIN_BLACK.format(getQueueCountAsyncResult, self.train_no)) + return {"status": False, "is_black": True, "train_no": self.train_no} + elif "messages" in getQueueCountAsyncResult and getQueueCountAsyncResult["messages"]: + print(ticket.QUEUE_WARNING_MSG.format(getQueueCountAsyncResult["messages"][0], self.train_no)) + return {"status": False, "is_black": True, "train_no": self.train_no} + else: + if "validateMessages" in getQueueCountAsyncResult and getQueueCountAsyncResult["validateMessages"]: + print(str(getQueueCountAsyncResult["validateMessages"])) + return {"status": False, "is_black": False} + else: + return {"status": False, "is_black": False} + else: + return {"status": False, "is_black": False} + + + diff --git a/inter/LiftTicketInit.py b/inter/LiftTicketInit.py new file mode 100644 index 0000000..98c0eb4 --- /dev/null +++ b/inter/LiftTicketInit.py @@ -0,0 +1,17 @@ +# coding=utf-8 + + +class liftTicketInit: + def __init__(self, session): + self.session = session + + def reqLiftTicketInit(self): + """ + 请求抢票页面 + :return: + """ + urls = self.session.urls["left_ticket_init"] + self.session.httpClint.send(urls) + return { + "status": True + } \ No newline at end of file diff --git a/inter/Query.py b/inter/Query.py new file mode 100644 index 0000000..7c6a6e3 --- /dev/null +++ b/inter/Query.py @@ -0,0 +1,119 @@ +# coding=utf-8 +import copy +import datetime +import random +import time + +from config.TicketEnmu import ticket + + +class query: + """ + 查询接口 + """ + + def __init__(self, session, from_station, to_station, from_station_h, to_station_h, _station_seat, station_trains, + black_train_no, station_dates=None, ): + self.session = session + self.from_station = from_station + self.to_station = to_station + self.from_station_h = from_station_h + self.to_station_h = to_station_h + self.station_trains = station_trains + self._station_seat = _station_seat if isinstance(_station_seat, list) else list(_station_seat) + self.station_dates = station_dates if isinstance(station_dates, list) else list(station_dates) + self.ticket_black_list = dict() + self.black_train_no = black_train_no + + def station_seat(self, index): + """ + 获取车票对应坐席 + :return: + """ + seat = {'商务座': 32, + '一等座': 31, + '二等座': 30, + '特等座': 25, + '软卧': 23, + '硬卧': 28, + '硬座': 29, + '无座': 26, + } + return seat[index] + + def sendQuery(self): + """ + 查询 + :return: + """ + if self.black_train_no: + self.ticket_black_list[self.black_train_no] = datetime.datetime.now() + for station_date in self.station_dates: + select_url = copy.copy(self.session.urls["select_url"]) + select_url["req_url"] = select_url["req_url"].format( + station_date, self.from_station, self.to_station) + station_ticket = self.session.httpClint.send(select_url) + value = station_ticket.get("data", "") + if not value: + print (u'{0}-{1} 车次坐席查询为空'.format(self.from_station, self.to_station)) + else: + result = value.get('result', []) + if result: + for i in value['result']: + ticket_info = i.split('|') + if ticket_info[11] == "Y" and ticket_info[1].encode("utf8") == "预订": # 筛选未在开始时间内的车次 + for j in xrange(len(self._station_seat)): + is_ticket_pass = ticket_info[self.station_seat(self._station_seat[j].encode("utf8"))] + if is_ticket_pass != '' and is_ticket_pass != '无' and ticket_info[ + 3] in self.station_trains and is_ticket_pass != '*': # 过滤有效目标车次 + secretStr = ticket_info[0] + train_no = ticket_info[2] + query_from_station_name = ticket_info[6] + query_to_station_name = ticket_info[7] + train_location = ticket_info[15] + stationTrainCode = ticket_info[3] + train_date = station_date + leftTicket = ticket_info[12] + set_type = self._station_seat[j] + print (u'车次: {0} 始发车站: {1} 终点站: {2} {3}: {4}'.format(train_no, + self.from_station_h, + self.to_station_h, + self._station_seat[j].encode( + "utf8"), + ticket_info[self.station_seat( + self._station_seat[ + j].encode("utf8"))] + )) + if "train_no" in self.ticket_black_list and ( + datetime.datetime.now() - self.ticket_black_list[ + train_no]).seconds / 60 < int(ticket.TICKET_BLACK_LIST_TIME): + print(ticket.QUERY_IN_BLACK_LIST.format(train_no)) + break + else: + print (ticket.QUERY_C) + # self.buy_ticket_time = datetime.datetime.now() + return { + "secretStr": secretStr, + "train_no": train_no, + "stationTrainCode": stationTrainCode, + "train_date": train_date, + "query_from_station_name": query_from_station_name, + "query_to_station_name": query_to_station_name, + # "buy_ticket_time": self.buy_ticket_time, + "set_type": set_type, + "leftTicket": leftTicket, + "train_location": train_location, + "code": ticket.SUCCESS_CODE, + "status": True, + } + else: + pass + else: + pass + else: + print u"车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket) + return {"code": ticket.FAIL_CODE, "status": False} + + +if __name__ == "__main__": + q = query() diff --git a/inter/QueryOrderWaitTime.py b/inter/QueryOrderWaitTime.py new file mode 100644 index 0000000..b93b221 --- /dev/null +++ b/inter/QueryOrderWaitTime.py @@ -0,0 +1,123 @@ +# coding=utf-8 +import copy +import time + +from config.TicketEnmu import ticket +from config.emailConf import sendEmail +from myException.ticketIsExitsException import ticketIsExitsException +from myException.ticketNumOutException import ticketNumOutException + + +class queryOrderWaitTime: + """ + 排队 + """ + + def __init__(self, session): + self.session = session + + def sendQueryOrderWaitTime(self): + """ + 排队获取订单等待信息,每隔3秒请求一次,最高请求次数为20次! + :return: + """ + num = 1 + while True: + num += 1 + if num > ticket.OUT_NUM: + print(ticket.WAIT_OUT_NUM) + order_id = self.queryMyOrderNoComplete() # 排队失败,自动取消排队订单 + if order_id: + self.cancelNoCompleteMyOrder(order_id) + break + try: + queryOrderWaitTimeUrl = copy.deepcopy(self.session.urls["queryOrderWaitTimeUrl"]) + queryOrderWaitTimeUrl["req_url"] = queryOrderWaitTimeUrl["req_url"].format(int(round(time.time() * 1000))) + queryOrderWaitTimeResult = self.session.httpClint.send(queryOrderWaitTimeUrl) + except ValueError: + queryOrderWaitTimeResult = {} + if queryOrderWaitTimeResult: + if queryOrderWaitTimeResult.get("status", False): + data = queryOrderWaitTimeResult.get("data", False) + if data and data.get("orderId", ""): + sendEmail(ticket.WAIT_ORDER_SUCCESS.format( + data.get("orderId", ""))) + raise ticketIsExitsException(ticket.WAIT_ORDER_SUCCESS.format( + data.get("orderId"))) + elif data.get("msg", False): + print data.get("msg", "") + break + elif data.get("waitTime", False): + print(ticket.WAIT_ORDER_CONTINUE.format(0 - data.get("waitTime", False))) + else: + pass + elif queryOrderWaitTimeResult.get("messages", False): + print(ticket.WAIT_ORDER_FAIL.format(queryOrderWaitTimeResult.get("messages", ""))) + else: + print(ticket.WAIT_ORDER_NUM.format(num + 1)) + else: + pass + time.sleep(2) + else: + print(ticketNumOutException(ticket.WAIT_ORDER_SUB_FAIL)) + + def queryMyOrderNoComplete(self): + """ + 获取订单列表信息 + :return: + """ + self.initNoComplete() + queryMyOrderNoCompleteUrl = self.session.urls["queryMyOrderNoCompleteUrl"] + data = {"_json_att": ""} + try: + queryMyOrderNoCompleteResult = self.session.httpClint.send(queryMyOrderNoCompleteUrl, data) + except ValueError: + queryMyOrderNoCompleteResult = {} + if queryMyOrderNoCompleteResult: + if queryMyOrderNoCompleteResult.get("data", False) and queryMyOrderNoCompleteResult["data"].get("orderDBList", False): + orderId = queryMyOrderNoCompleteResult["data"]["orderDBList"][0]["sequence_no"] + return orderId + elif queryMyOrderNoCompleteResult.get("data", False) and queryMyOrderNoCompleteResult["data"].get("orderCacheDTO", False): + if queryMyOrderNoCompleteResult["data"]["orderCacheDTO"].get("message", False): + print(queryMyOrderNoCompleteResult["data"]["orderCacheDTO"]["message"]["message"]) + raise ticketNumOutException( + queryMyOrderNoCompleteResult["data"]["orderCacheDTO"]["message"]["message"]) + else: + if queryMyOrderNoCompleteResult.get("message", False): + print queryMyOrderNoCompleteResult.get("message", False) + return False + else: + return False + else: + print(u"接口 {} 无响应".format(queryMyOrderNoCompleteUrl)) + + def initNoComplete(self): + """ + 获取订单前需要进入订单列表页,获取订单列表页session + :return: + """ + self.session.httpClint.set_cookies(acw_tc="AQAAAEnFJnekLwwAtGHjZZCr79B6dpXk", current_captcha_type="Z") + initNoCompleteUrl = self.session.urls["initNoCompleteUrl"] + data = {"_json_att": ""} + self.session.httpClint.send(initNoCompleteUrl, data) + + def cancelNoCompleteMyOrder(self, sequence_no): + """ + 取消订单 + :param sequence_no: 订单编号 + :return: + """ + cancelNoCompleteMyOrderUrl = self.session.urls["cancelNoCompleteMyOrder"] + cancelNoCompleteMyOrderData = { + "sequence_no": sequence_no, + "cancel_flag": "cancel_order", + "_json_att": "" + } + cancelNoCompleteMyOrderResult = self.session.httpClint.send(cancelNoCompleteMyOrderUrl, + cancelNoCompleteMyOrderData) + if cancelNoCompleteMyOrderResult.get("data", False) and cancelNoCompleteMyOrderResult["data"].get("existError", "N"): + print(ticket.CANCEL_ORDER_SUCCESS.format(sequence_no)) + time.sleep(2) + return True + else: + print(ticket.CANCEL_ORDER_FAIL.format(sequence_no)) diff --git a/inter/__init__.py b/inter/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/myException/PassengerUserException.py b/myException/PassengerUserException.py old mode 100644 new mode 100755 diff --git a/myException/UserPasswordException.py b/myException/UserPasswordException.py old mode 100644 new mode 100755 diff --git a/myException/__init__.py b/myException/__init__.py old mode 100644 new mode 100755 diff --git a/myException/balanceException.py b/myException/balanceException.py old mode 100644 new mode 100755 diff --git a/myException/ticketConfigException.py b/myException/ticketConfigException.py old mode 100644 new mode 100755 diff --git a/myException/ticketIsExitsException.py b/myException/ticketIsExitsException.py old mode 100644 new mode 100755 diff --git a/myException/ticketNumOutException.py b/myException/ticketNumOutException.py old mode 100644 new mode 100755 diff --git a/myUrllib/__init__.py b/myUrllib/__init__.py old mode 100644 new mode 100755 diff --git a/myUrllib/httpUtils.py b/myUrllib/httpUtils.py old mode 100644 new mode 100755 index 0a4a2f4..a3c1ae3 --- a/myUrllib/httpUtils.py +++ b/myUrllib/httpUtils.py @@ -1,6 +1,8 @@ # -*- coding: utf8 -*- import json import socket +import urllib +from collections import OrderedDict from time import sleep import requests @@ -8,6 +10,51 @@ import requests from config import logger +def _set_header_default(): + header_dict = OrderedDict() + header_dict["Host"] = "kyfw.12306.cn" + header_dict["Connection"] = "keep-alive" + header_dict["Accept"] = "application/json, text/javascript, */*; q=0.01" + header_dict["Origin"] = "https://kyfw.12306.cn" + header_dict["X-Requested-With"] = "XMLHttpRequest" + header_dict[ + "User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" + header_dict["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8" + header_dict["Referer"] = "https://kyfw.12306.cn/otn/leftTicket/init" + header_dict["Accept-Encoding"] = "gzip, deflate, br" + header_dict["Accept-Language"] = "zh-CN,zh;q=0.9,en;q=0.8" + return header_dict + + +def _set_header_j(): + """设置header""" + return { + "Content-Type": "application/json; charset=UTF-8", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5", + "Accept": "application/json, text/javascript, */*; q=0.01", + "Referer": "https://kyfw.12306.cn/otn/leftTicket/init", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", + "Origin": "https://kyfw.12306.cn", + "Connection": "keep-alive", + } + + +def _set_header_x(): + """设置header""" + return { + "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", + "X-Requested-With": "XMLHttpRequest", + "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5", + "Accept": "application/json, text/javascript, */*; q=0.01", + "Referer": "https://kyfw.12306.cn/otn/leftTicket/init", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8", + "Origin": "https://kyfw.12306.cn", + "Connection": "keep-alive", + } + + class HTTPClient(object): def __init__(self): @@ -20,7 +67,7 @@ class HTTPClient(object): def initS(self): self._s = requests.Session() - self._s.headers.update(self._set_header()) + self._s.headers.update(_set_header_j()) return self def set_cookies(self, **kwargs): @@ -46,27 +93,16 @@ class HTTPClient(object): """ self._s.cookies.set(key, None) - def _set_header(self): - """设置header""" - return { - "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", - "X-Requested-With": "application/json, text/javascript, */*; q=0.01", - "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0.1 Safari/604.3.5", - "Referer": "https://kyfw.12306.cn/otn/login/init", - "Accept": "*/*", - "Accept-Encoding": "br, gzip, deflate", - "Origin": "https://kyfw.12306.cn", - "Accept-Language": "zh-cn", - "Connection": "keep-alive", - } - def setHeaders(self, headers): self._s.headers.update(headers) return self - def resetHeaders(self): + def resetHeaders(self, header_type): self._s.headers.clear() - self._s.headers.update(self._set_header()) + if header_type == 1: + self._s.headers.update(_set_header_x()) + else: + self._s.headers.update(_set_header_j()) def getHeadersHost(self): return self._s.headers["Host"] @@ -101,31 +137,43 @@ class HTTPClient(object): def send(self, urls, data=None, **kwargs): """send request to url.If response 200,return response, else return None.""" allow_redirects = False - is_logger = urls["is_logger"] + is_logger = urls.get("is_logger", False) + req_url = urls.get("req_url", "") + re_try = urls.get("re_try", 0) + s_time = urls.get("s_time", 0) + contentType = urls.get("Content-Type", 0) error_data = {"code": 99999, "message": u"重试次数达到上限"} - self.setHeadersReferer(urls["Referer"]) if data: method = "post" self.setHeaders({"Content-Length": "{0}".format(len(data))}) else: method = "get" - self.resetHeaders() + self.resetHeaders(contentType) + self.setHeadersReferer(urls["Referer"]) if is_logger: logger.log( - u"url: {0}\n入参: {1}\n请求方式: {2}\n".format(urls["req_url"],data,method,)) + u"url: {0}\n入参: {1}\n请求方式: {2}\n".format(req_url, data, method, )) self.setHeadersHost(urls["Host"]) if self.cdn: url_host = self.cdn else: url_host = urls["Host"] - for i in range(urls["re_try"]): + if contentType == 1: + # 普通from表单 + self.resetHeaders(contentType) + if method == "post": + pass + data = urllib.urlencode(data) + elif contentType == 0: + self.resetHeaders(contentType) + for i in range(re_try): try: # sleep(urls["s_time"]) if "s_time" in urls else sleep(0.001) - sleep(urls.get("s_time", 0.001)) + sleep(s_time) requests.packages.urllib3.disable_warnings() response = self._s.request(method=method, timeout=2, - url="https://" + url_host + urls["req_url"], + url="https://" + url_host + req_url, data=data, allow_redirects=allow_redirects, verify=False, @@ -135,7 +183,7 @@ class HTTPClient(object): if is_logger: logger.log( u"出参:{0}".format(response.content)) - return json.loads(response.content) if method == "post" else response.content + return json.loads(response.content) if urls["is_json"] else response.content else: logger.log( u"url: {} 返回参数为空".format(urls["req_url"])) diff --git a/myUrllib/myurllib2.py b/myUrllib/myurllib2.py old mode 100644 new mode 100755 diff --git a/requirements.txt b/requirements.txt old mode 100644 new mode 100755 diff --git a/run.py b/run.py old mode 100644 new mode 100755 index 69eb9dd..61d0f07 --- a/run.py +++ b/run.py @@ -1,10 +1,11 @@ # -*- coding=utf-8 -*- -from init import login, select_ticket_info +from init import login, select_ticket_info, SelectTicketInfoFast def run(): # login.main() - select_ticket_info.select().main() + SelectTicketInfoFast.selectFast().main() + # select_ticket_info.select().main() if __name__ == '__main__': diff --git a/station_name.txt b/station_name.txt old mode 100644 new mode 100755 diff --git a/tkcode b/tkcode old mode 100644 new mode 100755 index e69de29..ce239c2 Binary files a/tkcode and b/tkcode differ diff --git a/tmp/__init__.py b/tmp/__init__.py old mode 100644 new mode 100755 diff --git a/tmp/log/__init__.py b/tmp/log/__init__.py old mode 100644 new mode 100755 diff --git a/uml/uml.png b/uml/uml.png old mode 100644 new mode 100755