Merge pull request #1 from testerSunshine/master

update
pull/142/head
MonsterTan 2019-01-08 16:41:58 +08:00 committed by GitHub
commit 99ec619f2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 709 additions and 28782 deletions

View File

@ -10,4 +10,5 @@ RUN pip install --no-cache-dir -r requirements.txt
#EXPOSE 5010 #EXPOSE 5010
WORKDIR /usr/src/app/ WORKDIR /usr/src/app/
CMD [ "python", "run.py" ] #CMD [ "python", "run.py" ]
ENTRYPOINT [ "python", "run.py" ]

View File

@ -19,8 +19,9 @@
- 由于新增对时功能请务必用sudosudosudo 执行否则会报权限错误windows打开ide或者cmd请用管理员身份执行python run.py不需要加sudo - 由于新增对时功能请务必用sudosudosudo 执行否则会报权限错误windows打开ide或者cmd请用管理员身份执行python run.py不需要加sudo
- 如果你的服务器安装了docker那么就可以docker启动 - 如果你的服务器安装了docker那么就可以docker启动
- 1、docker build -t dockerticket . - 1、docker build -t dockerticket .
- 2、docker run dockerticket python run.py & - 2、~~docker run dockerticket python run.py &~~
- 3、本来是可以直接Dockerfile启动的不知道为毛启动不了如果有大佬看到问题所在欢迎提出 - 3、~~本来是可以直接Dockerfile启动的不知道为毛启动不了如果有大佬看到问题所在欢迎提出~~
- 4、docker run -d --name 12306-ticket dockerticket
- 目录对应说明 - 目录对应说明
- agency - cdn代理 - agency - cdn代理
@ -34,7 +35,8 @@
![image](https://github.com/testerSunshine/12306/blob/master/uml/uml.png) ![image](https://github.com/testerSunshine/12306/blob/master/uml/uml.png)
- 项目声明: - 项目声明:
- 本软件只供学习交流使用务作为商业用途交流群号286271084(已满) 请加2群649992274 - 本软件只供学习交流使用务作为商业用途交流群号286271084(已满) 2群649992274(已满)请加3群 群号632501142
- **进群先看公告!!!进群先看公告!!!进群先看公告!!! 重要的事情说三遍**
- 能为你抢到一张回家的票,是我最大的心愿 - 能为你抢到一张回家的票,是我最大的心愿
- 成功log如果是购票失败的请带上失败的log给我我尽力帮你调也可加群一起交流程序只是加速买票的过程并不一定能买到票 - 成功log如果是购票失败的请带上失败的log给我我尽力帮你调也可加群一起交流程序只是加速买票的过程并不一定能买到票
@ -56,15 +58,20 @@
恭喜您订票成功订单号为EB52743573, 请立即打开浏览器登录12306访问未完成订单在30分钟内完成支付 恭喜您订票成功订单号为EB52743573, 请立即打开浏览器登录12306访问未完成订单在30分钟内完成支付
``` ```
- 使用帮助: - 使用帮助:
- 测试邮箱是否可用 - 测试邮箱是否可用 [邮箱配置问题看issues](https://github.com/testerSunshine/12306/issues/107)
- 学生票issues [学生票修改](https://github.com/testerSunshine/12306/issues/47)
- 依赖安装不对的问题ImportError[requirements.txt问题](https://github.com/testerSunshine/12306/issues/91)
- 若快豆子疑问 [点我](https://github.com/testerSunshine/12306/issues/67)
- 测试下单接口是否可用有两个下单接口随便用哪个都ok - 测试下单接口是否可用有两个下单接口随便用哪个都ok
- 如果下载验证码过期或者下载失败的问题应该是12306封ip的策略多重试几次12306现在封服务器(阿里云和腾讯云)ip比较严重尽量不要放在服务器里面 - 如果下载验证码过期或者下载失败的问题应该是12306封ip的策略多重试几次12306现在封服务器(阿里云和腾讯云)ip比较严重尽量不要放在服务器里面
- 感谢一下小伙伴对本项目提供的帮助 - 感谢一下小伙伴对本项目提供的帮助
- @ sun7127@126.com - @ sun7127@126.com
- @才 - @才
- 以及所有为此项目提供pr的同学
- [更新日志](Update.md) - [更新日志](Update.md)
- 如果觉得项目还不错,可以考虑打赏一波,哈哈 - 如果觉得项目还不错,可以考虑打赏一波
- -
![image](https://github.com/testerSunshine/12306/blob/master/uml/wx.jpeg?imageMogr2/auto-orient/strip) ![image](https://github.com/testerSunshine/12306/blob/master/uml/wx.jpeg?imageMogr2/auto-orient/strip)
![image](https://github.com/testerSunshine/12306/blob/master/uml/zfb.jpeg?imageMogr2/auto-orient/strip) ![image](https://github.com/testerSunshine/12306/blob/master/uml/zfb.jpeg?imageMogr2/auto-orient/strip)

View File

@ -1,14 +1,18 @@
# encoding=utf8 # encoding=utf8
import collections import collections
import json import json
import os
import re import re
import sys import sys
import csv import csv
import requests import requests
from config import urlConf from config import urlConf
try:
reload(sys) reload(sys)
sys.setdefaultencoding('utf-8') sys.setdefaultencoding('utf-8')
except NameError:
pass
class CDNProxy: class CDNProxy:
def __init__(self, host=None): def __init__(self, host=None):
@ -42,7 +46,7 @@ class CDNProxy:
city_re = re.compile(r"<li id=\"(\S+)\" class=\"PingListCent PingRLlist") city_re = re.compile(r"<li id=\"(\S+)\" class=\"PingListCent PingRLlist")
self.city_list = re.findall(city_re, rep.content) self.city_list = re.findall(city_re, rep.content)
if self.city_list: if self.city_list:
print self.city_list print(self.city_list)
break break
else: else:
pass pass
@ -51,62 +55,24 @@ class CDNProxy:
def open_cdn_file(self): def open_cdn_file(self):
cdn = [] cdn = []
cdn_re = re.compile("CONNECT (\S+) HTTP/1.1") # cdn_re = re.compile("CONNECT (\S+) HTTP/1.1")
with open("./cdn_list", "r") as f: # path = os.path.join(os.path.dirname(__file__), '../cdn_list')
# with open(path, "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:
# print(cdn_list[0].split(":")[0])
# cdn.append(cdn_list[0].split(":")[0])
# return cdn
path = os.path.join(os.path.dirname(__file__), '../cdn_list')
with open(path, "r") as f:
for i in f.readlines(): for i in f.readlines():
# print(i.replace("\n", "")) # print(i.replace("\n", ""))
cdn_list = re.findall(cdn_re, i) if i and "kyfw.12306.cn:443" not in i:
if cdn_list and "kyfw.12306.cn:443" not in cdn_list: cdn.append(i.replace("\n", ""))
cdn.append(cdn_list[0].split(":")[0])
return cdn return cdn
def get_cdn_list(self):
"""
筛选代理
:return:
"""
f = self.open_cdn_file()
url = self.urlConf["cdn_list"]["req_url"]
num = 1
f.seek(0)
f.truncate()
for guid in self.city_list:
data = {"guid": guid,
"host": "kyfw.12306.cn",
"ishost": 0,
"encode": "HJXhdRqjh5yCF6G/AZ6EDk9faB1oSk5r",
"checktype": 0}
try:
cdn_info = self.httpClint.post(url, data, headers=self._set_header(), timeout=self.timeout).content
print(cdn_info)
if cdn_info:
split_cdn = cdn_info.split("(")[1].rstrip(")").replace("{", "").replace("}", "").split(",")
local_dict = collections.OrderedDict()
for i in split_cdn:
splits = i.split(":")
local_dict[splits[0]] = splits[2] if splits[0] == "result" else splits[1]
if local_dict and "state" in local_dict and local_dict["state"] == "1":
if "responsetime" in local_dict and local_dict["responsetime"].find("毫秒") != -1 and int(filter(str.isdigit, local_dict["responsetime"])) < 100:
f.write(json.dumps(local_dict)+"\n")
num += 1
except Exception as e:
print(e.message)
print(u"本次cdn获取完成总个数{0}".format(num))
def all_cdn(self):
"""获取cdn列表"""
with open('cdn_list', 'r') as f:
cdn = f.readlines()
return cdn
def par_csv(self):
cdn_csv = csv.reader(open("../cdn1.csv", "r"))
for c in cdn_csv:
cdn_re = re.compile(r'https://(\S+)/otn/index/init')
cdn_ip = re.findall(cdn_re, c[0])
if cdn_ip and c[2] == "200":
print(cdn_ip[0])
if __name__ == '__main__': if __name__ == '__main__':
cdn = CDNProxy() cdn = CDNProxy()

29044
cdn_list

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime
import os import os
import sys
import time import time
saleMinDelayDay = 0 saleMinDelayDay = 0
@ -22,10 +23,15 @@ seat_conf = {'商务座': 32,
'特等座': 25, '特等座': 25,
'软卧': 23, '软卧': 23,
'硬卧': 28, '硬卧': 28,
'软座': 24,
'硬座': 29, '硬座': 29,
'无座': 26, '无座': 26,
} }
if sys.version_info.major == 2:
seat_conf_2 = dict([(v, k) for (k, v) in seat_conf.iteritems()]) seat_conf_2 = dict([(v, k) for (k, v) in seat_conf.iteritems()])
else:
seat_conf_2 = dict([(v, k) for (k, v) in seat_conf.items()])
def getNowTimestamp(): def getNowTimestamp():
return time.time() return time.time()
@ -90,3 +96,14 @@ def getVCodeImageFile(imageName):
def getCacheFile(cacheType): def getCacheFile(cacheType):
return os.path.join(getCacheDir(), cacheType + ".cache") return os.path.join(getCacheDir(), cacheType + ".cache")
def checkSleepTime(session):
now = datetime.datetime.now()
if now.hour >= 23 or now.hour < 6:
print(u"12306休息时间本程序自动停止,明天早上七点将自动运行")
open_time = datetime.datetime(now.year, now.month, now.day, 6)
if open_time < now:
open_time += datetime.timedelta(1)
time.sleep((open_time - now).seconds)
session.call_login()

View File

@ -13,4 +13,8 @@ def _get_yaml():
f = open(path) f = open(path)
s = yaml.load(f) s = yaml.load(f)
f.close() f.close()
return s return s.decode() if isinstance(s, bytes) else s
if __name__ == '__main__':
print(_get_yaml())

View File

@ -5,8 +5,7 @@ set:
# - 2018-01-06 # - 2018-01-06
# - 2018-01-07 # - 2018-01-07
station_dates: station_dates:
- "2019-01-27" - "2019-02-02"
- "2019-01-26"
# 是否根据时间范围 和 乘车类型 购票 # 是否根据时间范围 和 乘车类型 购票
# 否则将需要手动填写车次 # 否则将需要手动填写车次
@ -46,15 +45,18 @@ set:
# - "G1021" # - "G1021"
# - "G99" # - "G99"
# - "G6011" # - "G6011"
- "D2972" # - "D2972"
- "D1874" # - "D1874"
- "D2834" # - "D2834"
- "G6172"
- "G6186"
- "G6154"
# 出发城市,比如深圳北,就填深圳就搜得到 # 出发城市,比如深圳北,就填深圳就搜得到
from_station: "广州南" from_station: "广州南"
# 到达城市 比如深圳北,就填深圳就搜得到 # 到达城市 比如深圳北,就填深圳就搜得到
to_station: "三江南" to_station: "邵阳"
# 座位(list) 多个座位ex: # 座位(list) 多个座位ex:
# - "二等座" # - "二等座"
@ -69,8 +71,9 @@ set:
# - "张三" # - "张三"
# - "李四" # - "李四"
ticke_peoples: ticke_peoples:
# - "文贤平" - "文贤平"
- "梁敏" - "李梦云"
# - "梁敏"
# 12306登录账号(list) # 12306登录账号(list)
12306account: 12306account:
- user: "931128603@qq.com" - user: "931128603@qq.com"
@ -80,7 +83,7 @@ set:
ticket_black_list_time: 5 ticket_black_list_time: 5
# 自动打码 # 自动打码
is_auto_code: True is_auto_code: False
# 打码平台, 2 为若快平台(目前只支持若快平台打码,打码兔已经关闭), 若快注册地址http://www.ruokuai.com/client/index?6726 # 打码平台, 2 为若快平台(目前只支持若快平台打码,打码兔已经关闭), 若快注册地址http://www.ruokuai.com/client/index?6726
auto_code_type: 2 auto_code_type: 2
@ -119,7 +122,10 @@ order_type: 2
# 下单模式 1 为预售整点刷新刷新间隔0.1-0.5S, 然后会校验时间比如12点的预售那脚本就会在12.00整检票,刷新订单 # 下单模式 1 为预售整点刷新刷新间隔0.1-0.5S, 然后会校验时间比如12点的预售那脚本就会在12.00整检票,刷新订单
# 2 是捡漏捡漏的刷新间隔时间为0.5-3秒时间间隔长不容易封ip # 2 是捡漏捡漏的刷新间隔时间为0.5-3秒时间间隔长不容易封ip
order_model: 1 order_model: 2
# 预售放票时间, 如果是捡漏模式,可以忽略此操作
open_time: '13:00:00'

View File

@ -53,6 +53,7 @@ urls = {
"s_time": 0.1, "s_time": 0.1,
"is_logger": False, "is_logger": False,
"is_json": False, "is_json": False,
"not_decode": True,
}, },
"codeCheck": { # 验证码校验 "codeCheck": { # 验证码校验
"req_url": "/passport/captcha/captcha-check", "req_url": "/passport/captcha/captcha-check",

View File

@ -52,5 +52,5 @@ class RClient(object):
if __name__ == '__main__': if __name__ == '__main__':
rc = RClient('931128603', '',) rc = RClient('931128603', '',)
im = open('tkcode', 'rb').read() im = open('tkcode', 'rb').read()
print rc.rk_create(im, 6113) print(rc.rk_create(im, 6113))

View File

@ -7,7 +7,6 @@ from inter.GetPassCodeNewOrderAndLogin import getPassCodeNewOrderAndLogin
from inter.GetRandCode import getRandCode from inter.GetRandCode import getRandCode
from myException.UserPasswordException import UserPasswordException from myException.UserPasswordException import UserPasswordException
from myException.balanceException import balanceException from myException.balanceException import balanceException
from myUrllib import myurllib2
class GoLogin: class GoLogin:
@ -127,15 +126,6 @@ class GoLogin:
self.getUserName(uamtk) self.getUserName(uamtk)
break break
def logout(self):
url = 'https://kyfw.12306.cn/otn/login/loginOut'
result = myurllib2.get(url)
if result:
print (u"已退出")
else:
print (u"退出失败")
# if __name__ == "__main__": # if __name__ == "__main__":
# # main() # # main()
# # logout() # # logout()

View File

@ -1,6 +1,7 @@
# -*- coding=utf-8 -*- # -*- coding=utf-8 -*-
import datetime import datetime
import random import random
import os
import socket import socket
import sys import sys
import threading import threading
@ -9,7 +10,7 @@ import time
import wrapcache import wrapcache
from agency.cdn_utils import CDNProxy from agency.cdn_utils import CDNProxy
from config import urlConf from config import urlConf, configCommon
from config.AutoSynchroTime import autoSynchroTime from config.AutoSynchroTime import autoSynchroTime
from config.TicketEnmu import ticket from config.TicketEnmu import ticket
from config.configCommon import seat_conf from config.configCommon import seat_conf
@ -30,8 +31,11 @@ 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
try:
reload(sys) reload(sys)
sys.setdefaultencoding('utf-8') sys.setdefaultencoding('utf-8')
except NameError:
pass
class select: class select:
@ -43,7 +47,7 @@ class select:
self.from_station, self.to_station, self.station_dates, self._station_seat, self.is_more_ticket, \ 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.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.order_model = self.get_ticket_info() self.arrival_time, self.take_time, self.order_model, self.open_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"]
@ -51,7 +55,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.queryUrl = "leftTicket/queryZ"
self.passengerTicketStrList = "" self.passengerTicketStrList = ""
self.oldPassengerStr = "" self.oldPassengerStr = ""
self.set_type = "" self.set_type = ""
@ -62,11 +66,11 @@ class select:
:return: :return:
""" """
ticket_info_config = _get_yaml() ticket_info_config = _get_yaml()
from_station = ticket_info_config["set"]["from_station"].encode("utf8") from_station = ticket_info_config["set"]["from_station"]
to_station = ticket_info_config["set"]["to_station"].encode("utf8") to_station = ticket_info_config["set"]["to_station"]
station_dates = ticket_info_config["set"]["station_dates"] station_dates = ticket_info_config["set"]["station_dates"]
set_names = ticket_info_config["set"]["set_type"] set_names = ticket_info_config["set"]["set_type"]
set_type = [seat_conf[x.encode("utf8")] for x in 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"] is_more_ticket = ticket_info_config["set"]["is_more_ticket"]
ticke_peoples = ticket_info_config["set"]["ticke_peoples"] ticke_peoples = ticket_info_config["set"]["ticke_peoples"]
station_trains = ticket_info_config["set"]["station_trains"] station_trains = ticket_info_config["set"]["station_trains"]
@ -82,17 +86,18 @@ class select:
# 下单模式 # 下单模式
order_model = ticket_info_config["order_model"] order_model = ticket_info_config["order_model"]
open_time = ticket_info_config["open_time"]
print u"*" * 20 print(u"*" * 50)
print u"12306刷票小助手最后更新于2019.01.02请勿作为商业用途交流群号286271084(已满) 请加2群649992274" print(u"12306刷票小助手最后更新于2019.01.07请勿作为商业用途交流群号286271084(已满) 2群649992274(已满)请加3群群号632501142")
if is_by_time: if is_by_time:
method_notie = u"购票方式:根据时间区间购票\n可接受最早出发时间:{0}\n可接受最晚抵达时间:{1}\n可接受最长旅途时间:{2}\n可接受列车类型:{3}\n" \ 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), .format(minutes_to_time(departure_time), minutes_to_time(arrival_time), minutes_to_time(take_time),
" , ".join(train_types)) " , ".join(train_types))
else: else:
method_notie = u"购票方式:根据候选车次购买\n候选购买车次:{0}".format(",".join(station_trains)) method_notie = u"购票方式:根据候选车次购买\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 下单模式:{9}\n".format \ u"刷新间隔: 随机(1-3S)\n{6}\n僵尸票关小黑屋时长: {7}\n下单接口: {8}\n下单模式: {9}\n预售踩点时间:{10} ".format \
( (
from_station, from_station,
to_station, to_station,
@ -103,12 +108,13 @@ class select:
method_notie, method_notie,
ticket_black_list_time, ticket_black_list_time,
order_type, order_type,
order_model order_model,
) open_time,
print u"*" * 20 ))
print (u"*" * 50)
return from_station, to_station, station_dates, set_type, is_more_ticket, ticke_peoples, station_trains, \ 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, \ ticket_black_list_time, order_type, is_by_time, train_types, departure_time, arrival_time, take_time, \
order_model order_model, open_time
def station_table(self, from_station, to_station): def station_table(self, from_station, to_station):
""" """
@ -116,7 +122,8 @@ class select:
:param station: :param station:
:return: :return:
""" """
result = open('station_name.txt') path = os.path.join(os.path.dirname(__file__), '../station_name.txt')
result = open(path)
info = result.read().split('=')[1].strip("'").split('@') info = result.read().split('=')[1].strip("'").split('@')
del info[0] del info[0]
station_name = {} station_name = {}
@ -146,7 +153,7 @@ class select:
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:
if cdn[i].replace("\n", "") not in self.cdn_list: # 如果有重复的cdn则放弃加入 if cdn[i].replace("\n", "") not in self.cdn_list: # 如果有重复的cdn则放弃加入
print("加入cdn {0}".format(cdn[i].replace("\n", ""))) # print(u"加入cdn {0}".format(cdn[i].replace("\n", "")))
self.cdn_list.append(cdn[i].replace("\n", "")) self.cdn_list.append(cdn[i].replace("\n", ""))
print(u"所有cdn解析完成...") print(u"所有cdn解析完成...")
@ -177,30 +184,25 @@ class select:
l.reqLiftTicketInit() l.reqLiftTicketInit()
self.call_login() self.call_login()
check_user = checkUser(self) check_user = checkUser(self)
check_user.sendCheckUser() 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) from_station, to_station = self.station_table(self.from_station, self.to_station)
num = 0 num = 0
# isAutoSynchroTime = False
while 1: while 1:
try: try:
num += 1 num += 1
check_user.sendCheckUser()
now = datetime.datetime.now() # 感谢群里大佬提供整点代码 now = datetime.datetime.now() # 感谢群里大佬提供整点代码
if now.hour >= 23 or now.hour < 6: configCommon.checkSleepTime(self) # 晚上到点休眠
print(u"12306休息时间本程序自动停止,明天早上七点将自动运行")
open_time = datetime.datetime(now.year, now.month, now.day, 6)
if open_time < now:
open_time += datetime.timedelta(1)
time.sleep((open_time - now).seconds)
self.call_login()
if self.order_model is 1: if self.order_model is 1:
sleep_time_s = 0.1 sleep_time_s = 0.5
sleep_time_t = 0.5 sleep_time_t = 0.6
# 测试了一下有微妙级的误差应该不影响测试结果2019-01-02 22:30:00.004555,预售还是会受到前一次刷新的时间影响,暂时没想到好的解决方案 # 测试了一下有微妙级的误差应该不影响测试结果2019-01-02 22:30:00.004555,预售还是会受到前一次刷新的时间影响,暂时没想到好的解决方案
if now.strftime("%M:%S") == "29:55" or now.strftime("%M:%S") == "59:55": while not now.strftime("%H:%M:%S") == self.open_time:
print(u"预售整点模式卡点中") now = datetime.datetime.now()
time.sleep(5) if now.strftime("%H:%M:%S") > self.open_time:
print(u"预售模式执行") break
time.sleep(0.0001)
else: else:
sleep_time_s = 0.5 sleep_time_s = 0.5
sleep_time_t = 3 sleep_time_t = 3
@ -275,31 +277,31 @@ class select:
random_time)) random_time))
time.sleep(random_time) time.sleep(random_time)
except PassengerUserException as e: except PassengerUserException as e:
print e.message print(e)
break break
except ticketConfigException as e: except ticketConfigException as e:
print e.message print(e)
break break
except ticketIsExitsException as e: except ticketIsExitsException as e:
print e.message print(e)
break break
except ticketNumOutException as e: except ticketNumOutException as e:
print e.message print(e)
break break
except UserPasswordException as e: except UserPasswordException as e:
print e.message print(e)
break break
except ValueError as e: except ValueError as e:
if e.message == "No JSON object could be decoded": if e == "No JSON object could be decoded":
print(u"12306接口无响应正在重试") print(u"12306接口无响应正在重试")
else: else:
print(e.message) print(e)
except KeyError as e: except KeyError as e:
print(e.message) print(e)
except TypeError as e: except TypeError as e:
print(u"12306接口无响应正在重试 {0}".format(e.message)) print(u"12306接口无响应正在重试 {0}".format(e))
except socket.error as e: except socket.error as e:
print(e.message) print(e)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -68,7 +68,7 @@ class checkOrderInfo:
self.passengerTicketStrList, self.passengerTicketStrList,
) )
QueueCount.sendGetQueueCount() QueueCount.sendGetQueueCount()
elif "errMsg" in checkOrderInfoRep['data'] and checkOrderInfoRep['data']["errMsg"]: elif "errMsg" in data and data["errMsg"]:
print checkOrderInfoRep['data']["errMsg"] print(checkOrderInfoRep['data']["errMsg"])
elif 'messages' in checkOrderInfoRep and checkOrderInfoRep['messages']: elif 'messages' in checkOrderInfoRep and checkOrderInfoRep['messages']:
print (checkOrderInfoRep['messages'][0]) print (checkOrderInfoRep['messages'][0])

