294 lines
15 KiB
Python
Executable File
294 lines
15 KiB
Python
Executable File
# -*- 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()
|