最近我看到看到使用python实现火车票查询,我自己也实现了,感觉收获蛮多的,下面我就把每一步骤都详细给分享出来。(注意使用的是python3)
首先我将最终结果给展示出来:
在cmd命令行执行:python tickets.py -dk shanghai chengdu 20161007 > result.txt
意思是:查询 上海--成都 2016.10.07 的D和K开头的列车信息,并保存到 result.txt文件中;下面就是result.txt文件中的结果:
下面的将是实现步骤:
1、安装第三方库 pip install 安装:requests,docopt,prettytable
2、docopt可以用来解析从命令行中输入的参数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
""" Usage: test [-gdtkz] <from> <to> <date> Options: -h,--help 显示帮助菜单 -g 高铁 -d 动车 -t 特快 -k 快速 -z 直达 Example: tickets -gdt beijing shanghai 2016-08-25 """ import docopt args = docopt.docopt(__doc__) print (args) # 上面 """ """ 包含中的: #Usage: # test [-gdtkz] <from> <to> <date> #是必须要的 test 是可以随便写的,不影响解析 |
最终打印的结果是一个字典,方便后面使用:
3、获取列车的信息
我们在12306的余票查询的接口:
url:https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate=2016-10-05&from_station=CDW&to_station=SHH
方法为:get
传输的参数:queryDate:2016-10-05、from_station:CDW、to_station:SHH
其中城市对应简称是需要另外的接口查询得出
3.1 查询城市对应的简称:
这个接口的url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.8968'
方法是get,对返回结果利用正则表达式,取出城市名和简称的值(返回的值类似:7@cqn|重庆南|CRW|chongqingnan|cqn|,我们需要的就是:CRW、chongqingnan),代码如下
parse_stations.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#coding=utf-8 from prettytable import PrettyTable class TrainCollection( object ): """ 解析列车信息 """ # 显示车次、出发/到达站、 出发/到达时间、历时、一等坐、二等坐、软卧、硬卧、硬座 header = '序号 车次 出发站/到达站 出发时间/到达时间 历时 商务座 一等座 二等座 软卧 硬卧 硬座 无座' .split() def __init__( self ,rows,traintypes): self .rows = rows self .traintypes = traintypes def _get_duration( self ,row): """ 获取车次运行的时间 """ duration = row.get( 'lishi' ).replace( ':' , '小时' ) + '分' if duration.startswith( '00' ): return duration[ 4 :] elif duration.startswith( '0' ): return duration[ 1 :] return duration @property def trains( self ): result = [] flag = 0 for row in self .rows: if row[ 'station_train_code' ][ 0 ] in self .traintypes: flag + = 1 train = [ # 序号 flag, # 车次 row[ 'station_train_code' ], # 出发、到达站点 '/' .join([row[ 'from_station_name' ],row[ 'to_station_name' ]]), # 成功、到达时间 '/' .join([row[ 'start_time' ],row[ 'arrive_time' ]]), # duration 时间 self ._get_duration(row), # 商务座 row[ 'swz_num' ], # 一等座 row[ 'zy_num' ], # 二等座 row[ 'ze_num' ], # 软卧 row[ 'rw_num' ], # 硬卧 row[ 'yw_num' ], # 硬座 row[ 'yz_num' ], # 无座 row[ 'wz_num' ] ] result.append(train) return result def print_pretty( self ): """打印列车信息""" pt = PrettyTable() pt._set_field_names( self .header) for train in self .trains: pt.add_row(train) print (pt) if __name__ = = '__main__' : t = TrainCollection() |
其中pprint这个模块能是打印出来的信息,更加方便阅读:
在cmd中运行:python parse_stations.py > stations.py
就会在当前目录下得到stations.py文件,文件中就是站点名字和简称,在stations.py文件中加入"stations = "这样就是一个字典,方便后面的取值,下面就是stations.py文件的内容:
3.2 现在获取列车信息的参数已经准备齐了,接下来就是拿到列车的返回值,解析出自己需要的信息,比如:车次号,一等座的票数等等。。,myprettytable.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#coding=utf-8 from prettytable import PrettyTable class TrainCollection( object ): """ 解析列车信息 """ # 显示车次、出发/到达站、 出发/到达时间、历时、一等坐、二等坐、软卧、硬卧、硬座 header = '序号 车次 出发站/到达站 出发时间/到达时间 历时 商务座 一等座 二等座 软卧 硬卧 硬座 无座' .split() def __init__( self ,rows,traintypes): self .rows = rows self .traintypes = traintypes def _get_duration( self ,row): """ 获取车次运行的时间 """ duration = row.get( 'lishi' ).replace( ':' , '小时' ) + '分' if duration.startswith( '00' ): return duration[ 4 :] elif duration.startswith( '0' ): return duration[ 1 :] return duration @property def trains( self ): result = [] flag = 0 for row in self .rows: if row[ 'station_train_code' ][ 0 ] in self .traintypes: flag + = 1 train = [ # 序号 flag, # 车次 row[ 'station_train_code' ], # 出发、到达站点 '/' .join([row[ 'from_station_name' ],row[ 'to_station_name' ]]), # 成功、到达时间 '/' .join([row[ 'start_time' ],row[ 'arrive_time' ]]), # duration 时间 self ._get_duration(row), # 商务座 row[ 'swz_num' ], # 一等座 row[ 'zy_num' ], # 二等座 row[ 'ze_num' ], # 软卧 row[ 'rw_num' ], # 硬卧 row[ 'yw_num' ], # 硬座 row[ 'yz_num' ], # 无座 row[ 'wz_num' ] ] result.append(train) return result def print_pretty( self ): """打印列车信息""" pt = PrettyTable() pt._set_field_names( self .header) for train in self .trains: pt.add_row(train) print (pt) if __name__ = = '__main__' : t = TrainCollection() |
prettytable 这个库是能打印出类似mysql查询数据显示出来的格式,
4、接下来就是整合各个模块:tickets.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
"""Train tickets query via command-line. Usage: tickets [-gdtkz] <from> <to> <date> Options: -h,--help 显示帮助菜单 -g 高铁 -d 动车 -t 特快 -k 快速 -z 直达 Example: tickets -gdt beijing shanghai 2016-08-25 """ import requests from docopt import docopt from stations import stations # from pprint import pprint from myprettytable import TrainCollection class SelectTrain( object ): def __init__( self ): """ 获取命令行输入的参数 """ self .args = docopt(__doc__) #这个是获取命令行的所有参数,返回的是一个字典 def cli( self ): """command-line interface""" # 获取 出发站点和目标站点 from_station = stations.get( self .args[ '<from>' ]) #出发站点 to_station = stations.get( self .args[ '<to>' ]) # 目的站点 leave_time = self ._get_leave_time() # 出发时间 url = 'https://kyfw.12306.cn/otn/lcxxcx/query?purpose_codes=ADULT&queryDate={0}&from_station={1}&to_station={2}' . format ( leave_time,from_station,to_station) # 拼接请求列车信息的Url # 获取列车查询结果 r = requests.get(url,verify = False ) traindatas = r.json()[ 'data' ][ 'datas' ] # 返回的结果,转化成json格式,取出datas,方便后面解析列车信息用 # 解析列车信息 traintypes = self ._get_traintype() views = TrainCollection(traindatas,traintypes) views.print_pretty() def _get_traintype( self ): """ 获取列车型号,这个函数的作用是的目的是:当你输入 -g 是只是返回 高铁,输入 -gd 返回动车和高铁,当不输参数时,返回所有的列车信息 """ traintypes = [ '-g' , '-d' , '-t' , '-k' , '-z' ] # result = [] # for traintype in traintypes: # if self.args[traintype]: # result.append(traintype[-1].upper()) trains = [traintype[ - 1 ].upper() for traintype in traintypes if self .args[traintype]] if trains: return trains else : return [ 'G' , 'D' , 'T' , 'K' , 'Z' ] def _get_leave_time( self ): """ 获取出发时间,这个函数的作用是为了:时间可以输入两种格式:2016-10-05、20161005 """ leave_time = self .args[ '<date>' ] if len (leave_time) = = 8 : return '{0}-{1}-{2}' . format (leave_time[: 4 ],leave_time[ 4 : 6 ],leave_time[ 6 :]) if '-' in leave_time: return leave_time if __name__ = = '__main__' : cli = SelectTrain() cli.cli() |
好了,基本上就结束了,按照开头的哪样,就能查询你想要的车次信息了
以上所述是小编给大家介绍的Python脚本实现12306火车票查询系统,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:http://www.cnblogs.com/xiaoshitoutest/p/5923813.html