前面一段时间由于事情比较多,所以才一直没有时间发文,很感谢大家还在一直支持我,先开始我们今天的干货吧,今天要和大家介绍的是实现 12306 的火车票信息查询,从实验楼的一位小哥哥哪里学习来的,不过他的是在 Linux 下实现的,我这里为了方便大多数人的使用,改成了在 Windows + Pycharm 环境下实现,文末我会贴出小哥哥的录播地址。
效果展示:
如下图所示,这个时间北京到上海已经没有票了哟!
实现原理:
其实非常简单,主要是调用了 12306 的查询接口,得到返回数据后,再进行相应的处理,然后格式输出。
步骤如下:
寻找 12306 查询接口
理解接口是怎么样调用
找到调用接口的城市名对应的字符
编写脚本调用接口获取信息
格式输出火车票信息
找到城市名对应的字符:
这个需要我们自己去找位置,我给大家贴出了图片,在我划红线标记的位置,复制 url 链接打开,就可以看到全部的城市名和城市名对应的字符了,如下图所示。
将城市名和对应的字符,爬取下来保存到本地,注意是要将字典直接保存在本地,我给出了完整的代码,每行代码都写了详细的解析。
importrequests
importre
importjson
defmain():
# 12306 的城市名 和 城市名对应的代码 js 文件 url
url ='https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9018'
reponse = requests.get(url,verify=False)# 关闭 https 证书的验证
pattern =u'([\u4e00-\u9fa5]+)\|([A-Z]+)'# 正则表达式,匹配城市名和城市代码
result = re.findall(pattern,reponse.text)
f = open('/Users/lec/Desktop/12306.json','w')# 将字典保存在本地。
datas = dict(result)
json.dump(datas,f)
f.close()
if__name__ =='__main__':
main()
获得接口 url :
text是我们输入的信息,比如:北京 上海 2018-07-13 ,code_dict是我们上面代码所保存下来的城市名字典,详细请看代码解析。
defget_train_url(text,data_dict):
train = str(text).split(' ')# 这里的 train 分别存储了 出发站,到达站,出发日期
try:
# 分别将城市转化为对应的城市代码
from_station = data_dict[train[]]
to_station = data_dict[train[1]]
date = train[2]
except:
date,from_station,to_station ='--','--','--'# 出现无的情况,用 -- 代替
# api url 的构造,也就是找到如上图所示的初始网站信息
# https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2018-07-13&leftTicketDTO.from_station=BJP&leftTicketDTO.to_station=SHH&purpose_codes=ADULT
url = (
'https://kyfw.12306.cn/otn/leftTicket/query?'
'leftTicketDTO.train_date={}&'
'leftTicketDTO.from_station={}&'
'leftTicketDTO.to_station={}&'
'purpose_codes=ADULT'
).format(date, from_station, to_station)
print(url)
returnurl
获得火车票信息并打印:
这里有一个技巧,我们可以根据这个余票文件的代码信息,按照对应的格式找到我们需要的火车票信息,大家对应着代码看会更好理解,为了输出更加的美观,我们采用的是 prettytable 这个库,具体的使用方法,大家可以百度下,我这里就不再介绍了,详细请看代码的解析。
defget_train_data(url,code_dict):
requests.packages.urllib3.disable_warnings()# 关闭https证书验证警告
tb = PrettyTable()# 实例化一个对象
tb.field_names = ["车次","出发站","目的地","出发时间","到达时间","消耗时间","一等座","二等座","软卧","硬卧","硬座","无座"]# 创造需要的字段
try:
r = requests.get(url, verify=False)# 关闭 https 证书的验证
raw_trains = r.json()['data']['result']# 获取返回的json数据里的data部分的result结果
forraw_traininraw_trains:# 循环遍历每辆列车的信息
train_list = []# 一趟火车的全部信息
data_list = raw_train.split('|')
train_no = data_list[3]# 车次号码
train_list.append(train_no)
from_station_code = data_list[6]# 出发站
from_station_name = code_dict[from_station_code]# 将城市代码 替换成城市名字
train_list.append(from_station_name)
to_station_code = data_list[7]# 终点站
to_station_name = code_dict[to_station_code]# 将城市代码 替换成城市名字
train_list.append(to_station_name)
start_time = data_list[8]# 出发时间
train_list.append(start_time)
arrive_time = data_list[9]# 到达时间
train_list.append(arrive_time)
lishi = data_list[10]# 历时
train_list.append(lishi)
first_class_seat = data_list[31]or'--'# 一等座
train_list.append(first_class_seat)
second_class_seat = data_list[30]or'--'# 二等座
train_list.append(second_class_seat)
soft_sleep = data_list[23]or'--'# 软卧
train_list.append(soft_sleep)
hard_sleep = data_list[28]or'--'# 硬卧
train_list.append(hard_sleep)
hard_seat = data_list[29]or'--'# 硬座
train_list.append(hard_seat)
no_seat = data_list[26]or'--'# 无座
train_list.append(no_seat)
tb.add_row(train_list)#以补充行的形式来添加数据.
print(tb)# 打印查询结果
except:
print('输入信息有误,请重新输入')
好啦,截至到这里我们已经成功实现了 12306 火车票查询脚本,如果觉得还有些不明白的地方可以看看实验楼的录播,以后我们看回家有没有火车票,直接自己运行本地的脚本就可以啦,逼格更加高!
录播地址:https://www.bilibili.com/video/av12380578/
如果觉得文章还不错的话,还请大家点赞分享下。算是对「fightjiang」最大的支持!
每 天 分 享 Python 干 货
领取专属 10元无门槛券
私享最新 技术干货