mirror of https://github.com/testerSunshine/12306
parent
75f88a4c1a
commit
cf2e8f8ef6
|
@ -58,6 +58,9 @@
|
||||||
- 测试邮箱是否可用
|
- 测试邮箱是否可用
|
||||||
- 测试下单接口是否可用,有两个下单接口,随便用哪个都ok
|
- 测试下单接口是否可用,有两个下单接口,随便用哪个都ok
|
||||||
- 如果下载验证码过期或者下载失败的问题,应该是12306封ip的策略,多重试几次,12306现在封服务器(阿里云和腾讯云)ip比较严重,尽量不要放在服务器里面
|
- 如果下载验证码过期或者下载失败的问题,应该是12306封ip的策略,多重试几次,12306现在封服务器(阿里云和腾讯云)ip比较严重,尽量不要放在服务器里面
|
||||||
|
- 感谢一下小伙伴对本项目提供的帮助
|
||||||
|
- @读,◢
|
||||||
|
- @才
|
||||||
- [更新日志](Update.md)
|
- [更新日志](Update.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -123,3 +123,8 @@
|
||||||
- 优化随机查询1-3秒,经测试很稳定,不会封ip
|
- 优化随机查询1-3秒,经测试很稳定,不会封ip
|
||||||
- 增加余票不足优先提交功能(当余票小于乘车人,如果选择优先提交,则删减联系人和余票数一致在提交)
|
- 增加余票不足优先提交功能(当余票小于乘车人,如果选择优先提交,则删减联系人和余票数一致在提交)
|
||||||
- 开关为ticket_config.yaml配置文件中is_more_ticket参数
|
- 开关为ticket_config.yaml配置文件中is_more_ticket参数
|
||||||
|
|
||||||
|
- 2018.12.26更新
|
||||||
|
- 优化已知bug
|
||||||
|
- 开启cdn查询
|
||||||
|
- 自动识别查询接口
|
||||||
|
|
|
@ -50,8 +50,15 @@ class CDNProxy:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def open_cdn_file(self):
|
def open_cdn_file(self):
|
||||||
f = open("./cdn_list", "a+")
|
cdn = []
|
||||||
return f
|
cdn_re = re.compile("CONNECT (\S+) HTTP/1.1")
|
||||||
|
with open("./cdn_list", "r") as f:
|
||||||
|
for i in f.readlines():
|
||||||
|
# print(i.replace("\n", ""))
|
||||||
|
cdn_list = re.findall(cdn_re, i)
|
||||||
|
if cdn_list and "kyfw.12306.cn:443" not in cdn_list:
|
||||||
|
cdn.append(cdn_list[0].split(":")[0])
|
||||||
|
return cdn
|
||||||
|
|
||||||
def get_cdn_list(self):
|
def get_cdn_list(self):
|
||||||
"""
|
"""
|
||||||
|
@ -101,9 +108,6 @@ class CDNProxy:
|
||||||
print(cdn_ip[0])
|
print(cdn_ip[0])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
cdn = CDNProxy()
|
cdn = CDNProxy()
|
||||||
cdn.get_cdn_list()
|
cdn.open_cdn_file()
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -77,6 +77,18 @@ urls = {
|
||||||
"is_logger": False,
|
"is_logger": False,
|
||||||
"is_json": False,
|
"is_json": False,
|
||||||
},
|
},
|
||||||
|
"loginInitCdn": { # 登录页面
|
||||||
|
"req_url": "/otn/login/init",
|
||||||
|
"req_type": "get",
|
||||||
|
"Referer": "https://kyfw.12306.cn/otn/index/init",
|
||||||
|
"Host": "kyfw.12306.cn",
|
||||||
|
"re_try": 1,
|
||||||
|
"re_time": 0.1,
|
||||||
|
"s_time": 0.1,
|
||||||
|
"is_logger": False,
|
||||||
|
"is_test_cdn": True,
|
||||||
|
"is_json": False,
|
||||||
|
},
|
||||||
"getUserInfo": { # 获取用户信息
|
"getUserInfo": { # 获取用户信息
|
||||||
"req_url": "/otn/index/initMy12306",
|
"req_url": "/otn/index/initMy12306",
|
||||||
"req_type": "get",
|
"req_type": "get",
|
||||||
|
@ -156,7 +168,7 @@ urls = {
|
||||||
"is_json": True,
|
"is_json": True,
|
||||||
},
|
},
|
||||||
"select_url": { # 查询余票
|
"select_url": { # 查询余票
|
||||||
"req_url": "/otn/leftTicket/queryX?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT",
|
"req_url": "/otn/{3}?leftTicketDTO.train_date={0}&leftTicketDTO.from_station={1}&leftTicketDTO.to_station={2}&purpose_codes=ADULT",
|
||||||
"req_type": "get",
|
"req_type": "get",
|
||||||
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
"Referer": "https://kyfw.12306.cn/otn/leftTicket/init",
|
||||||
"Host": "kyfw.12306.cn",
|
"Host": "kyfw.12306.cn",
|
||||||
|
|
|
@ -3,6 +3,7 @@ import datetime
|
||||||
import random
|
import random
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import wrapcache
|
import wrapcache
|
||||||
|
@ -26,7 +27,7 @@ from myException.ticketConfigException import ticketConfigException
|
||||||
from myException.ticketIsExitsException import ticketIsExitsException
|
from myException.ticketIsExitsException import ticketIsExitsException
|
||||||
from myException.ticketNumOutException import ticketNumOutException
|
from myException.ticketNumOutException import ticketNumOutException
|
||||||
from myUrllib.httpUtils import HTTPClient
|
from myUrllib.httpUtils import HTTPClient
|
||||||
from utils.timeUtil import time_to_minutes,minutes_to_time
|
from utils.timeUtil import time_to_minutes, minutes_to_time
|
||||||
|
|
||||||
reload(sys)
|
reload(sys)
|
||||||
sys.setdefaultencoding('utf-8')
|
sys.setdefaultencoding('utf-8')
|
||||||
|
@ -42,7 +43,6 @@ class select:
|
||||||
self.ticke_peoples, self.station_trains, self.ticket_black_list_time, \
|
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.order_type, self.is_by_time, self.train_types, self.departure_time, \
|
||||||
self.arrival_time, self.take_time = self.get_ticket_info()
|
self.arrival_time, self.take_time = self.get_ticket_info()
|
||||||
|
|
||||||
self.is_auto_code = _get_yaml()["is_auto_code"]
|
self.is_auto_code = _get_yaml()["is_auto_code"]
|
||||||
self.auto_code_type = _get_yaml()["auto_code_type"]
|
self.auto_code_type = _get_yaml()["auto_code_type"]
|
||||||
self.is_cdn = _get_yaml()["is_cdn"]
|
self.is_cdn = _get_yaml()["is_cdn"]
|
||||||
|
@ -50,6 +50,7 @@ class select:
|
||||||
self.urls = urlConf.urls
|
self.urls = urlConf.urls
|
||||||
self.login = GoLogin(self, self.is_auto_code, self.auto_code_type)
|
self.login = GoLogin(self, self.is_auto_code, self.auto_code_type)
|
||||||
self.cdn_list = []
|
self.cdn_list = []
|
||||||
|
self.queryUrl = "leftTicket/queryX"
|
||||||
self.passengerTicketStrList = ""
|
self.passengerTicketStrList = ""
|
||||||
self.oldPassengerStr = ""
|
self.oldPassengerStr = ""
|
||||||
self.set_type = ""
|
self.set_type = ""
|
||||||
|
@ -79,12 +80,13 @@ class select:
|
||||||
take_time = time_to_minutes(ticket_info_config["set"]["take_time"])
|
take_time = time_to_minutes(ticket_info_config["set"]["take_time"])
|
||||||
|
|
||||||
print u"*" * 20
|
print u"*" * 20
|
||||||
print u"12306刷票小助手,最后更新于2018.9.21,请勿作为商业用途,交流群号:286271084"
|
print u"12306刷票小助手,最后更新于2018.12.26,请勿作为商业用途,交流群号:286271084"
|
||||||
if is_by_time:
|
if is_by_time:
|
||||||
method_notie="购票方式:根据时间区间购票\n可接受最早出发时间:{0}\n可接受最晚抵达时间:{1}\n可接受最长旅途时间:{2}\n可接受列车类型:{3}\n"\
|
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))
|
.format(minutes_to_time(departure_time), minutes_to_time(arrival_time), minutes_to_time(take_time),
|
||||||
|
" , ".join(train_types))
|
||||||
else:
|
else:
|
||||||
method_notie="购票方式:根据候选车次购买\n候选购买车次:{0}".format(",".join(station_trains))
|
method_notie = "购票方式:根据候选车次购买\n候选购买车次:{0}".format(",".join(station_trains))
|
||||||
print u"当前配置:\n出发站:{0}\n到达站:{1}\n乘车日期:{2}\n坐席:{3}\n是否有票优先提交:{4}\n乘车人:{5}\n" \
|
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 \
|
u"刷新间隔:随机(1-3S)\n{6}\n僵尸票关小黑屋时长:{7}\n 下单接口:{8}\n".format \
|
||||||
(
|
(
|
||||||
|
@ -128,26 +130,17 @@ class select:
|
||||||
else:
|
else:
|
||||||
self.login.go_login()
|
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):
|
def cdn_req(self, cdn):
|
||||||
for i in range(len(cdn) - 1):
|
for i in range(len(cdn) - 1):
|
||||||
http = HTTPClient()
|
http = HTTPClient()
|
||||||
urls = self.urls["loginInit"]
|
urls = self.urls["loginInitCdn"]
|
||||||
http.cdn = cdn[i].replace("\n", "")
|
http._cdn = cdn[i].replace("\n", "")
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
rep = http.send(urls)
|
rep = http.send(urls)
|
||||||
if rep and "message" not in rep and (datetime.datetime.now() - start_time).microseconds / 1000 < 500:
|
if rep and "message" not in rep and (datetime.datetime.now() - start_time).microseconds / 1000 < 500:
|
||||||
print("加入cdn {0}".format(cdn[i].replace("\n", "")))
|
if cdn[i].replace("\n", "") not in self.cdn_list: # 如果有重复的cdn,则放弃加入
|
||||||
self.cdn_list.append(cdn[i].replace("\n", ""))
|
print("加入cdn {0}".format(cdn[i].replace("\n", "")))
|
||||||
|
self.cdn_list.append(cdn[i].replace("\n", ""))
|
||||||
print(u"所有cdn解析完成...")
|
print(u"所有cdn解析完成...")
|
||||||
|
|
||||||
def cdn_certification(self):
|
def cdn_certification(self):
|
||||||
|
@ -157,14 +150,14 @@ class select:
|
||||||
"""
|
"""
|
||||||
if self.is_cdn == 1:
|
if self.is_cdn == 1:
|
||||||
CDN = CDNProxy()
|
CDN = CDNProxy()
|
||||||
all_cdn = CDN.all_cdn()
|
all_cdn = CDN.open_cdn_file()
|
||||||
if all_cdn:
|
if all_cdn:
|
||||||
print(u"由于12306网站策略调整,cdn功能暂时关闭。")
|
# print(u"由于12306网站策略调整,cdn功能暂时关闭。")
|
||||||
# print(u"开启cdn查询")
|
print(u"开启cdn查询")
|
||||||
# print(u"本次待筛选cdn总数为{}, 筛选时间大约为5-10min".format(len(all_cdn)))
|
print(u"本次待筛选cdn总数为{}, 筛选时间大约为5-10min".format(len(all_cdn)))
|
||||||
# t = threading.Thread(target=self.cdn_req, args=(all_cdn,))
|
t = threading.Thread(target=self.cdn_req, args=(all_cdn,))
|
||||||
# t2 = threading.Thread(target=self.set_cdn, args=())
|
# t2 = threading.Thread(target=self.set_cdn, args=())
|
||||||
# t.start()
|
t.start()
|
||||||
# t2.start()
|
# t2.start()
|
||||||
else:
|
else:
|
||||||
raise ticketConfigException(u"cdn列表为空,请先加载cdn")
|
raise ticketConfigException(u"cdn列表为空,请先加载cdn")
|
||||||
|
@ -174,7 +167,7 @@ class select:
|
||||||
l = liftTicketInit(self)
|
l = liftTicketInit(self)
|
||||||
l.reqLiftTicketInit()
|
l.reqLiftTicketInit()
|
||||||
self.call_login()
|
self.call_login()
|
||||||
check_user = checkUser(self)
|
check_user = checkUser(self)
|
||||||
check_user.sendCheckUser()
|
check_user.sendCheckUser()
|
||||||
from_station, to_station = self.station_table(self.from_station, self.to_station)
|
from_station, to_station = self.station_table(self.from_station, self.to_station)
|
||||||
num = 0
|
num = 0
|
||||||
|
@ -220,7 +213,8 @@ class select:
|
||||||
print(ticket.QUEUE_WARNING_MSG.format(train_no))
|
print(ticket.QUEUE_WARNING_MSG.format(train_no))
|
||||||
else:
|
else:
|
||||||
# 获取联系人
|
# 获取联系人
|
||||||
s = getPassengerDTOs(session=self, ticket_peoples=self.ticke_peoples, set_type=seat_conf_2[seat],
|
s = getPassengerDTOs(session=self, ticket_peoples=self.ticke_peoples,
|
||||||
|
set_type=seat_conf_2[seat],
|
||||||
is_more_ticket_num=is_more_ticket_num)
|
is_more_ticket_num=is_more_ticket_num)
|
||||||
getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr()
|
getPassengerDTOsResult = s.getPassengerTicketStrListAndOldPassengerStr()
|
||||||
if getPassengerDTOsResult.get("status", False):
|
if getPassengerDTOsResult.get("status", False):
|
||||||
|
@ -256,8 +250,8 @@ class select:
|
||||||
",".join(
|
",".join(
|
||||||
self.station_trains),
|
self.station_trains),
|
||||||
(
|
(
|
||||||
datetime.datetime.now() - start_time).microseconds / 1000,
|
datetime.datetime.now() - start_time).microseconds / 1000,
|
||||||
wrapcache.get("cdn"),
|
queryResult.get("cdn", None),
|
||||||
len(
|
len(
|
||||||
self.cdn_list),
|
self.cdn_list),
|
||||||
random_time)
|
random_time)
|
||||||
|
@ -290,4 +284,6 @@ class select:
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
pass
|
s = select()
|
||||||
|
cdn = CDNProxy().open_cdn_file()
|
||||||
|
s.cdn_req(cdn)
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
import copy
|
import copy
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
import wrapcache
|
import wrapcache
|
||||||
from config import urlConf
|
from config import urlConf
|
||||||
from config.TicketEnmu import ticket
|
from config.TicketEnmu import ticket
|
||||||
|
@ -27,7 +32,6 @@ class query:
|
||||||
self.station_dates = station_dates if isinstance(station_dates, list) else list(station_dates)
|
self.station_dates = station_dates if isinstance(station_dates, list) else list(station_dates)
|
||||||
self.ticket_black_list = dict()
|
self.ticket_black_list = dict()
|
||||||
self.ticke_peoples_num = ticke_peoples_num
|
self.ticke_peoples_num = ticke_peoples_num
|
||||||
|
|
||||||
# by time
|
# by time
|
||||||
self.is_by_time = session.is_by_time
|
self.is_by_time = session.is_by_time
|
||||||
self.train_types = session.train_types
|
self.train_types = session.train_types
|
||||||
|
@ -76,13 +80,19 @@ class query:
|
||||||
查询
|
查询
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
t1 = threading.Thread(target=self.set_cdn, args=())
|
||||||
|
t1.start()
|
||||||
for station_date in self.station_dates:
|
for station_date in self.station_dates:
|
||||||
select_url = copy.copy(self.urls["select_url"])
|
select_url = copy.copy(self.urls["select_url"])
|
||||||
select_url["req_url"] = select_url["req_url"].format(station_date, self.from_station, self.to_station)
|
select_url["req_url"] = select_url["req_url"].format(station_date, self.from_station, self.to_station, self.session.queryUrl)
|
||||||
station_ticket = self.httpClint.send(select_url)
|
station_ticket = self.httpClint.send(select_url)
|
||||||
|
if station_ticket.get("c_url", ""):
|
||||||
|
print(station_ticket.get("c_url", ""))
|
||||||
|
self.session.queryUrl = station_ticket.get("c_url", "") # 重设查询接口
|
||||||
|
continue
|
||||||
value = station_ticket.get("data", "")
|
value = station_ticket.get("data", "")
|
||||||
if not value:
|
if not value:
|
||||||
print (u'{0}-{1} 车次坐席查询为空'.format(self.from_station_h, self.to_station_h))
|
print (u'{0}-{1} 车次坐席查询为空, 查询url: https://kyfw.12306.cn{2}, 可以手动查询是否有票'.format(self.from_station_h, self.to_station_h, select_url["req_url"]))
|
||||||
else:
|
else:
|
||||||
result = value.get('result', [])
|
result = value.get('result', [])
|
||||||
if result:
|
if result:
|
||||||
|
@ -142,12 +152,25 @@ class query:
|
||||||
"train_location": train_location,
|
"train_location": train_location,
|
||||||
"code": ticket.SUCCESS_CODE,
|
"code": ticket.SUCCESS_CODE,
|
||||||
"is_more_ticket_num": is_more_ticket_num,
|
"is_more_ticket_num": is_more_ticket_num,
|
||||||
|
"cdn": self.httpClint.cdn,
|
||||||
"status": True,
|
"status": True,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
print u"车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket)
|
print u"车次配置信息有误,或者返回数据异常,请检查 {}".format(station_ticket)
|
||||||
return {"code": ticket.FAIL_CODE, "status": False}
|
return {"code": ticket.FAIL_CODE, "status": False}
|
||||||
|
|
||||||
|
def set_cdn(self):
|
||||||
|
"""
|
||||||
|
设置cdn
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if self.session.is_cdn == 1:
|
||||||
|
while True:
|
||||||
|
if self.session.cdn_list:
|
||||||
|
self.httpClint.cdn = self.session.cdn_list[random.randint(0, len(self.session.cdn_list) - 1)]
|
||||||
|
else:
|
||||||
|
time.sleep(0.05)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
q = query()
|
q = query()
|
||||||
|
|
|
@ -117,9 +117,8 @@ class HTTPClient(object):
|
||||||
if is_test_cdn:
|
if is_test_cdn:
|
||||||
url_host = self._cdn
|
url_host = self._cdn
|
||||||
elif is_cdn:
|
elif is_cdn:
|
||||||
cdn = wrapcache.get("cdn")
|
if self._cdn:
|
||||||
if cdn:
|
url_host = self._cdn
|
||||||
url_host = cdn
|
|
||||||
else:
|
else:
|
||||||
url_host = urls["Host"]
|
url_host = urls["Host"]
|
||||||
else:
|
else:
|
||||||
|
@ -136,7 +135,7 @@ class HTTPClient(object):
|
||||||
allow_redirects=allow_redirects,
|
allow_redirects=allow_redirects,
|
||||||
verify=False,
|
verify=False,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200 or response.status_code == 302:
|
||||||
if response.content:
|
if response.content:
|
||||||
if is_logger:
|
if is_logger:
|
||||||
logger.log(
|
logger.log(
|
||||||
|
|
Loading…
Reference in New Issue