前面已经介绍了实现登录12306(https://blog.csdn.net/zjt980452483/article/details/81167765),如果想实现免输入验证码的话,可以借助一些打码平台,这个部分大家可以去自行了解。本人已经实现过,准确率还是蛮高的,但是因为需要按次数收费,所以后面废弃了这部分代码。
简单说一下打码的思路:联系打码平台,告诉他们需要验证坐标型验证码。客服就会将相应的API文档发给你,将其中的py文件拷贝至项目路径中,根据文档中提示信息修改内容。然后从12306网站获取登录的验证码,存放在指定路径下,并将该路径和图片文件名写入打码平台提供的py文档中。运行程序后,会自动将图片发回至打码平台。平台会将正确的结果以字符串的形式反馈回来,稍作调整就可以使用了。
余票查询
这一部分,是由 user_input() 函数和 check() 两个函数组成。 user_input() 接收用户输入的信息(出发地、目的地和出发日),将 user_input() 的反馈结果传给check() ,然后打印出查询结果。这不一部分我使用未登录的状态进行查票,模拟浏览器上的操作如下:
这部分代码是在第一节基础上继续完善,补充部分的完整的代码如下:
import time
from station import stationDic,stationList
import re
def User_input():
print "++++++++++ 输入查询日期:++++++++++ "
while True:
print "参考样式\"2010-01-01\""
train_date = raw_input()
# 检查输入时间格式是否正确
try:
time.strptime(train_date, "%Y-%m-%d")
if re.match("^2018-\d\d-\d\d$",train_date):
break
else:
print '格式有误,重新输入'
except ValueError:
print '格式有误,重新输入'
print "++++++++++ 输入出发站 ++++++++++"
while True:
print "参考样式\"北京\" 、\"北京西\""
from_station = raw_input()
if from_station in stationDic.keys():
break
else:
print "未检索到站名,请重新输入"
print "++++++++++ 输入到达站 ++++++++++"
while True:
to_station = raw_input()
if to_station in stationDic.keys():
break
else:
print "为检索到站名,请重新输入"
# 返回车站汉字形式
return train_date,from_station,to_station
def check(data,from_station,to_station):
# print data,from_station,to_station
# 获取12306车次查询信息
req = urllib2.Request('https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=%s&leftTicketDTO.from_station=%s&leftTicketDTO.to_station=%s&purpose_codes=ADULT'%(data,from_station,to_station))
req.headers = headers
html = opener.open(req).read()
result = loads(html)
train_count = len(result['data']['result'])
now_time = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
print "查询到的结果有: ",train_count
station = []
for i in range(train_count):
station.append(result['data']['result'][i])
secretStrTmp = []
for i in range(train_count):
message = result['data']['result'][i]
messageList = message.split('|')
# 取出每个列表中第一个值,后续下单会用到
count = 0
secretStrTmp.insert(count,messageList[0])
count += 1
# 打印每条车次信息的详细情况
if messageList[0] != 'null':
print u'''
车次:\033[41;1m%s\033[0m''' %( messageList[3]),
print "出发站:%s 到达站:%s" %(stationList[from_station], stationList[to_station]),
print u'''
出发时间:%s 到达时间:%s 历时:%s 高级软卧:\033[1;32;1m %-10s \033[0m 软卧:\033[1;32;1m %-10s \033[0m 硬卧:\033[1;32;1m %5s \033[0m 软座:\033[1;32;1m %5s \033[0m 硬座:\033[1;32;1m %5s \033[0m 无座:\033[1;32;1m %5s \033[0m'''\
%( messageList[8], messageList[9], messageList[10],messageList[21], messageList[23], messageList[28], messageList[24], messageList[29], messageList[26]),
# print " 火车始发站:%s 终点站:%s"%(stationList[messageList[4]], stationList[messageList[5]])
# 此处手动在站点字典中添加“九龙”信息
print ' '
return station
train_date,from_station,to_station = User_input()
station= check(train_date,stationDic[from_station],stationDic[to_station])
其中" from station import stationDic,stationList "所提及的 station,是为我自定义station.py文件,用于存放12306提供全国铁路网所有车站名及车站识别码,因为里面的内容过长,这里只贴出部分内容的截图和获取方法,完整内容既可以从浏览器中下载,也从我提供的源代码中找到
从浏览器中获取station信息的方法如下:
一、输入搜索条件
定义函数 user_input() 接收用户输入的参数,返回对应的字符串用于后续查询条件
1.输入查询日期
print "++++++++++ 输入查询日期:++++++++++ "
while True:
print "参考样式\"2010-01-01\""
train_date = raw_input()
# 检查输入时间格式是否正确
try:
time.strptime(train_date, "%Y-%m-%d")
if re.match("^2018-\d\d-\d\d$",train_date):
break
else:
print '格式有误,重新输入'
except ValueError:
print '格式有误,重新输入'
利用 time.strptime() 检验用户输入的时间格式,要求必须是“2018-07-25”;利用while死循环和异常的特点,直到检测到输入正确的结果才跳出循环
2.输入出发站
print "++++++++++ 输入出发站 ++++++++++"
while True:
print "参考样式\"北京\" 、\"北京西\""
from_station = raw_input()
if from_station in stationDic.keys():
break
else:
print "未检索到站名,请重新输入"
print "++++++++++ 输入到达站 ++++++++++"
while True:
to_station = raw_input()
if to_station in stationDic.keys():
break
else:
print "为检索到站名,请重新输入"
# 返回车站汉字形式
return train_date,from_station,to_station
此处需要将用户输入的车站名,输入到station文件中stationDic字典中进行检查,如果存在,则说明输入合格.
注意,此处返回的直接是用户输入的中文字符串。后面有的地方需要将地名转换成响应的识别码如 北京北:bjb;