View File

@ -1,7 +1,8 @@
# coding=utf-8 # coding=utf-8
import datetime import datetime
import time
import wrapcache import wrapcache
from config import configCommon
from config.TicketEnmu import ticket from config.TicketEnmu import ticket
@ -15,6 +16,9 @@ class checkUser:
:return: :return:
""" """
CHENK_TIME = 0.3 CHENK_TIME = 0.3
while 1:
time.sleep(0.1) # 防止cpu占用过高
configCommon.checkSleepTime(self.session) # 修复晚上查询线程休眠时,检查登录线程为休眠,造成快豆迅速消耗
if wrapcache.get("user_time") is None: if wrapcache.get("user_time") is None:
check_user_url = self.session.urls["check_user_url"] check_user_url = self.session.urls["check_user_url"]
data = {"_json_att": ""} data = {"_json_att": ""}

View File

@ -18,11 +18,11 @@ def getPassCodeNewOrderAndLogin(session, imgType):
codeImgUrl = copy.deepcopy(session.urls["codeImgByOrder"]) codeImgUrl = copy.deepcopy(session.urls["codeImgByOrder"])
codeImgUrl["req_url"] = codeImgUrl["req_url"].format(random.random()) codeImgUrl["req_url"] = codeImgUrl["req_url"].format(random.random())
print (u"下载验证码...") print (u"下载验证码...")
img_path = './tkcode' img_path = './tkcode.png'
result = session.httpClint.send(codeImgUrl) result = session.httpClint.send(codeImgUrl)
try: try:
if isinstance(result, dict): if isinstance(result, dict):
print(u"下载验证码失败, 请手动检查是否ip被封或者重试请求地址{}".format(codeImgUrl.get("req_url"))) print(u"下载验证码失败, 请手动检查是否ip被封或者重试请求地址https://kyfw.12306.cn/{}".format(codeImgUrl.get("req_url")))
return False return False
else: else:
print(u"下载验证码成功") print(u"下载验证码成功")

