欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

(五)Python查询12306余票:添加票价信息

程序员文章站 2024-03-17 21:38:34
...

前一篇–>docopt实现参数的输入—–查询任意时间任意车站余票

票价的查询根据前面result的解析是无法获取的,票价需要另外发送请求获取。
(五)Python查询12306余票:添加票价信息
(五)Python查询12306余票:添加票价信息
请求链接:
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这几个参数。
(五)Python查询12306余票:添加票价信息

有了前面教程解析车票信息result的基础解析车票也是大同小异罢了,找出对应车票类型对应的票价对应的位置就行。

实现获取车票票价的函数:

#pricesDic用于存放票价信息
pricesDic = {
        'A': '',
        'B': '',
        'C': '',
        'D': '',
        'E': '',
        'F': '',
        'G': '',
        'H': '',
        'I': '',
        'J': ''
    }

def getPrice(threadname,train_no, from_station_no, to_station_no, seat_types, date,pricesDic):
    while 1:
        try:
            headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}
            moneyUrl = "https://kyfw.12306.cn/otn/leftTicket/queryTicketPrice?train_no={}&from_station_no={}&to_station_no={}&seat_types={}&train_date={}".format(
                train_no, from_station_no, to_station_no, seat_types, date)
            req = urllib.request.Request(url=moneyUrl, headers=headers)
            r_price = urllib.request.urlopen(req).read().decode('utf-8')
            if r_price.startswith(u'\ufeff'):
                r_price = r_price.encode('utf8')[3:].decode('utf-8')
                # print(r_price)
            r_price = json.loads(r_price)
            break
        except:
            continue
    price = r_price['data']
    price = dict(price)#获取data字典,票价信息在字典中
    A = ('A9' in price.keys())#商务座票价对应key是A9或者P
    if A == False:
        A = ('P' in price.keys())
        if A == False:
            A = ''
        else:
            A = price['P']
    else:
        A = price['A9']

    B = ('M' in price.keys())#一等座对应key为M
    if B == False:
        B = ''
    else:
        B = price['M']
    C = ('O' in price.keys())#二等座对应key为O
    if C == False:
        C = ''
    else:
        C = price['O']
    D = ('A6' in price.keys())
    if D == False:
        D = ''
    else:
        D = price['A6']
    E = ('A4' in price.keys())
    if E == False:
        E = ''
    else:
        E = price['A4']
    F = ('F' in price.keys())
    if F == False:
        F = ''
    else:
        F = price['F']
    G = ('A3' in price.keys())
    if G == False:
        G = ''
    else:
        G = price['A3']

    H = ('A2' in price.keys())
    if H == False:
        H = ''
    else:
        H = price['A2']
    I = ('A1' in price.keys())
    if I == False:
        I = ''
    else:
        I = price['A1']

    J = ('WZ' in price.keys())
    if J == False:
        J = ''
    else:
        J = price['WZ']
    pricesDic['A'] = A
    pricesDic['B'] = B
    pricesDic['C'] = C
    pricesDic['D'] = D
    pricesDic['E'] = E
    pricesDic['F'] = F
    pricesDic['G'] = G
    pricesDic['H'] = H
    pricesDic['I'] = I
    pricesDic['J'] = J

我实现查询票价使用了Python中的线程,另外开启一个线程去查询票价:

import threading

threadLock = threading.Lock()
class myThread (threading.Thread):
    def __init__(self, threadID, threadName, train_no, from_station_no, to_station_no, seat_types, date,pricesDic):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.threadName = threadName
        self.train_no = train_no
        self.from_station_no = from_station_no
        self.to_station_no = to_station_no
        self.seat_types = seat_types
        self.date = date
        self.pricesDic = pricesDic
    def run(self):
        #print ("开始线程:" + self.threadName)
        # 获取锁,用于线程同步
        threadLock.acquire()
        getPrice(self.threadName, self.train_no, self.from_station_no, self.to_station_no, self.seat_types, self.date, self.pricesDic)
        # 释放锁,开启下一个线程
        threadLock.release()
        #print ("退出线程:" + self.threadName)

