这几天用keras+tensorflow训练了下验证码,弄了一个gpu的显卡,训练速度杠杠的^_^, 准度直接提升了几个档次,(小白阶段只会用框架^_^),图片识别准度基本达到96%,文字识别无限接近100%,但是在12306认证的过程中,很多时候都出现及时图片识别都正确,还是认证失败的问题。目前测试了下帮朋友抢到几张票,感觉有点成就感^_^
12306图片验证测试接口:http://www.xiuler.com/test
我在认证失败的图片加上了识别结果拿出来分析,基本上图片识别都是正确的
以上训练框架,我参考了 https://github.com/libowei1213/12306_captcha基于深度学习识别12306验证码,感谢分享的文章,在此中获益良多,其实目前12306抢票脚本已经很多,我随便找了个,然后稍稍改进了下加上图形界面,有些东西可以自行调整,里面用了上面提供的框架keras+tensorflow,里面采用了当前效果最好的卷积网络模型之一:DenseNet,很强大
主要实现代码附上: (目前只是为了研究所写,代码质量可以忽略……)
12306pass.py
#coding:utf-8
import requests
import random,re,time,threading,uuid
import http.cookiejar as HC
import json
from drawPro import *
from push_progress import *
from PySide2.QtWidgets import *
from PySide2.QtCore import *
from PySide2.QtGui import *
from code12306 import *
class SignWidget(QDialog):
txtInfo=Signal(str)
def __init__(self, parent = None):
super(SignWidget, self).__init__(parent)
self.setAttribute(Qt.WA_QuitOnClose, True)
# 禁用安全请求警告
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
self.session = requests.session()
self.session.cookies = HC.LWPCookieJar(filename='cookies')
try:
self.session.cookies.load(ignore_discard=True)
except:
print('未找到cookies文件')
self.session.headers = {
'Host': 'kyfw.12306.cn',
'Origin': 'https://kyfw.12306.cn',
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Referer': 'https://kyfw.12306.cn/otn/login/init',
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.8',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.73 Safari/537.36',
}
self.session.verify = False
self.stationNameToCode = dict()
self.stationCodeToName = dict()
self.stationDownloadName="stationCode.txt"
self.trainDate = ''
self.fromStationName = ''
self.fromStationCode = ''
self.toStationName = ''
self.toStationCode = ''
self.fromStationTelecode = ''
self.toStationTelecode = ''
self.trainSecretStr = ''
self.trainNo = ''
self.trainCode = ''
self.leftTicket = ''
self.seatType = ''
self.trainLocation = ''
self.submitToken = ''
self.passengerTicketStr = ''
self.oldPassengerStr = ''
self.orderId = ''
self.stoppiao=False
self.seatMap = {'无座': '1', '硬座': '1', '硬卧': '3', '软卧': '4', '高级软卧': '6', '动卧': 'F', '二等座': 'O', '一等座': 'M',
'商务座': '9'}
self.canChooseSeat = dict()
self.textcon=""
self.captchaDownloadName="temp/"
self.proxy={
'http': self.getnewip()
}
self.initStations()
# 批量待签章按钮
self.login_button = QPushButton()
self.login_button.setStyleSheet(
'QPushButton{border:1px solid #3678b5;color:#ffffff;background:#3678b5}'
'QPushButton:hover{background:#5098ca}'
)
self.login_button.setText(u'登陆')
self.login_button.setFixedSize(50, 30)
self.login_button.setCursor(Qt.PointingHandCursor)
self.login_button.clicked.connect(self.loginthread)
# 测试按钮
self.test_button = QPushButton()
self.test_button.setStyleSheet(
'QPushButton{border:1px solid #3678b5;color:#ffffff;background:#3678b5}'
'QPushButton:hover{background:#5098ca}'
)
self.test_button.setText(u'测试')
self.test_button.setFixedSize(50, 30)
self.test_button.setCursor(Qt.PointingHandCursor)
self.test_button.clicked.connect(self.test)
# 开始抢票按钮
self.sub_button = QPushButton()
self.sub_button.setStyleSheet(
'QPushButton{border:1px solid #3678b5;color:#ffffff;background:#3678b5}'
'QPushButton:hover{background:#5098ca}'
)
self.sub_button.setText(u'开始抢票')
self.sub_button.setFixedSize(50, 30)
self.sub_button.setCursor(Qt.PointingHandCursor)
self.sub_button.clicked.connect(self.submitpaker)
# 停止抢票
self.stop_button = QPushButton()
self.stop_button.setStyleSheet(
'QPushButton{border:1px solid #3678b5;color:#ffffff;background:#3678b5}'
'QPushButton:hover{background:#5098ca}'
)
self.stop_button.setText(u'停止')
self.stop_button.setFixedSize(50, 30)
self.stop_button.setCursor(Qt.PointingHandCursor)
self.stop_button.clicked.connect(self.stoptrain)
self.textprint = QTextEdit()
self.textprint.setStyleSheet(
"QTextEdit{border:1px solid #e1e1e1;}"
)
self.textprint.setText(self.textcon)
self.textprint.setReadOnly(True)
usernamelabel = QLabel()
usernamelabel.setText("用户名: ")
self.usernameedit = QLineEdit()
self.usernameedit.setStyleSheet(
"QLineEdit{border:1px solid #e1e1e1;}"
)
self.usernameedit.setText("")
self.usernameedit.setFixedSize(120, 30)
pwdlabel = QLabel()
pwdlabel.setText("密码: ")
self.pwdedit = QLineEdit()
self.pwdedit.setStyleSheet(
"QLineEdit{border:1px solid #e1e1e1;}"
)
self.pwdedit.setText("")
self.pwdedit.setEchoMode(QLineEdit.Password)
self.pwdedit.setAttribute(Qt.WA_InputMethodEnabled, False)
self.pwdedit.setFixedSize(100, 30)
pushlabel = QLabel()
pushlabel.setText("刷新频率: ")
self.pushedit = QLineEdit()
self.pushedit.setStyleSheet(
"QLineEdit{border:1px solid #e1e1e1;}"
)
self.pushedit.setText("0.5")
self.pushedit.setFixedSize(50, 30)
beginStationlabel= QLabel()
beginStationlabel.setText("起点站: ")
self.beginStationedit = QLineEdit()
self.beginStationedit.setStyleSheet(
"QLineEdit{border:1px solid #e1e1e1;}"
)
self.beginStationedit.setText("深圳北")
self.beginStationedit.setFixedSize(100, 30)
endStationlabel = QLabel()
endStationlabel.setText("终点站: ")
self.endStationedit = QLineEdit()
self.endStationedit.setStyleSheet(
"QLineEdit{border:1px solid #e1e1e1;}"
)
self.endStationedit.setText("长沙南")
self.endStationedit.setFixedSize(100, 30)
begintimelabel = QLabel()
begintimelabel.setText("坐车时间: ")
self.begintimeedit = QLineEdit()
self.begintimeedit.setStyleSheet(
"QLineEdit{border:1px solid #e1e1e1;}"
)
self.begintimeedit.setText("2019-01-29")
self.begintimeedit.setFixedSize(100, 30)
seatlabel = QLabel()
seatlabel.setText("座位: ")
self.seatedit = QLineEdit()
self.seatedit.setStyleSheet(
"QLineEdit{border:1px solid #e1e1e1;}"
)
self.seatedit.setText("二等座")
self.seatedit.setFixedSize(100, 30)
userlabel = QLabel()
userlabel.setText("乘车人: ")
self.useredit = QLineEdit()
self.useredit.setStyleSheet(
"QLineEdit{border:1px solid #e1e1e1;}"
)
self.useredit.setText("李大厨")
self.useredit.setFixedSize(100, 30)
self.notseat=QCheckBox()
self.notseat.setText("支持无座")
# 加载列表
self.createtable()
# 脚部信息
self.footlabel = QLabel()
self.footlabel.setFixedHeight(14)
self.footlabel.setText("欢迎进入")
self.footlabel.setStyleSheet(
'QLabel{color:#999;}'
)
self.trainlistnums=QListWidget()
self.trainlistnums.setStyleSheet(
"QListWidget{border:1px solid #e1e1e1;}"
)
self.trainlistnums.setFixedWidth(150)
self.trainlistnums.itemDoubleClicked.connect(self.delitem)
main_button_lyout = QHBoxLayout()
main_button_lyout.addWidget(usernamelabel)
main_button_lyout.addWidget(self.usernameedit)
main_button_lyout.addWidget(pwdlabel)
main_button_lyout.addWidget(self.pwdedit)
main_button_lyout.addWidget(self.login_button)
main_button_lyout.addWidget(pushlabel)
main_button_lyout.addWidget(self.pushedit)
main_button_lyout.addStretch(1)
main_button_lyout.addWidget(self.test_button)
main_button_lyout.addWidget(self.sub_button)
main_button_lyout.addWidget(self.stop_button)
main_two_lyout=QHBoxLayout()
main_two_lyout.addWidget(beginStationlabel)
main_two_lyout.addWidget(self.beginStationedit)
main_two_lyout.addWidget(endStationlabel)
main_two_lyout.addWidget(self.endStationedit)
main_two_lyout.addWidget(begintimelabel)
main_two_lyout.addWidget(self.begintimeedit)
main_two_lyout.addWidget(seatlabel)
main_two_lyout.addWidget(self.seatedit)
main_two_lyout.addWidget(userlabel)
main_two_lyout.addWidget(self.useredit)
main_two_lyout.addWidget(self.notseat)
main_two_lyout.addStretch(1)
main_three_lyout=QHBoxLayout()
main_three_lyout.addWidget(self.trainlistnums)
main_three_lyout.addWidget(self.textprint)
self.pro = PushProgress()
self.pro.setFixedHeight(8)
self.pro.setValue(0)
self.pro.hide()
main_lyout = QVBoxLayout()
main_lyout.addLayout(main_button_lyout)
main_lyout.addLayout(main_two_lyout)
main_lyout.addWidget(self.pro)
main_lyout.addWidget(self.MyTable)
main_lyout.addLayout(main_three_lyout)
main_lyout.addWidget(self.footlabel)
self.main_content = QVBoxLayout()
self.main_content.addLayout(main_lyout)
self.main_content.setContentsMargins(5, 5, 5, 5)
self.main_layout = QVBoxLayout()
self.main_layout.addLayout(self.main_content)
self.setLayout(self.main_layout)
self.resize(1000,600)
self.txtInfo.connect(self.printinfo)
self.code12306=code12306()
self.text_model,self.image_model=self.code12306.load_model()
self.label_dict=self.code12306.load_label_dict()
#停止抢票
def stoptrain(self):
self.stoppiao=True
# 打印信息
def printinfo(self, txt):
print("txt:",txt)
self.textcon = txt + "\r\n" + self.textcon
self.textprint.setText(self.textcon)
# 创建TABLE
def createtable(self):
self.MyTable = QTableView()
self.MyTable.setStyleSheet(
'QTableView{selection-color:white;}QTableView:item:selected{background:#fff;color:#000;}QTableView:item:selected:!enabled{ background:transparent;}QTableView:item{border-bottom:1px solid #ddd;padding:10px;}')
self.MyTable.horizontalHeader().setStyleSheet(
'QHeaderView:section{background:#f2f2f2;border:none; height:40px; border-right:1px solid #dddddd;border-bottom:1px solid #dddddd}')
self.MyTable.setShowGrid(False)
self.MyTable.setFocusPolicy(Qt.NoFocus)
self.MyTable.setFrameShape(QFrame.NoFrame)
self.MyTable.horizontalHeader().setHighlightSections(False)
self.MyTable.setSelectionBehavior(QAbstractItemView.SelectRows)
self.MyTable.verticalHeader().setVisible(False)
self.MyTable.verticalHeader().setDefaultSectionSize(40)
self.MyTable.horizontalHeader().setStretchLastSection(True)
model = QStandardItemModel(self.MyTable)
model.setHorizontalHeaderItem(0, QStandardItem(u"车次"))
model.setHorizontalHeaderItem(1, QStandardItem(u"出发站\n到达站"))
model.setHorizontalHeaderItem(2, QStandardItem(u"出发时间\n到达时间"))
model.setHorizontalHeaderItem(3, QStandardItem(u"历时"))
model.setHorizontalHeaderItem(4, QStandardItem(u"商务座\n特等座"))
model.setHorizontalHeaderItem(5, QStandardItem(u"一等座"))
model.setHorizontalHeaderItem(6, QStandardItem(u"二等座"))
model.setHorizontalHeaderItem(7, QStandardItem(u"软卧\n一等卧"))
model.setHorizontalHeaderItem(8, QStandardItem(u"硬卧\n二等卧"))
model.setHorizontalHeaderItem(9, QStandardItem(u"硬座"))
model.setHorizontalHeaderItem(10, QStandardItem(u"无座"))
model.setHorizontalHeaderItem(11, QStandardItem(u"操作"))
self.tableOperation = OperationDelegate(self.MyTable)
self.MyTable.setItemDelegateForColumn(11, self.tableOperation)
self.MyTable.setModel(model)
# 信号与槽
self.tableOperation.addtrain.connect(self.addtrainnum)
# self.MyTable.horizontalHeader().resizeSection(0, 220)
# self.MyTable.horizontalHeader().resizeSection(1, 280)
# self.MyTable.horizontalHeader().resizeSection(2, 60)
# self.MyTable.horizontalHeader().resizeSection(5, 90)
# self.MyTable.horizontalHeader().resizeSection(3, 150)
# self.MyTable.setColumnHidden(6, True)
# self.MyTable.setColumnHidden(7, True)
# self.MyTable.setColumnHidden(8, True)
def delitem(self,item):
index=self.trainlistnums.currentIndex().row()
self.trainlistnums.takeItem(index)
def addtrainnum(self,i):
print(i)
filterTrain=self.filterTrainList[i]
trainDetailSplit = filterTrain.split('|')
trainnum=trainDetailSplit[3]
if not self.checknum(trainnum):
self.trainlistnums.addItem(trainnum)
def checknum(self,trainnum):
ishave=False
for i in range(self.trainlistnums.count()):
if trainnum == self.trainlistnums.item(i).text():
ishave=True
break
return ishave
#获取抢票车次
def gettrainnums(self):
tnums=[]
for i in range(self.trainlistnums.count()):
trainnum = self.trainlistnums.item(i).text()
tnums.append(trainnum)
return tnums
def test(self):
row_count = self.MyTable.model().rowCount()
self.MyTable.model().removeRows(0, row_count)
self.MyTable.model().setRowCount(0)
self.findTicket()
# url = 'https://www.12306.cn/index/'
# proxy = {
# 'http': '111.181.54.207:9999'
# }
# response = self.session.get(url, data=None, proxies=proxy)
# result = response.text
# print(result)
#读取iptxt文件
def loadtxt(self):
f = open("ip.txt") # 返回一个文件对象
realips = []
line = f.readline() # 调用文件的 readline()方法
while line:
line = f.readline()
line = re.sub('\n', '', line)
if (line != ''):
realips.append(line)
f.close()
return realips
# def loadtxt(self):
# realips = []
# try:
# r = urllib.request.urlopen(self.ipurl,timeout=30)
# result = r.read().decode('utf-8')
# for p in result.split('\n'):
# if (p != ''):
# realips.append(p)
# r.close()
# except Exception as e:
# print(e)
# return realips
def initStations(self):
errorCount = 0
while True:
if errorCount > 3:
print('读取车站代码失败,退出程序')
sys.exit()
try:
with open(self.stationDownloadName, 'r', encoding='utf8') as f:
stationsStr = f.read()
stations = stationsStr.split('@')
for s in stations:
tempStationSplit = s.split('|')
self.stationNameToCode[tempStationSplit[1]] = tempStationSplit[2]
self.stationCodeToName[tempStationSplit[2]] =tempStationSplit[1]
return
except:
print('车站代码读取失败,正在重试...')
errorCount += 1
self.downloadStations()
def downloadStations(self):
print('正在下载城市代码...')
stationUrl = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9035'
response = self.session.get(stationUrl)
pattern = re.compile('\'(.*?)\'')
with open(self.stationDownloadName, 'w', encoding='utf8') as f:
f.write(pattern.findall(response.text)[0].lstrip('@'))
print('城市代码下载完毕')
#获取新Ip
def getnewip(self):
ips = self.loadtxt()
pip = random.choice(ips)
print("新ip:",pip)
return pip
def create_captcha_answser(self,nlist):
# 根据手动计算,得出点击图片中心得大致位置(基本准确)
answer_list_all = [(35, 39), (106, 39), (173, 39), (240, 39), (39, 106), (106, 106), (173, 106), (240, 106)]
# 根据打码函数返回的json格式的图片序号进行遍历,找到其对应的坐标,并加入到列表中
cLists=[]
for num in nlist:
x, y=answer_list_all[num]
result="{0},{1}".format(str(x + random.randint(-2, 3)), str(y + random.randint(-3, 2)))
cLists.append(result)
cLists = ','.join(cLists)
return cLists
def getCoordinate(self,picurl):
txtresult = self.code12306.online_test(picurl,self.text_model,self.image_model,self.label_dict)
print(txtresult)
self.txtInfo.emit(str(txtresult))
# coordinates = ['8,44','108,46','186,43','249,44','26,120','107,120','185,125','253,119']
# cLists=[]
# for num in txtresult:
# cList = coordinates[num]
# cLists.append(cList)
cLists=self.create_captcha_answser(txtresult)
return cLists
def getcodeurl(self):
# 获取验证码
captchaRes = self.session.get(
'https://kyfw.12306.cn/passport/captcha/captcha-image?login_site=E&module=login&rand=sjrand&0.46630622142659206',proxies=self.proxy)
captcha = captchaRes.content
filename = "%s%s.png" % (self.captchaDownloadName,uuid.uuid4())
with open(filename, 'wb') as f:
f.write(captcha)
return filename
#验证码验证
def captchaCheck(self):
captchaErrorCount = 0
print('正在识别验证码...')
self.txtInfo.emit('正在识别验证码...')
while True:
if captchaErrorCount > 10:
print('验证码失败次数超过限制,登录失败,重新抢票')
break
#下载验证码图片
codeimg=self.getcodeurl()
captchaStr=""
try:
captchaStr = self.getCoordinate(codeimg)
except Exception as e:
print(e)
print("captchaStr:",captchaStr)
self.txtInfo.emit("captchaStr:"+captchaStr)
#captchaStr = captchaStr.replace('|', ',')
captchaStr = requests.utils.requote_uri(captchaStr)
data = {
'answer': captchaStr,
'login_site' :'E',
'rand': 'sjrand'
}
#验证验证码
response = self.session.post('https://kyfw.12306.cn/passport/captcha/captcha-check', data = data,proxies=self.proxy)
print(response.text)
result = response.json()
if result['result_code'] == '4':
print('识别验证码成功')
break
else:
#print('识别验证码失败')
captchaErrorCount += 1
def secLoginVerify(self,newapptk):
print('第二次验证')
newAppTkErrorCount = 0
url = 'https://kyfw.12306.cn/otn/uamauthclient'
data = {
'tk': newapptk
}
while True:
if newAppTkErrorCount > 5:
print('newAppTk获取失败,退出程序')
sys.exit()
response = self.session.post(url, data = data)
try:
verifyResult = response.json()
print(verifyResult)
return verifyResult
except json.decoder.JSONDecodeError:
newAppTkErrorCount += 1
#登录线程
def loginthread(self):
self.login()
#登录
def login(self):
# 1 伪装cookie++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
setCookieCountError = 0
self.proxy = {
'http': self.getnewip()
}
try:
url = 'https://kyfw.12306.cn/otn/HttpZF/logdevice?algID=WYEdoc45yu&hashCode=EhTtj7Znzyie6I21jpgekYReLAnA8fyGEB4VlIGbF0g&FMQw=0&q4f3=zh-CN&VPIf=1&custID=133&VEek=unknown&dzuS=20.0%20r0&yD16=0&EOQP=895f3bf3ddaec0d22b6f7baca85603c4&lEnu=3232235778&jp76=e8eea307be405778bd87bbc8fa97b889&hAqN=Win32&platform=WEB&ks0Q=2955119c83077df58dd8bb7832898892&TeRS=728x1366&tOHY=24xx768x1366&Fvje=i1l1o1s1&q5aJ=-8&wNLf=99115dfb07133750ba677d055874de87&0aew={}&E3gR=abfdbb80598e02f8aa71b2b330daa098×tamp={}'.format(
self.session.headers['User-Agent'], str(round(time.time() * 1000)))
response = self.session.get(requests.utils.requote_uri(url),proxies=self.proxy)
pattern = re.compile('\(\'(.*?)\'\)')
userVerify3 = eval(pattern.findall(response.text)[0])
# print('设置cookie')
# print(userVerify3)
railExpiration = userVerify3['exp']
railDeviceId = userVerify3['dfp']
#self.session.cookies['RAIL_EXPIRATION'] = railExpiration
#self.session.cookies['RAIL_DEVICEID'] = railDeviceId
except Exception as e:
print(e)
# 2 做验证码验证++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
self.captchaCheck()
# 3 用户名密码登陆++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
print('用户名密码登录')
loginUrl = 'https://kyfw.12306.cn/passport/web/login'
data = {
'username': self.usernameedit.text(),
'password': self.pwdedit.text(),
'appid': 'otn'
}
response = self.session.post(loginUrl, data=data,proxies=self.proxy)
loginResult = response.json()
if loginResult['result_code'] != 0:
print('用户名密码错误(loginCheck) {}'.format(loginResult['result_code']))
self.txtInfo.emit('用户名密码错误(loginCheck) {}'.format(loginResult['result_code']))
return False
#self.session.cookies['uamtk'] = loginResult['uamtk']
# 4 用户登录第一次验证+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
url = 'https://kyfw.12306.cn/passport/web/auth/uamtk'
data = {
'appid': 'otn'
}
response = self.session.post(url, data=data,proxies=self.proxy)
self.userVerify = response.json()
print('第一次验证')
self.txtInfo.emit('第一次验证')
if self.userVerify['result_code'] != 0:
print('验证失败(uamtk) code:{}'.format(self.userVerify['result_code']))
# 5 用户登录第二次验证++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
newapptk = self.userVerify['newapptk']
userVerify2 = self.secLoginVerify(newapptk)
print('验证通过,用户为:{}'.format(userVerify2['username']))
self.txtInfo.emit('验证通过,用户为:{}'.format(userVerify2['username']))
self.session.cookies.save(ignore_discard=True, ignore_expires=True)
def findTicket(self,isshow=True):
status = False
self.curtrainName=""
self.proxy = {
'http': self.getnewip()
}
#1 输入站名坐车时间++++++++++++++++++++++++++++++++++++++++++++++++
self.trainDate = self.begintimeedit.text()
stationNames = []
stationNames.append(self.beginStationedit.text())
stationNames.append(self.endStationedit.text())
try:
stationCode = list(map(lambda x: self.stationNameToCode[x],stationNames))
self.fromStationName = stationNames[0]
self.fromStationCode = stationCode[0]
self.toStationName = stationNames[1]
self.toStationCode = stationCode[1]
print(self.fromStationName,self.fromStationCode,self.toStationName,self.toStationCode)
except KeyError:
print('车站名称错误,重新输入')
#2 查询车次+++++++++++++++++++++++++++++++++++++++++++++++++++++++
queryUrl = 'https://kyfw.12306.cn/otn/leftTicket/queryZ?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT'.format(
self.trainDate, self.fromStationCode, self.toStationCode)
findTicketError = 0
while True:
# if findTicketError > 5:
# print('查询出现错误,退出程序')
# sys.exit()
try:
response = self.session.get(queryUrl,proxies=self.proxy)
trainList = response.json()['data']['result']
break
except (json.decoder.JSONDecodeError,KeyError):
self.proxy = {
'http': self.getnewip()
}
findTicketError += 1
self.txtInfo.emit('查询车次失败第{0}次'.format(findTicketError))
if len(trainList) > 0:
'''
secretstr 0
内容是 预订 1
不知道什么串加车次 2
车次 3
始发站 4
终点站 5
要坐的站 6
要到的站 7
出发时间 8
到达时间 9
历时 10
是否可以预订(Y可以 N和IS_TIME_NOT_BUY 不可以) 11
leftTicket 12
日期20171216 13
trainLocation 15
软卧 23
硬卧 28
硬座 29
无座 26
二等座 30
一等座 31
商务座 32
'''
#3 过滤车次++++++++++++++++++++++++++++++++++++++++++++++++
filterTrainList = []
for train in trainList:
trainDetailSplit = train.split('|')
#if trainDetailSplit[11] == 'Y' and (not(trainDetailSplit[31] == ''or trainDetailSplit[31] == '无') or not(trainDetailSplit[30] == ''or trainDetailSplit[30] == '无') or not(trainDetailSplit[26] == ''or trainDetailSplit[26] == '无') or not(trainDetailSplit[23] == ''or trainDetailSplit[23] == '无') or not(trainDetailSplit[28] == ''or trainDetailSplit[28] == '无') or not(trainDetailSplit[29] == ''or trainDetailSplit[29] == '无')):
filterTrainList.append(train)
if len(filterTrainList) > 0:
self.filterTrainList=filterTrainList
if isshow:
self.printTrainList(filterTrainList)
#4 锁定用户输入车次++++++++++++++++++++++++++++++++++++++
#trainName = input('请输入要预订的列车编号:').upper()
trainnums=self.gettrainnums()
print("trainnums:",trainnums)
if len(trainnums)>0:
for trainName in trainnums:
if not status:
for filterTrain in filterTrainList:
trainDetailSplit = filterTrain.split('|')
if trainDetailSplit[3] == trainName:
self.seatType=""
self.curtrainName=trainName
self.trainSecretStr = trainDetailSplit[0]
self.trainNo = trainDetailSplit[2]
self.trainCode = trainDetailSplit[3]
self.fromStationTelecode = trainDetailSplit[6]
self.toStationTelecode = trainDetailSplit[7]
self.leftTicket = trainDetailSplit[12]
self.trainLocation = trainDetailSplit[15]
trainseat=self.seatedit.text()
if trainseat=="硬座":
if trainDetailSplit[29] != '' and trainDetailSplit[29] != u'无':
self.seatType = self.seatMap[trainseat]
status = True
elif trainseat=="二等座":
if trainDetailSplit[30] != '' and trainDetailSplit[30] != u'无':
self.seatType = self.seatMap[trainseat]
status = True
elif trainseat=="一等座":
if trainDetailSplit[31] != '' and trainDetailSplit[31] != u'无':
self.seatType = self.seatMap[trainseat]
status = True
elif trainseat=="硬卧":
if trainDetailSplit[28] != '' and trainDetailSplit[28] != u'无':
self.seatType = self.seatMap[trainseat]
status = True
elif trainseat == "商务座":
if trainDetailSplit[32] != '' and trainDetailSplit[32] != u'无':
self.seatType = self.seatMap[trainseat]
status = True
if self.seatType=="":
if self.notseat.isChecked():
if trainDetailSplit[26] != '' and trainDetailSplit[26] != u'无':
self.seatType = self.seatMap["无座"]
status = True
break
else:
break
else:
print("请选择车次")
else:
print('{},{}到{} 没有可买车次(已售完或暂停车次)'.format(self.trainDate, self.fromStationName, self.toStationName))
else:
print('{},{}到{} 无车次'.format(self.trainDate,self.fromStationName,self.toStationName))
return status
def printTrainList(self,filterTrainList):
model = self.MyTable.model()
for k,filterTrain in enumerate(filterTrainList):
ft = filterTrain.split('|')
trainnum = ft[3]
fromStationName = self.stationCodeToName[ft[6]]
toStationName = self.stationCodeToName[ft[7]]
fromtime=ft[8]
totime=ft[9]
totaltime=ft[10]
tedeng=(ft[32] if (ft[32]!="") else "--")
yideng=(ft[31] if (ft[31]!="") else "--")
erdeng = (ft[30] if (ft[30]!="") else "--")
ruanwo=(ft[23] if (ft[23]!="") else "--")
yingwo=(ft[28] if (ft[28]!="") else "--")
yingzuo=(ft[29] if (ft[29]!="") else "--")
wuzuo=(ft[26] if (ft[26]!="") else "--")
fromtoStation=fromStationName+"\n"+toStationName
fromtotime=fromtime+"\n"+totime
# status = QStandardItem()
# status.setText("未完成")
# status.setTextAlignment(Qt.AlignCenter)
# status.setForeground(QBrush(QColor(255, 0, 0)))
model.setItem(k, 0, QStandardItem(str(trainnum)))
model.setItem(k, 1, QStandardItem(fromtoStation))
model.setItem(k, 2, QStandardItem(fromtotime))
model.setItem(k, 3, QStandardItem(totaltime))
model.setItem(k, 4, QStandardItem(tedeng))
model.setItem(k, 5, QStandardItem(yideng))
model.setItem(k, 6, QStandardItem(erdeng))
model.setItem(k, 7, QStandardItem(ruanwo))
model.setItem(k, 8, QStandardItem(yingwo))
model.setItem(k, 9, QStandardItem(yingzuo))
model.setItem(k, 10, QStandardItem(wuzuo))
model.setItem(k, 11, QStandardItem(""))
#self.footlabel.setText("温馨提示: 共获取到 {0} 个车次.".format(len(filterTrainList)))
#获取用户参数信息
def choosePassenger(self,message):
passengerList = message['data']['normal_passengers']
print('账户可订票乘客: {}'.format(' '.join(list(map(lambda x: x['passenger_name'], passengerList)))))
pessnames = self.useredit.text() #输入订票乘客
pesstotalnames=pessnames.split(",")
pessDetailList=[]
for pessengerName in pesstotalnames:
for p in passengerList:
if pessengerName == p['passenger_name']:
pessengerDetail = {
'passenger_flag' : p['passenger_flag'],
'passenger_type' : p['passenger_type'],
'passenger_name' : p['passenger_name'],
'passenger_id_type_code' : p['passenger_id_type_code'],
'passenger_id_no' : p['passenger_id_no'],
'mobile_no' : p['mobile_no']
}
pessDetailList.append(pessengerDetail)
return pessDetailList
#获取乘客信息
def getuserlist(self):
self.session.headers['Referer'] = 'https://kyfw.12306.cn/otn/leftTicket/init'
# 3 initDC+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
data = '_json_att='
response = self.session.post(url, data=data)
pattern = re.compile('globalRepeatSubmitToken = \'(.*?)\'')
pattern2 = re.compile("key_check_isChange':'(.*?)'")
self.submitToken = pattern.findall(response.text)[0]
self.keyCheckIsChange = pattern2.findall(response.text)[0]
print('token:{}'.format(self.submitToken))
print('key_check_isChange:{}'.format(self.keyCheckIsChange))
# 4 getPassengerDTOs++++++++++++++++++++++++++++++++++++++++++++++++++++++
print('正在获取乘客信息')
url = 'https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs'
data = {
'_json_att': '',
'REPEAT_SUBMIT_TOKEN': self.submitToken
}
response = self.session.post(url, data=data)
result = response.json()
# print(result)
print('获取信息成功')
self.pd = self.choosePassenger(result)
#self.chooseSeat(self.seatedit.text())
def threadpiao(self):
trainnums = self.gettrainnums()
if len(trainnums) > 0:
searchnum = 0
while True:
if not self.stoppiao:
mtime=0.1
if float(self.pushedit.text())>0 and float(self.pushedit.text())<1:
mtime=random.random()
elif float(self.pushedit.text())>=1:
mtime = random.random()+1
searchnum += 1
result = self.findTicket(False)
if result:
self.txtInfo.emit(
'当前IP: {0},查询第 {1} 次,刷新速率:{2}, 结果:{3}'.format(self.proxy, searchnum,mtime,self.curtrainName + "找到余票,开始抢票"))
self.bookingTicket()
break
else:
self.txtInfo.emit('当前IP: {0},查询第 {1} 次,刷新速率:{2}, 结果:{3}'.format(self.proxy, searchnum,mtime, "此次没有找到余票"))
time.sleep(mtime)
else:
break
def submitpaker(self):
self.stoppiao=False
t = threading.Thread(target=self.threadpiao)
t.setDaemon(True)
t.start()
#组合购票人
def combinuser(self,seatType,plist):
passengerTicketStr=""
oldPassengerStr=""
for pd in plist:
passengerTicketStr += seatType + ',' + pd['passenger_flag'] + ',' + pd[
'passenger_type'] + ',' + pd['passenger_name'] + ',' + pd['passenger_id_type_code'] + ',' + \
pd['passenger_id_no'] + ',' + pd['mobile_no'] + ',N_'
oldPassengerStr += pd['passenger_name'] + ',' + pd['passenger_id_type_code'] + ',' + pd[
'passenger_id_no'] + ',' + pd['passenger_type'] + '_'
passengerTicketStr=passengerTicketStr[:-1]
return passengerTicketStr,oldPassengerStr
#抢票下单
def bookingTicket(self):
# 1 checkUser +++++++++++++++++++++++++++++++++++++++++++++
self.session.headers['Referer'] = 'https://kyfw.12306.cn/otn/leftTicket/init'
userCheckError = 0
while True:
if userCheckError > 5:
print('用户登录检测失败,退出程序')
sys.exit()
url = 'https://kyfw.12306.cn/otn/login/checkUser'
try:
result = self.session.post(url).json()
print(result)
if not result['data']['flag'] :
print('用户未登录checkUser')
userCheckError += 1
self.login()
continue
print('验证登录状态成功checkUser')
break
except json.decoder.JSONDecodeError:
userCheckError += 1
# 2 submitOrderRequest+++++++++++++++++++++++++++++++++++++
print('正在提交订单...')
self.txtInfo.emit('正在提交订单...')
url = 'https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'
data = {
'secretStr':self.trainSecretStr,
'train_date':self.trainDate,
'back_train_date':time.strftime("%Y-%m-%d", time.localtime(time.time())),
'tour_flag':'dc', # dc 单程
'purpose_codes':'ADULT', # adult 成人票
'query_from_station_name':self.fromStationName,
'query_to_station_name':self.toStationName
}
data = str(data)[1:-1].replace(':','=').replace(',','&').replace(' ','').replace('\'','')
data = requests.utils.requote_uri(data)
result = self.session.post(url,data=data).json()
# print('submitOrderRequest+++++')
# print(result)
if not result['status']:
print('提交订单失败 status = {}'.format(result['status']))
self.txtInfo.emit('提交订单失败 status = {}'.format(result['status']))
sys.exit()
print('提交订单成功')
self.txtInfo.emit('提交订单成功')
url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
data = '_json_att='
response = self.session.post(url, data=data)
pattern = re.compile('globalRepeatSubmitToken = \'(.*?)\'')
pattern2 = re.compile("key_check_isChange':'(.*?)'")
self.submitToken = pattern.findall(response.text)[0]
self.keyCheckIsChange = pattern2.findall(response.text)[0]
# print('token:{}'.format(self.submitToken))
# print('key_check_isChange:{}'.format(self.keyCheckIsChange))
# 4 getPassengerDTOs++++++++++++++++++++++++++++++++++++++++++++++++++++++
print('正在获取乘客信息')
self.txtInfo.emit('正在获取乘客信息')
url = 'https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs'
data = {
'_json_att': '',
'REPEAT_SUBMIT_TOKEN': self.submitToken
}
response = self.session.post(url, data=data)
result = response.json()
# print(result)
pdlists = self.choosePassenger(result)
#self.chooseSeat(self.seatedit.text())
# 5 checkOrderInfo++++++++++++++++++++++++++++++++++++++++++++++++++++++++
print('正在验证订单...')
self.txtInfo.emit('正在验证订单...')
self.passengerTicketStr,self.oldPassengerStr=self.combinuser(self.seatType,pdlists)
# print("passengerTicketStr:",self.passengerTicketStr)
# print("oldPassengerStr:", self.oldPassengerStr)
url = 'https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo'
data = 'cancel_flag=2&bed_level_order_num=000000000000000000000000000000&passengerTicketStr={}&oldPassengerStr={}_&tour_flag=dc&randCode=&whatsSelect=1&_json_att=&REPEAT_SUBMIT_TOKEN={}'.format(
self.passengerTicketStr,self.oldPassengerStr,self.submitToken
)
data = requests.utils.requote_uri(data)
checkOrderRrrorCount = 0
while True :
if checkOrderRrrorCount > 3:
print('验证订单失败,退出程序')
sys.exit()
response = self.session.post(url, data = data)
result = response.json()
if result['data']['submitStatus']:
print('订单验证成功')
self.txtInfo.emit('订单验证成功')
break
print("抢到的车次:",self.trainNo,"座位类型:",self.seatType)
self.txtInfo.emit("抢到的车次:"+self.trainNo+"座位类型:"+self.seatType)
# 6 getQueueCount+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
url = 'https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount'
dateGMT = time.strftime('%a %b %d %Y %H:%M:%S GMT+0800', time.strptime(self.trainDate, '%Y-%m-%d'))
# data = 'train_date={}&train_no={}&stationTrainCode={}&seatType={}&fromStationTelecode={}&toStationTelecode={}&leftTicket={}&purpose_codes=00&train_location={}&_json_att=&REPEAT_SUBMIT_TOKEN={}'.format(
# dateGMT,self.trainNo,self.trainCode,self.seatType,self.fromStationTelecode,self.toStationTelecode,self.leftTicket,self.trainLocation,self.submitToken
# )
data = {
'train_date' : dateGMT,
'train_no' : self.trainNo,
'stationTrainCode' : self.trainCode,
'seatType' : self.seatType,
'fromStationTelecode' : self.fromStationTelecode,
'toStationTelecode' : self.toStationTelecode,
'leftTicket' : self.leftTicket,
'purpose_codes' : '00',
'train_location' : self.trainLocation,
'_json_att' : '',
'REPEAT_SUBMIT_TOKEN' : self.submitToken
}
response = self.session.post(url, data = data)
print('getQueueCount++++++')
result = response.json()
print(result)
self.txtInfo.emit(str(result))
# 7 confirmSingleForQueue++++++++++++++++++++++++++++++++++++++++++++++++++
#https://kyfw.12306.cn/otn/confirmPassenger/confirmSingle
url = 'https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue'
data = {
'passengerTicketStr' : self.passengerTicketStr,
'oldPassengerStr' : self.oldPassengerStr,
'randCode' : '',
'purpose_codes' : '00',
'key_check_isChange' : self.keyCheckIsChange,
'leftTicketStr' : self.leftTicket,
'train_location' : self.trainLocation,
'choose_seats' : '',
'seatDetailType' : '000',
'whatsSelect' : '1',
'roomType' : '00',
'dwAll' : 'N',
'_json_att' : '',
'REPEAT_SUBMIT_TOKEN' : self.submitToken
}
qeueErrorCount = 0
while True:
response = self.session.post(url, data = data)
try:
result = response.json()
print('confirmSingleForQueue++++++')
print(result)
self.txtInfo.emit('confirmSingleForQueue++++++\n'+str(result))
if not result['data']['submitStatus']:
print('订票失败,重新抢票')
self.txtInfo.emit('订票失败,重新抢票')
break
else:
break
except:
qeueErrorCount += 1
# 8 queryOrderWaitTime+++++++++++++++++++++++++++++++++++++++++
waitTimeErrorCount = 0
while True:
# if waitTimeErrorCount > 10:
# print('请求次数过多,退出程序')
# sys.exit()
url = 'https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime?random={}&tourFlag=dc&_json_att=&REPEAT_SUBMIT_TOKEN={}'.format(
str(round(time.time() * 1000)),self.submitToken)
response = self.session.get(url)
result = response.json()
print(result)
self.txtInfo.emit('等待下票排队时间++++++\n'+str(result))
resultCode = result['data']['waitTime']
if resultCode == -1:
self.orderId = result['data']['orderId']
break
elif resultCode == -2:
print('取消次数过多,今日不能继续订票')
sys.exit()
else:
waitTimeErrorCount += 1
time.sleep(2.5)
# 8 resultOrderForDcQueue+++++++++++++++++++++++++++++++++++++++++
url = 'https://kyfw.12306.cn/otn/confirmPassenger/resultOrderForDcQueue'
data = 'orderSequence_no={}&_json_att=&REPEAT_SUBMIT_TOKEN={}'.format(self.orderId,self.submitToken)
resultOrderErrorCount = 0
while True:
if resultOrderErrorCount > 3:
print('查询订单错误')
sys.exit()
response = self.session.post(url, data = data)
try:
result = response.json()
print(result)
if result['data']['submitStatus']:
self.txtInfo.emit('订票成功,请登录12306查看支付')
print('订票成功,请登录12306查看')
break
except json.decoder.JSONDecodeError:
resultOrderErrorCount += 1
def paintEvent(self, event):
pass
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
table = SignWidget()
table.show()
sys.exit(app.exec_())
code12306.py 识别图片类
from model.densenet import DenseNet
from image_utils import *
import numpy as np
import time,random
import shutil
import os
n_classes = 80
image_shape = (64, 64, 3)
text_model_weight = "saves/DenseNet-BC_k=12_d=40.weight"
image_model_weight = "saves/DenseNet-BC_k=24_d=40.weight"
save_path = "/Users/jylonger/Documents/IMAGE"
save_fail_path = "/Users/jylonger/Documents/FAIL"
class code12306():
def load_model(self):
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
text_model = DenseNet(classes=n_classes, input_shape=image_shape, depth=40, growth_rate=12, bottleneck=True,
reduction=0.5, dropout_rate=0.0, weight_decay=1e-4)
image_model = DenseNet(classes=n_classes, input_shape=image_shape, depth=40, growth_rate=24, bottleneck=True,
reduction=0.5, dropout_rate=0.0, weight_decay=1e-4)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())))
text_model.load_weights(text_model_weight)
image_model.load_weights(image_model_weight)
return text_model, image_model
def load_label_dict(self):
# 读取类别名称
label_dict = {}
with open("labels.txt", encoding="utf-8") as file:
for line in file:
class_name, id = line.strip().split()
label_dict[int(id)] = class_name
return label_dict
def online_test(self,image_path,text_model, image_model, label_dict):
"""
获取验证码图片、模型识别、提交
:return:
"""
# 下载验证码图片到本地
#image_path = image_utils.download_captcha()
# 切割验证码为文字部分和图片部分
raw_texts, raw_images = process_raw_images(image_path, (image_shape[0], image_shape[1]))
# 图像转换为np数组
texts, images = np.array([np.asarray(image) for image in raw_texts]), np.array(
[np.asarray(image) for image in raw_images])
# 模型输出
text_predict = text_model.predict(texts)
image_predict = image_model.predict(images)
# 预测结果
text_result = np.argmax(text_predict, 1)
print(text_result)
image_result = np.argmax(image_predict, 1)
# 概率
text_prob = np.max(text_predict, 1)
image_prob = np.max(image_predict, 1)
# 类别名
text_label = [label_dict[r] for r in text_result]
print(text_label)
image_label = [label_dict[r] for r in image_result]
print(image_label)
ids = set()
for r1 in text_result:
for id, r2 in enumerate(image_result):
if r1 == r2:
ids.add(id)
return ids
# result = image_utils.submit_captcha(ids)
# print(result)
# if "成功" in result:
# # if save_path:
# # # 保存图片
# # for id in ids:
# # image_utils.save(raw_images[id], os.path.join(save_path, "IMG"), label_dict[image_result[id]])
# # for id, image in enumerate(raw_texts):
# # image_utils.save(image, os.path.join(save_path, "TXT"), label_dict[text_result[id]])
# return True
# else:
# if save_fail_path:
# for id,image in enumerate(raw_images):
# image_utils.save(image, os.path.join(save_fail_path, "IMG"), image_label[id])
# for id, image in enumerate(raw_texts):
# image_utils.save(image, os.path.join(save_fail_path, "TXT"), text_label[id])
# # if not os.path.exists(save_fail_path):
# # os.mkdir(save_fail_path)
# # shutil.move(image_path, save_fail_path)
# return False
if __name__ == '__main__':
code12306=code12306()
text_model, image_model = code12306.load_model()
label_dict = code12306.load_label_dict()
test_result = {True: 0, False: 0}
try:
test_result[code12306.online_test(text_model, image_model, label_dict)] += 1
time.sleep(4)
true_times, false_times = test_result[True], test_result[False]
print("%d/%d 准确率:%.3f" % (true_times, true_times + false_times, true_times / (true_times + false_times)))
except Exception as e:
time.sleep(4)
先到这里吧,有时间再记录一下