View File

@ -3,6 +3,11 @@ from config.TicketEnmu import ticket
from myException.PassengerUserException import PassengerUserException from myException.PassengerUserException import PassengerUserException
import wrapcache import wrapcache
try:
xrange # Python 2
except NameError:
xrange = range # Python 3
class getPassengerDTOs: class getPassengerDTOs:
""" """
@ -48,6 +53,7 @@ class getPassengerDTOs:
'商务座': 9, '商务座': 9,
'硬座': 1, '硬座': 1,
'无座': 1, '无座': 1,
'软座': 2,
'软卧': 4, '软卧': 4,
'硬卧': 3, '硬卧': 3,
} }

View File

@ -4,6 +4,11 @@ from PIL import Image
from config.ticketConf import _get_yaml from config.ticketConf import _get_yaml
from damatuCode.ruokuai import RClient from damatuCode.ruokuai import RClient
try:
raw_input # Python 2
except NameError: # Python 3
raw_input = input
def getRandCode(is_auto_code, auto_code_type, result): def getRandCode(is_auto_code, auto_code_type, result):
""" """
@ -23,10 +28,10 @@ def getRandCode(is_auto_code, auto_code_type, result):
return codexy(Ofset=",".join(list(Result["Result"])), is_raw_input=False) return codexy(Ofset=",".join(list(Result["Result"])), is_raw_input=False)
else: else:
if "Error" in Result and Result["Error"]: if "Error" in Result and Result["Error"]:
print u"打码平台错误: {0}, 请登录打码平台查看-http://www.ruokuai.com/client/index?6726".format(Result["Error"]) print(u"打码平台错误: {0}, 请登录打码平台查看-http://www.ruokuai.com/client/index?6726".format(Result["Error"]))
return "" return ""
else: else:
img = Image.open('./tkcode') img = Image.open('./tkcode.png')
img.show() img.show()
return codexy() return codexy()
except Exception as e: except Exception as e:
@ -46,7 +51,8 @@ def codexy(Ofset=None, is_raw_input=True):
| 5 | 6 | 7 | 8 | | 5 | 6 | 7 | 8 |
***************** *****************
""") """)
print(u"验证码分为8个对应上面数字例如第一和第二张输入1, 2") print(u"验证码分为8个对应上面数字例如第一和第二张输入1, 2 如果开启cdn查询的话会冲掉提示直接鼠标点击命令行获取焦点输入即可不要输入空格")
print(u"如果是linux无图形界面请使用自动打码is_auto_code: True")
Ofset = raw_input(u"输入对应的验证码: ") Ofset = raw_input(u"输入对应的验证码: ")
Ofset = Ofset.replace("", ",") Ofset = Ofset.replace("", ",")
select = Ofset.split(',') select = Ofset.split(',')
@ -55,29 +61,29 @@ def codexy(Ofset=None, is_raw_input=True):
offsetsY = 0 # 选择的答案的top值 offsetsY = 0 # 选择的答案的top值
for ofset in select: for ofset in select:
if ofset == '1': if ofset == '1':
offsetsY = 46 offsetsY = 77
offsetsX = 42 offsetsX = 40
elif ofset == '2': elif ofset == '2':
offsetsY = 46 offsetsY = 77
offsetsX = 105 offsetsX = 112
elif ofset == '3': elif ofset == '3':
offsetsY = 45 offsetsY = 77
offsetsX = 184 offsetsX = 184
elif ofset == '4': elif ofset == '4':
offsetsY = 48 offsetsY = 77
offsetsX = 256 offsetsX = 256
elif ofset == '5': elif ofset == '5':
offsetsY = 36 offsetsY = 149
offsetsX = 117 offsetsX = 40
elif ofset == '6': elif ofset == '6':
offsetsY = 112 offsetsY = 149
offsetsX = 115 offsetsX = 112
elif ofset == '7': elif ofset == '7':
offsetsY = 114 offsetsY = 149
offsetsX = 181 offsetsX = 184
elif ofset == '8': elif ofset == '8':
offsetsY = 111 offsetsY = 149
offsetsX = 252 offsetsX = 256
else: else:
pass pass
post.append(offsetsX) post.append(offsetsX)

