python第三方库PrettyTable使用实例,,一、简介Pretty


一、简介

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 = 0print(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 = 0print(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 = tbtb3.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 break22 except:23 continue24 return data25 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 break38 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.RESET11     def yellow(self, s):12         return Fore.LIGHTYELLOW_EX + s + Fore.RESET13     def white(self,s):14         return Fore.LIGHTWHITE_EX + s + Fore.RESET15     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]]) + ‘\n‘ + color.red(stations2CN[x["to_station_name"]])#始发站绿色,终点站红色                tmp.append(s)            elif y == "start_time":                s = color.green(x[y]) + ‘\n‘ + 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-0113 """14 from docopt import docopt15 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 break28 except:29 continue30 price = r_price[‘data‘]31 price = dict(price)#获取data字典,票价信息在字典中32 A = (‘A9‘ in price.keys())#商务座票价对应key是A9或者P33 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为M43 if B == False:44 B = ‘‘45 else:46 B = price[‘M‘]47 C = (‘O‘ in price.keys())#二等座对应key为O48 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‘] = A90 pricesDic[‘B‘] = B91 pricesDic[‘C‘] = C92 pricesDic[‘D‘] = D93 pricesDic[‘E‘] = E94 pricesDic[‘F‘] = F95 pricesDic[‘G‘] = G96 pricesDic[‘H‘] = H97 pricesDic[‘I‘] = I98 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_no10 self.from_station_no = from_station_no11 self.to_station_no = to_station_no12 self.seat_types = seat_types13 self.date = date14 self.pricesDic = pricesDic15 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‘] +‘\n‘+ color.blue(pricesDic[‘A‘]) 92 if pos == ‘zy_num‘: 93 data[‘zy_num‘] = data[‘zy_num‘] +‘\n‘+ color.blue(pricesDic[‘B‘]) 94 if pos == ‘ze_num‘: 95 data[‘ze_num‘] = data[‘ze_num‘] +‘\n‘+ color.blue(pricesDic[‘C‘]) 96 if pos == ‘gr_num‘: 97 data[‘gr_num‘] = data[‘gr_num‘] +‘\n‘+ color.blue(pricesDic[‘D‘]) 98 if pos == ‘rw_num‘: 99 data[‘rw_num‘] = data[‘rw_num‘] +‘\n‘+ color.blue(pricesDic[‘E‘])100 if pos == ‘dw_num‘:101 data[‘dw_num‘] = data[‘dw_num‘] +‘\n‘+ color.blue(pricesDic[‘F‘])102 if pos == ‘yw_num‘:103 data[‘yw_num‘] = data[‘yw_num‘] +‘\n‘+ color.blue(pricesDic[‘G‘])104 if pos == ‘rz_num‘:105 data[‘rz_num‘] = data[‘rz_num‘] +‘\n‘+ color.blue(pricesDic[‘H‘])106 if pos == ‘yz_num‘:107 data[‘yz_num‘] = data[‘yz_num‘] +‘\n‘+ color.blue(pricesDic[‘I‘])108 if pos == ‘wz_num‘:109 data[‘wz_num‘] = data[‘wz_num‘] +‘\n‘+ 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]]) + ‘\n‘ + color.red(stations2CN[x["to_station_name"]])119 tmp.append(s)120 elif y == "start_time":121 s = color.green(x[y]) + ‘\n‘ + 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



python第三方库PrettyTable使用实例

评论关闭