python第三方库PrettyTable使用实例
Posted jason89
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python第三方库PrettyTable使用实例相关的知识,希望对你有一定的参考价值。
一、简介
PrettyTable 是python中的一个第三方库,可用来生成美观的ASCII格式的表格,十分实用。
二、安装
在保证能够通外网的情况下执行命令:pip install PrettyTable安装即可。
三、基本使用实例
import prettytable as pt #直接创建表 tb = pt.PrettyTable() #表头字段 tb.field_names = ["City name", "Area", "Population", "Annual Rainfall"] #按行添加数据 tb.add_row(["Adelaide",1295, 1158259, 600.5]) tb.add_row(["Brisbane",5905, 1857594, 1146.4]) tb.add_row(["Darwin", 112, 120900, 1714.7]) tb.add_row(["Hobart", 1357, 205556,619.5]) print(tb) 输出结果: +-----------+------+------------+-----------------+ | City name | Area | Population | Annual Rainfall | +-----------+------+------------+-----------------+ | Adelaide | 1295 | 1158259 | 600.5 | | Brisbane | 5905 | 1857594 | 1146.4 | | Darwin | 112 | 120900 | 1714.7 | | Hobart | 1357 | 205556 | 619.5 | +-----------+------+------------+-----------------+
#按列添加数据 tb.add_column(‘index‘,[1,2,3,4]) print(tb) +-----------+------+------------+-----------------+-------+ | City name | Area | Population | Annual Rainfall | index | +-----------+------+------------+-----------------+-------+ | Adelaide | 1295 | 1158259 | 600.5 | 1 | | Brisbane | 5905 | 1857594 | 1146.4 | 2 | | Darwin | 112 | 120900 | 1714.7 | 3 | | Hobart | 1357 | 205556 | 619.5 | 4 | +-----------+------+------------+-----------------+-------+ #使用不同的输出风格 tb.set_style(pt.MSWORD_FRIENDLY) print(‘--- style:MSWORD_FRIENDLY -----‘) print(tb) --- style:MSWORD_FRIENDLY ----- | City name | Area | Population | Annual Rainfall | | Adelaide | 1295 | 1158259 | 600.5 | | Brisbane | 5905 | 1857594 | 1146.4 | | Darwin | 112 | 120900 | 1714.7 | | Hobart | 1357 | 205556 | 619.5 | tb.set_style(pt.PLAIN_COLUMNS) print(‘--- style:PLAIN_COLUMNS -----‘) print(tb) --- style:PLAIN_COLUMNS ----- City name Area Population Annual Rainfall Adelaide 1295 1158259 600.5 Brisbane 5905 1857594 1146.4 Darwin 112 120900 1714.7 Hobart 1357 205556 619.5 #随机风格,每次不同 tb.set_style(pt.RANDOM) print(‘--- style:MSWORD_FRIENDLY -----‘) print(tb) --- style:MSWORD_FRIENDLY ----- @ Adelaide 1295 1158259 600.5 @ @ Brisbane 5905 1857594 1146.4@ @ Darwin 112 120900 1714.7@ @ Hobart 1357 205556 619.5 @ tb.set_style(pt.DEFAULT) print(‘--- style:DEFAULT -----‘) print(tb) --- style:DEFAULT ----- +-----------+------+------------+-----------------+ | City name | Area | Population | Annual Rainfall | +-----------+------+------------+-----------------+ | Adelaide | 1295 | 1158259 | 600.5 | | Brisbane | 5905 | 1857594 | 1146.4 | | Darwin | 112 | 120900 | 1714.7 | | Hobart | 1357 | 205556 | 619.5 | +-----------+------+------------+-----------------+ #不打印,获取表格字符串 s = tb.get_string() print(s) +-----------+------+------------+-----------------+ | City name | Area | Population | Annual Rainfall | +-----------+------+------------+-----------------+ | Adelaide | 1295 | 1158259 | 600.5 | | Brisbane | 5905 | 1857594 | 1146.4 | | Darwin | 112 | 120900 | 1714.7 | | Hobart | 1357 | 205556 | 619.5 | +-----------+------+------------+-----------------+ ## 可以只获取指定列或行 s = tb.get_string(fields=["City name", "Population"],start=1,end=4) print(s) +-----------+------------+ | City name | Population | +-----------+------------+ | Brisbane | 1857594 | | Darwin | 120900 | | Hobart | 205556 | +-----------+------------+ # 自定义表格输出样式 #设定左对齐 tb.align = ‘l‘ #设定数字输出格式 tb.float_format = "2.2" #设定边框连接符为‘*" tb.junction_char = "*" #设定排序方式 tb.sortby = "City name" #设定左侧不填充空白字符 tb.left_padding_width = 0 print(tb) *----------*-----*-----------*----------------* |City name |Area |Population |Annual Rainfall | *----------*-----*-----------*----------------* |Adelaide |1295 |1158259 |600.50 | |Brisbane |5905 |1857594 |1146.40 | |Darwin |112 |120900 |1714.70 | |Hobart |1357 |205556 |619.50 | *----------*-----*-----------*----------------*
#不显示边框 tb.border = 0 print(tb) City name Area Population Annual Rainfall Adelaide 1295 1158259 600.50 Brisbane 5905 1857594 1146.40 Darwin 112 120900 1714.70 Hobart 1357 205556 619.50 #修改边框分隔符 tb.set_style(pt.DEFAULT) tb.horizontal_char = ‘+‘ print(tb) +++++++++++++++++++++++++++++++++++++++++++++++++++ | City name | Area | Population | Annual Rainfall | +++++++++++++++++++++++++++++++++++++++++++++++++++ | Adelaide | 1295 | 1158259 | 600.50 | | Brisbane | 5905 | 1857594 | 1146.40 | | Darwin | 112 | 120900 | 1714.70 | | Hobart | 1357 | 205556 | 619.50 | +++++++++++++++++++++++++++++++++++++++++++++++++++
#prettytable也支持输出HTML代码 s = tb.get_html_string() print(s) <table> <tr> <th>City name</th> <th>Area</th> <th>Population</th> <th>Annual Rainfall</th> </tr> <tr> <td>Adelaide</td> <td>1295</td> <td>1158259</td> <td>600.50</td> </tr> <tr> <td>Brisbane</td> <td>5905</td> <td>1857594</td> <td>1146.40</td> </tr> <tr> <td>Darwin</td> <td>112</td> <td>120900</td> <td>1714.70</td> </tr> <tr> <td>Hobart</td> <td>1357</td> <td>205556</td> <td>619.50</td> </tr> </table> #使用copy方法复制对象 #tb.set_style(pt.DEFAULT) tb.horizontal_char = ‘.‘ tb2 = tb.copy() tb.align = ‘l‘ tb2.align = ‘r‘ print(tb) print(tb2) +...........+......+............+.................+ | City name | Area | Population | Annual Rainfall | +...........+......+............+.................+ | Adelaide | 1295 | 1158259 | 600.50 | | Brisbane | 5905 | 1857594 | 1146.40 | | Darwin | 112 | 120900 | 1714.70 | | Hobart | 1357 | 205556 | 619.50 | +...........+......+............+.................+ +...........+......+............+.................+ | City name | Area | Population | Annual Rainfall | +...........+......+............+.................+ | Adelaide | 1295 | 1158259 | 600.50 | | Brisbane | 5905 | 1857594 | 1146.40 | | Darwin | 112 | 120900 | 1714.70 | | Hobart | 1357 | 205556 | 619.50 | +...........+......+............+.................+ #直接赋值,得到的是索引 tb.horizontal_char = ‘-‘ tb.aliign = ‘l‘ tb3 = tb tb3.align = ‘r‘ print(tb) print(tb3) +-----------+------+------------+-----------------+ | City name | Area | Population | Annual Rainfall | +-----------+------+------------+-----------------+ | Adelaide | 1295 | 1158259 | 600.50 | | Brisbane | 5905 | 1857594 | 1146.40 | | Darwin | 112 | 120900 | 1714.70 | | Hobart | 1357 | 205556 | 619.50 | +-----------+------+------------+-----------------+ +-----------+------+------------+-----------------+ | City name | Area | Population | Annual Rainfall | +-----------+------+------------+-----------------+ | Adelaide | 1295 | 1158259 | 600.50 | | Brisbane | 5905 | 1857594 | 1146.40 | | Darwin | 112 | 120900 | 1714.70 | | Hobart | 1357 | 205556 | 619.50 | +-----------+------+------------+-----------------+
四、查询12306余票信息
首先我们来看看每查询一条信息12306网站返回的信息:
请求链接:
https://kyfw.12306.cn/otn/leftTicket/queryO?leftTicketDTO.train_date=2018-01-31&leftTicketDTO.from_station=XAY&leftTicketDTO.to_station=GZG&purpose_codes=ADULT
很显然我们只需要关注三个参数:train_date,from_station,to_station。
#获得result
1 import requests 2 import urllib 3 import json 5 """获取data""" 6 def getData(url): 7 data = ‘‘ 8 while 1: 9 try: 10 headers = {‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0‘} 11 12 # 关键代码:############################################### 13 14 req = urllib.request.Request(url=url, headers=headers) 15 16 data = urllib.request.urlopen(req).read().decode(‘utf-8‘) 17 18 ########################################################### 19 if data.startswith(u‘ufeff‘): 20 data = data.encode(‘utf8‘)[3:].decode(‘utf-8‘) 21 break 22 except: 23 continue 24 return data 25 26 """获取result""" 27 28 def resolveData(): 29 #查询链接 30 url = ‘https://kyfw.12306.cn/otn/leftTicket/queryO?leftTicketDTO.train_date=2018-01-31&leftTicketDTO.from_station=XAY&leftTicketDTO.to_station=GZG&purpose_codes=ADULT‘ 31 32 #获取数据 33 while 1: 34 try: 35 data = getData(url) 36 lists = json.loads(data)["data"]["result"] 37 break 38 except: 39 continue#获取失败则重新获取 40 for item in lists:#打印result信息 41 print(item)
调用resolveData():
观察这一长串字符我们还是能发现规律的,所有的信息都以"|"为分割线,图中已经显示了一些信息,其他信息需要我们观察多个result结果才能找出对应位置。
解析result信息:
1 """获取result""" 2 3 def resolveData(): 4 5 #查询链接 6 7 url = ‘https://kyfw.12306.cn/otn/leftTicket/queryO?leftTicketDTO.train_date=2018-01-31&leftTicketDTO.from_station=XAY&leftTicketDTO.to_station=GZG&purpose_codes=ADULT‘ #获取数据 8 9 while 1: 10 11 try: 12 13 data = getData(url) 14 15 lists = json.loads(data)["data"]["result"] 16 17 break 18 19 except: 20 21 continue 22 23 cont = [] 24 25 name = [ 26 27 "station_train_code", 28 29 "from_station_name", 30 31 ‘start_time‘, 32 33 "lishi", 34 35 "swz_num", 36 37 "zy_num", 38 39 "ze_num", 40 41 "gr_num", 42 43 "rw_num", 44 45 "dw_num", 46 47 "yw_num", 48 49 "rz_num", 50 51 "yz_num", 52 53 "wz_num", 54 55 "qt_num", 56 57 "note_num" 58 59 ] 60 61 62 63 for items in lists:#遍历result的每一项 64 65 #data字典用于存放每一车次的余票信息 66 67 data = { 68 69 "station_train_code": ‘‘, 70 71 "from_station_name": ‘‘, 72 73 "to_station_name": ‘‘, 74 75 ‘start_time‘: ‘‘, 76 77 ‘end‘: ‘‘, 78 79 "lishi": ‘‘, 80 81 "swz_num": ‘‘, 82 83 "zy_num": ‘‘, 84 85 "ze_num": ‘‘, 86 87 "dw_num": ‘‘, 88 89 "gr_num": ‘‘, 90 91 "rw_num": ‘‘, 92 93 "yw_num": ‘‘, 94 95 "rz_num": ‘‘, 96 97 "yz_num": ‘‘, 98 99 "wz_num": ‘‘, 100 101 "qt_num": ‘‘, 102 103 "note_num": ‘‘ 104 105 } 106 107 item = items.split(‘|‘)#用"|"进行分割 108 109 data[‘station_train_code‘] = item[3]#车次在3号位置 110 111 data[‘from_station_name‘] = item[6]#始发站信息在6号位置 112 113 data[‘to_station_name‘] = item[7]#终点站信息在7号位置 114 115 data[‘start_time‘] = item[8]#出发时间信息在8号位置 116 117 data[‘arrive_time‘] = item[9]#抵达时间在9号位置 118 119 data[‘lishi‘] = item[10]#经历时间在10号位置 120 121 data[‘swz_num‘] = item[32] or item[25]# 特别注意:商务座在32或25位置 122 123 data[‘zy_num‘] = item[31]#一等座信息在31号位置 124 125 data[‘ze_num‘] = item[30]#二等座信息在30号位置 126 127 data[‘gr_num‘] = item[21]#高级软卧信息在31号位置 128 129 data[‘rw_num‘] = item[23]#软卧信息在23号位置 130 131 data[‘dw_num‘] = item[27]#动卧信息在27号位置 132 133 data[‘yw_num‘] = item[28]#硬卧信息在28号位置 134 135 data[‘rz_num‘] = item[24]#软座信息在24号位置 136 137 data[‘yz_num‘] = item[29]#硬座信息在29号位置 138 139 data[‘wz_num‘] = item[26]#无座信息在26号位置 140 141 data[‘qt_num‘] = item[22]#其他信息在22号位置 142 143 data[‘note_num‘] = item[1]#备注在1号位置 144 145 146 147 #如果没有信息则用“-”代替 148 149 for pos in name: 150 151 if data[pos] == ‘‘: 152 153 data[pos] = ‘-‘ 154 155 156 157 cont.append(data) 158 159 tickets = []#存放所有车次的余票信息 160 161 #格式化添加进tickets中 162 163 for x in cont: 164 165 tmp = [] 166 167 for y in name: 168 169 if y == "from_station_name": 170 171 s = stations2CN[x[y]] + ‘--‘ + stations2CN[x["to_station_name"]] 172 173 tmp.append(s) 174 175 elif y == "start_time": 176 177 s = x[y] + ‘--‘ + x["arrive_time"] 178 179 tmp.append(s) 180 181 elif y == "station_train_code": 182 183 s = x[y] 184 185 tmp.append(s) 186 187 else: 188 189 tmp.append(x[y]) 190 191 tickets.append(tmp) 192 193 return tickets#返回所有车次余票信息 194 195 196 197 if __name__ == "__main__":#main方法 198 199 tickets = resolveData() 200 201 for ticket in tickets: 202 203 print(ticket)
同12306官网进行对比,查询解析准确。搞定!
下一步我们将使数据输出的更加漂亮。
1 #打印车票函数: 2 from prettytable import PrettyTable 3 #显示查询结果 4 def display(tickets): 5 ptable = PrettyTable(‘车次 出发/到达站 出发/到达时间 历时 商务座 一等座 二等座 高级软卧 软卧 动卧 硬卧 软座 硬座 无座 其他 备注‘.split(‘ ‘)) 6 for ticket in tickets: 7 ptable.add_row(ticket) 8 print(ptable) 9 10 if __name__ == "__main__":#main方法 11 tickets = resolveData() 12 display(tickets) 13 input(‘按任意键退出...‘)
使用了prettytable后使输出十分规整,现在我想为这一表格中的字体加上颜色,我们需要使用colorama。
环境安装:pip install colorama
创建一个专门用于更改颜色的类Colored并且添加相应方法:
1 from colorama import init, Fore, Back, Style 2 3 init(autoreset=False) 4 class Colored(object): 5 # 前景色:红色 背景色:默认 6 def red(self, s): 7 return Fore.LIGHTRED_EX + s + Fore.RESET 8 # 前景色:绿色 背景色:默认 9 def green(self, s): 10 return Fore.LIGHTGREEN_EX + s + Fore.RESET 11 def yellow(self, s): 12 return Fore.LIGHTYELLOW_EX + s + Fore.RESET 13 def white(self,s): 14 return Fore.LIGHTWHITE_EX + s + Fore.RESET 15 def blue(self,s): 16 return Fore.LIGHTBLUE_EX + s + Fore.RESET
现在我们使用这个类,修改resolveData()函数的部分代码:
def resolveData(): #查询链接 url = ‘https://kyfw.12306.cn/otn/leftTicket/queryO?leftTicketDTO.train_date=2018-01-31&leftTicketDTO.from_station=XAY&leftTicketDTO.to_station=GZG&purpose_codes=ADULT‘ #获取数据 while 1: try: data = getData(url) lists = json.loads(data)["data"]["result"] break except: continue cont = [] name = [ "station_train_code", "from_station_name", ‘start_time‘, "lishi", "swz_num", "zy_num", "ze_num", "gr_num", "rw_num", "dw_num", "yw_num", "rz_num", "yz_num", "wz_num", "qt_num", "note_num" ] color = Colored()#创建Colored对象 for items in lists:#遍历result的每一项 #data字典用于存放每一车次的余票信息 data = { "station_train_code": ‘‘, "from_station_name": ‘‘, "to_station_name": ‘‘, ‘start_time‘: ‘‘, ‘end‘: ‘‘, "lishi": ‘‘, "swz_num": ‘‘, "zy_num": ‘‘, "ze_num": ‘‘, "dw_num": ‘‘, "gr_num": ‘‘, "rw_num": ‘‘, "yw_num": ‘‘, "rz_num": ‘‘, "yz_num": ‘‘, "wz_num": ‘‘, "qt_num": ‘‘, "note_num": ‘‘ } item = items.split(‘|‘)#用"|"进行分割 data[‘station_train_code‘] = item[3]#车次在3号位置 data[‘from_station_name‘] = item[6]#始发站信息在6号位置 data[‘to_station_name‘] = item[7]#终点站信息在7号位置 data[‘start_time‘] = item[8]#出发时间信息在8号位置 data[‘arrive_time‘] = item[9]#抵达时间在9号位置 data[‘lishi‘] = item[10]#经历时间在10号位置 data[‘swz_num‘] = item[32] or item[25]# 特别注意:商务座在32或25位置 data[‘zy_num‘] = item[31]#一等座信息在31号位置 data[‘ze_num‘] = item[30]#二等座信息在30号位置 data[‘gr_num‘] = item[21]#高级软卧信息在31号位置 data[‘rw_num‘] = item[23]#软卧信息在23号位置 data[‘dw_num‘] = item[27]#动卧信息在27号位置 data[‘yw_num‘] = item[28]#硬卧信息在28号位置 data[‘rz_num‘] = item[24]#软座信息在24号位置 data[‘yz_num‘] = item[29]#硬座信息在29号位置 data[‘wz_num‘] = item[26]#无座信息在26号位置 data[‘qt_num‘] = item[22]#其他信息在22号位置 if item[0] == ‘null‘: data[‘note_num‘] = item[1] else: data[‘note_num‘] = color.white(item[1])#加高亮白色 #如果没有信息则用“-”代替 for pos in name: if data[pos] == ‘‘: data[pos] = ‘-‘ cont.append(data) tickets = []#存放所有车次的余票信息 #格式化添加进tickets中 for x in cont: tmp = [] for y in name: if y == "from_station_name": s = color.green(stations2CN[x[y]]) + ‘ ‘ + color.red(stations2CN[x["to_station_name"]])#始发站绿色,终点站红色 tmp.append(s) elif y == "start_time": s = color.green(x[y]) + ‘ ‘ + color.red(x["arrive_time"]) tmp.append(s) elif y == "station_train_code": s = color.yellow(x[y]) tmp.append(s) else: tmp.append(x[y]) tickets.append(tmp) return tickets#返回所有车次余票信息
我们能实现很漂亮的输出了,可是只是固定时间固定车站之间的车票信息,在本次中我们使用docopt来实现命令行的参数输入,从而查询任意时间任意两个车站的余票。
环境安装:pip install docopt
使用docopt实现命令行的输入:
1 """Train tickets query via command-line. 2 Usage: 3 tickets <from> <to> <date> 4 5 Options: 6 -h,--help 显示帮助菜单 7 from 出发车站 8 to 终点站 9 date 出发日期 10 11 Example: 12 filename 南京 北京 2016-07-01 13 """ 14 from docopt import docopt 15 16 def cli(): 17 """command-line interface""" 18 arguments = docopt(__doc__)
在main函数中调用cli()方法并打印arguments:
成功的通过命令行传递查询参数。
接下来我们只需要稍微修改一下resolveData函数就行了。
修改两行:
1 def resolveData(from_station,to_station,from_date): 2 #查询链接 3 url = ‘https://kyfw.12306.cn/otn/leftTicket/queryO?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT‘.format(from_date, stations2CODE[from_station],stations2CODE[to_station]) #获取数据
stations2CODE将输入的车站名转换成12306规定的代码。这是一个字典,具体在stationInfo.py中。
在cli()函数中调用修改后的resolveData方法并打印表格:
1 def cli(): 2 """command-line interface""" 3 arguments = docopt(__doc__) 4 tickets = resolveData(arguments[‘<from>‘], arguments[‘<to>‘], arguments[‘<date>‘]) 5 display(tickets)
添加票价信息:
票价的查询根据前面result的解析是无法获取的,票价需要另外发送请求获取。
请求链接:
https://kyfw.12306.cn/otn/leftTicket/queryTicketPrice?train_no=88000K131008&from_station_no=12&to_station_no=27&seat_types=1413&train_date=2018-01-30
关注train_no、from_station_no、to_station_no、seat_types、train_date这几个参数。
有了前面教程解析车票信息result的基础解析车票也是大同小异罢了,找出对应车票类型对应的票价对应的位置就行。
实现获取车票票价的函数:
1 #pricesDic用于存放票价信息 2 pricesDic = { 3 ‘A‘: ‘‘, 4 ‘B‘: ‘‘, 5 ‘C‘: ‘‘, 6 ‘D‘: ‘‘, 7 ‘E‘: ‘‘, 8 ‘F‘: ‘‘, 9 ‘G‘: ‘‘, 10 ‘H‘: ‘‘, 11 ‘I‘: ‘‘, 12 ‘J‘: ‘‘ 13 } 14 15 def getPrice(threadname,train_no, from_station_no, to_station_no, seat_types, date,pricesDic): 16 while 1: 17 try: 18 headers = {‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0‘} 19 moneyUrl = "https://kyfw.12306.cn/otn/leftTicket/queryTicketPrice?train_no={}&from_station_no={}&to_station_no={}&seat_types={}&train_date={}".format( 20 train_no, from_station_no, to_station_no, seat_types, date) 21 req = urllib.request.Request(url=moneyUrl, headers=headers) 22 r_price = urllib.request.urlopen(req).read().decode(‘utf-8‘) 23 if r_price.startswith(u‘ufeff‘): 24 r_price = r_price.encode(‘utf8‘)[3:].decode(‘utf-8‘) 25 # print(r_price) 26 r_price = json.loads(r_price) 27 break 28 except: 29 continue 30 price = r_price[‘data‘] 31 price = dict(price)#获取data字典,票价信息在字典中 32 A = (‘A9‘ in price.keys())#商务座票价对应key是A9或者P 33 if A == False: 34 A = (‘P‘ in price.keys()) 35 if A == False: 36 A = ‘‘ 37 else: 38 A = price[‘P‘] 39 else: 40 A = price[‘A9‘] 41 42 B = (‘M‘ in price.keys())#一等座对应key为M 43 if B == False: 44 B = ‘‘ 45 else: 46 B = price[‘M‘] 47 C = (‘O‘ in price.keys())#二等座对应key为O 48 if C == False: 49 C = ‘‘ 50 else: 51 C = price[‘O‘] 52 D = (‘A6‘ in price.keys()) 53 if D == False: 54 D = ‘‘ 55 else: 56 D = price[‘A6‘] 57 E = (‘A4‘ in price.keys()) 58 if E == False: 59 E = ‘‘ 60 else: 61 E = price[‘A4‘] 62 F = (‘F‘ in price.keys()) 63 if F == False: 64 F = ‘‘ 65 else: 66 F = price[‘F‘] 67 G = (‘A3‘ in price.keys()) 68 if G == False: 69 G = ‘‘ 70 else: 71 G = price[‘A3‘] 72 73 H = (‘A2‘ in price.keys()) 74 if H == False: 75 H = ‘‘ 76 else: 77 H = price[‘A2‘] 78 I = (‘A1‘ in price.keys()) 79 if I == False: 80 I = ‘‘ 81 else: 82 I = price[‘A1‘] 83 84 J = (‘WZ‘ in price.keys()) 85 if J == False: 86 J = ‘‘ 87 else: 88 J = price[‘WZ‘] 89 pricesDic[‘A‘] = A 90 pricesDic[‘B‘] = B 91 pricesDic[‘C‘] = C 92 pricesDic[‘D‘] = D 93 pricesDic[‘E‘] = E 94 pricesDic[‘F‘] = F 95 pricesDic[‘G‘] = G 96 pricesDic[‘H‘] = H 97 pricesDic[‘I‘] = I 98 pricesDic[‘J‘] = J
我实现查询票价使用了Python中的线程,另外开启一个线程去查询票价:
1 import threading 2 3 threadLock = threading.Lock() 4 class myThread (threading.Thread): 5 def __init__(self, threadID, threadName, train_no, from_station_no, to_station_no, seat_types, date,pricesDic): 6 threading.Thread.__init__(self) 7 self.threadID = threadID 8 self.threadName = threadName 9 self.train_no = train_no 10 self.from_station_no = from_station_no 11 self.to_station_no = to_station_no 12 self.seat_types = seat_types 13 self.date = date 14 self.pricesDic = pricesDic 15 def run(self): 16 #print ("开始线程:" + self.threadName) 17 # 获取锁,用于线程同步 18 threadLock.acquire() 19 getPrice(self.threadName, self.train_no, self.from_station_no, self.to_station_no, self.seat_types, self.date, self.pricesDic) 20 # 释放锁,开启下一个线程 21 threadLock.release() 22 #print ("退出线程:" + self.threadName)
在resolveData函数中开启线程查询票价,并且将票价加入余票信息中:
再次修改resolveData函数,观察变化:
1 def resolveData(from_station, to_station, date): 2 #拼接出查询链接 3 url = ‘https://kyfw.12306.cn/otn/leftTicket/queryO?leftTicketDTO.train_date={}&leftTicketDTO.from_station={}&leftTicketDTO.to_station={}&purpose_codes=ADULT‘.format(date, stations2CODE[from_station], stations2CODE[to_station]) 4 #获取数据 5 while 1: 6 try: 7 data = getData(url) 8 lists = json.loads(data)["data"]["result"] 9 # if data[‘status‘] == False: 10 # print(‘获取失败!请检查网络‘) 11 # break 12 break 13 except: 14 continue 15 cont = [] 16 name = [ 17 "station_train_code", 18 "from_station_name", 19 ‘start_time‘, 20 "lishi", 21 "swz_num", 22 "zy_num", 23 "ze_num", 24 "gr_num", 25 "rw_num", 26 "dw_num", 27 "yw_num", 28 "rz_num", 29 "yz_num", 30 "wz_num", 31 "qt_num", 32 "note_num" 33 ] 34 color = Colored() 35 for items in lists: 36 data = { 37 "station_train_code": ‘‘, 38 "from_station_name": ‘‘, 39 "to_station_name": ‘‘, 40 ‘start_time‘: ‘‘, 41 ‘end‘: ‘‘, 42 "lishi": ‘‘, 43 "swz_num": ‘‘, 44 "zy_num": ‘‘, 45 "ze_num": ‘‘, 46 "dw_num": ‘‘, 47 "gr_num": ‘‘, 48 "rw_num": ‘‘, 49 "yw_num": ‘‘, 50 "rz_num": ‘‘, 51 "yz_num": ‘‘, 52 "wz_num": ‘‘, 53 "qt_num": ‘‘, 54 "note_num": ‘‘ 55 } 56 item = items.split(‘|‘) 57 data[‘station_train_code‘] = item[3] 58 data[‘from_station_name‘] = item[6] 59 data[‘to_station_name‘] = item[7] 60 data[‘start_time‘] = item[8] 61 data[‘arrive_time‘] = item[9] 62 data[‘lishi‘] = item[10] 63 data[‘swz_num‘] = item[32] or item[25]# 商务座在32或25位置 64 data[‘zy_num‘] = item[31] 65 data[‘ze_num‘] = item[30] 66 data[‘gr_num‘] = item[21] 67 data[‘rw_num‘] = item[23] 68 data[‘dw_num‘] = item[27] 69 data[‘yw_num‘] = item[28] 70 data[‘rz_num‘] = item[24] 71 data[‘yz_num‘] = item[29] 72 data[‘wz_num‘] = item[26] 73 data[‘qt_num‘] = item[22] 74 if item[0] == ‘null‘: 75 data[‘note_num‘] = item[1] 76 else: 77 data[‘note_num‘] = color.white(item[1]) 78 #解析出查询票价需要的参数 79 train_no = item[2] 80 from_station_no = item[16] 81 to_station_no = item[17] 82 types = item[35] 83 getPriceThread = myThread(1, "Thread-1", train_no, from_station_no, to_station_no, types, date, pricesDic) 84 getPriceThread.start()#开启查询车票的线程 85 for pos in name: 86 if data[pos] == ‘‘: 87 data[pos] = ‘-‘ 88 threadLock.acquire()#必须加锁,这是为了线程同步 89 for pos in priceName:#将票价添加进余票信息中 90 if pos == ‘swz_num‘: 91 data[‘swz_num‘] = data[‘swz_num‘] +‘ ‘+ color.blue(pricesDic[‘A‘]) 92 if pos == ‘zy_num‘: 93 data[‘zy_num‘] = data[‘zy_num‘] +‘ ‘+ color.blue(pricesDic[‘B‘]) 94 if pos == ‘ze_num‘: 95 data[‘ze_num‘] = data[‘ze_num‘] +‘ ‘+ color.blue(pricesDic[‘C‘]) 96 if pos == ‘gr_num‘: 97 data[‘gr_num‘] = data[‘gr_num‘] +‘ ‘+ color.blue(pricesDic[‘D‘]) 98 if pos == ‘rw_num‘: 99 data[‘rw_num‘] = data[‘rw_num‘] +‘ ‘+ color.blue(pricesDic[‘E‘]) 100 if pos == ‘dw_num‘: 101 data[‘dw_num‘] = data[‘dw_num‘] +‘ ‘+ color.blue(pricesDic[‘F‘]) 102 if pos == ‘yw_num‘: 103 data[‘yw_num‘] = data[‘yw_num‘] +‘ ‘+ color.blue(pricesDic[‘G‘]) 104 if pos == ‘rz_num‘: 105 data[‘rz_num‘] = data[‘rz_num‘] +‘ ‘+ color.blue(pricesDic[‘H‘]) 106 if pos == ‘yz_num‘: 107 data[‘yz_num‘] = data[‘yz_num‘] +‘ ‘+ color.blue(pricesDic[‘I‘]) 108 if pos == ‘wz_num‘: 109 data[‘wz_num‘] = data[‘wz_num‘] +‘ ‘+ color.blue(pricesDic[‘J‘]) 110 threadLock.release() 111 cont.append(data) 112 color = Colored() 113 tickets = [] 114 for x in cont: 115 tmp = [] 116 for y in name: 117 if y == "from_station_name": 118 s = color.green(stations2CN[x[y]]) + ‘ ‘ + color.red(stations2CN[x["to_station_name"]]) 119 tmp.append(s) 120 elif y == "start_time": 121 s = color.green(x[y]) + ‘ ‘ + color.red(x["arrive_time"]) 122 tmp.append(s) 123 elif y == "station_train_code": 124 s = color.yellow(x[y]) 125 tmp.append(s) 126 else: 127 tmp.append(x[y]) 128 tickets.append(tmp) 129 return tickets#返回所有车次余票信息
最终测试:
成功获取票价!
到这来为止我们就结束了DOS界面的开发。源代码:
链接:https://pan.baidu.com/s/1c1Gdxra 密码:6xpz
我在此基础上实现了连续多天的查询,并且实现了列车类型的过滤,
源代码在此:链接:https://pan.baidu.com/s/1jI2Ak4Y 密码:02gu
转载原文:https://blog.csdn.net/qq_25343557/article/details/78965044