View File

@ -117,7 +117,7 @@ class query:
start_time = ticket_info[8] start_time = ticket_info[8]
arrival_time = ticket_info[9] arrival_time = ticket_info[9]
distance_time = ticket_info[10] distance_time = ticket_info[10]
print start_time, arrival_time, distance_time print(start_time, arrival_time, distance_time)
seat = j seat = j
try: try:
ticket_num = int(ticket_info[j]) ticket_num = int(ticket_info[j])
@ -160,8 +160,8 @@ class query:
"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, "cdn": self.httpClint.cdn,}
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -45,7 +45,7 @@ class queryOrderWaitTime:
raise ticketIsExitsException(ticket.WAIT_ORDER_SUCCESS.format( raise ticketIsExitsException(ticket.WAIT_ORDER_SUCCESS.format(
data.get("orderId"))) data.get("orderId")))
elif data.get("msg", False): elif data.get("msg", False):
print data.get("msg", "") print(data.get("msg", ""))
break break
elif data.get("waitTime", False): elif data.get("waitTime", False):
print(ticket.WAIT_ORDER_CONTINUE.format(0 - data.get("waitTime", False))) print(ticket.WAIT_ORDER_CONTINUE.format(0 - data.get("waitTime", False)))
@ -83,7 +83,7 @@ class queryOrderWaitTime:
queryMyOrderNoCompleteResult["data"]["orderCacheDTO"]["message"]["message"]) queryMyOrderNoCompleteResult["data"]["orderCacheDTO"]["message"]["message"])
else: else:
if queryMyOrderNoCompleteResult.get("message", False): if queryMyOrderNoCompleteResult.get("message", False):
print queryMyOrderNoCompleteResult.get("message", False) print(queryMyOrderNoCompleteResult.get("message", False))
return False return False
else: else:
return False return False