在resolveData函数中开启线程查询票价,并且将票价加入余票信息中:
再次修改resolveData函数,观察变化:

def resolveData(from_station, to_station, date):
    #拼接出查询链接
    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])
    #获取数据
    while 1:
        try:
            data = getData(url)
            lists = json.loads(data)["data"]["result"]
            # if data['status'] == False:
            #     print('获取失败!请检查网络')
            #     break
            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()
    for items in lists:
        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]
        data['from_station_name'] = item[6]
        data['to_station_name'] = item[7]
        data['start_time'] = item[8]
        data['arrive_time'] = item[9]
        data['lishi'] = item[10]
        data['swz_num'] = item[32] or item[25]# 商务座在32或25位置
        data['zy_num'] = item[31]
        data['ze_num'] = item[30]
        data['gr_num'] = item[21]
        data['rw_num'] = item[23]
        data['dw_num'] = item[27]
        data['yw_num'] = item[28]
        data['rz_num'] = item[24]
        data['yz_num'] = item[29]
        data['wz_num'] = item[26]
        data['qt_num'] = item[22]
        if item[0] == 'null':
            data['note_num'] = item[1]
        else:
            data['note_num'] = color.white(item[1])
        #解析出查询票价需要的参数
        train_no = item[2]
        from_station_no = item[16]
        to_station_no = item[17]
        types = item[35]
        getPriceThread = myThread(1, "Thread-1", train_no, from_station_no, to_station_no, types, date, pricesDic)
        getPriceThread.start()#开启查询车票的线程
        for pos in name:
            if data[pos] == '':
                data[pos] = '-'
        threadLock.acquire()#必须加锁,这是为了线程同步
        for pos in priceName:#将票价添加进余票信息中
            if pos == 'swz_num':
                data['swz_num'] = data['swz_num'] +'\n'+ color.blue(pricesDic['A'])
            if pos == 'zy_num':
                data['zy_num'] = data['zy_num'] +'\n'+ color.blue(pricesDic['B'])
            if pos == 'ze_num':
                data['ze_num'] = data['ze_num'] +'\n'+ color.blue(pricesDic['C'])
            if pos == 'gr_num':
                data['gr_num'] = data['gr_num'] +'\n'+ color.blue(pricesDic['D'])
            if pos == 'rw_num':
                data['rw_num'] = data['rw_num'] +'\n'+ color.blue(pricesDic['E'])
            if pos == 'dw_num':
                data['dw_num'] = data['dw_num'] +'\n'+ color.blue(pricesDic['F'])
            if pos == 'yw_num':
                data['yw_num'] = data['yw_num'] +'\n'+ color.blue(pricesDic['G'])
            if pos == 'rz_num':
                data['rz_num'] = data['rz_num'] +'\n'+ color.blue(pricesDic['H'])
            if pos == 'yz_num':
                data['yz_num'] = data['yz_num'] +'\n'+ color.blue(pricesDic['I'])
            if pos == 'wz_num':
                data['wz_num'] = data['wz_num'] +'\n'+ color.blue(pricesDic['J'])
        threadLock.release()
        cont.append(data)
    color = Colored()
    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#返回所有车次余票信息

最终测试:
(五)Python查询12306余票:添加票价信息
成功获取票价!

到这来为止我们就结束了DOS界面的开发。源代码:
链接:https://pan.baidu.com/s/1c1Gdxra 密码:6xpz

我在此基础上实现了连续多天的查询,并且实现了列车类型的过滤,
源代码在此:链接:https://pan.baidu.com/s/1jI2Ak4Y 密码:02gu
不懂得地方欢迎交流。
代码有BUG看看能不能您解决

相关标签: python 12306

上一篇: CSP 202006-2 稀疏向量

下一篇: