最近我看到看到使用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