View File

@ -5,7 +5,6 @@ from collections import OrderedDict
from time import sleep from time import sleep
import requests import requests
from config import logger from config import logger
import wrapcache
def _set_header_default(): def _set_header_default():
@ -27,6 +26,7 @@ class HTTPClient(object):
""" """
self.initS() self.initS()
self._cdn = None self._cdn = None
self._proxies = None
def initS(self): def initS(self):
self._s = requests.Session() self._s = requests.Session()
@ -118,7 +118,7 @@ class HTTPClient(object):
url_host = self._cdn url_host = self._cdn
elif is_cdn: elif is_cdn:
if self._cdn: if self._cdn:
print(u"当前请求cdn为{}".format(self._cdn)) # print(u"当前请求cdn为{}".format(self._cdn))
url_host = self._cdn url_host = self._cdn
else: else:
url_host = urls["Host"] url_host = urls["Host"]
@ -128,7 +128,10 @@ class HTTPClient(object):
try: try:
# sleep(urls["s_time"]) if "s_time" in urls else sleep(0.001) # sleep(urls["s_time"]) if "s_time" in urls else sleep(0.001)
sleep(s_time) sleep(s_time)
try:
requests.packages.urllib3.disable_warnings() requests.packages.urllib3.disable_warnings()
except:
pass
response = self._s.request(method=method, response = self._s.request(method=method,
timeout=2, timeout=2,
url="https://" + url_host + req_url, url="https://" + url_host + req_url,
@ -137,11 +140,16 @@ class HTTPClient(object):
verify=False, verify=False,
**kwargs) **kwargs)
if response.status_code == 200 or response.status_code == 302: if response.status_code == 200 or response.status_code == 302:
if urls.get("not_decode", False):
return response.content
if response.content: if response.content:
if is_logger: if is_logger:
logger.log( logger.log(
u"出参:{0}".format(response.content)) u"出参:{0}".format(response.content))
return json.loads(response.content) if urls["is_json"] else response.content if urls["is_json"]:
return json.loads(response.content.decode() if isinstance(response.content, bytes) else response.content)
else:
return response.content.decode("utf8", "ignore") if isinstance(response.content, bytes) else response.content
else: else:
logger.log( logger.log(
u"url: {} 返回参数为空".format(urls["req_url"])) u"url: {} 返回参数为空".format(urls["req_url"]))

