12306 的火车票信息查询

前面一段时间由于事情比较多,所以才一直没有时间发文,很感谢大家还在一直支持我,先开始我们今天的干货吧,今天要和大家介绍的是实现 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 干 货

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180713G1MMFJ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券