View File

@ -1,63 +0,0 @@
# -*- coding=utf-8 -*-
import httplib
import ssl
import urllib
import urllib2
import sys
from cookielib import LWPCookieJar
reload(sys)
sys.setdefaultencoding('UTF8')
cookiejar = LWPCookieJar()
cookiesuppor = urllib2.HTTPCookieProcessor(cookiejar)
opener = urllib2.build_opener(cookiesuppor, urllib2.HTTPHandler)
urllib2.install_opener(opener)
ssl._create_default_https_context = ssl._create_unverified_context
def get(url):
try:
request = urllib2.Request(url=url)
request.add_header("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
request.add_header('X-Requested-With', 'xmlHttpRequest')
request.add_header('User-Agent', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
)
request.add_header('Referer', 'https://kyfw.12306.cn/otn/confirmPassenger/initDc')
request.add_header('Accept', '*/*')
result = urllib2.urlopen(request).read()
assert isinstance(result, object)
return result
except httplib.error as e:
print e
pass
except urllib2.URLError as e:
print e
pass
except urllib2.HTTPBasicAuthHandler, urllib2.HTTPError:
pass
def Post(url, data):
try:
request = urllib2.Request(url=url, data=urllib.urlencode(data))
# req.add_header('User-Agent', 'Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0')
# request = urllib2Post.Request(ajax_url, urllib.urlencode(dc))
request.add_header("Content-Type", "application/x-www-form-urlencoded;application/json;charset=utf-8")
request.add_header('X-Requested-With', 'xmlHttpRequest')
request.add_header('User-Agent', "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
)
request.add_header('Referer', 'https://kyfw.12306.cn/otn/confirmPassenger/initDc')
request.add_header('Accept', '*/*')
# request.add_header('Accept-Encoding', 'gzip, deflate')
for i in range(3):
result = urllib2.urlopen(request).read()
if result:
return result
else:
print("返回结果为空,正在第{0}重试".format(i))
except httplib.error as e:
return e
except urllib2.URLError as e:
return e
except urllib2.HTTPBasicAuthHandler, urllib2.HTTPError:
return ('error')

BIN
tkcode

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB