美文网首页
47.测试运行以及完整代码

47.测试运行以及完整代码

作者: M_小七 | 来源:发表于2020-08-30 16:44 被阅读0次

    测试运行以及完整代码

    学习目标
    1. 了解 购票的整个逻辑

    6.1 测试运行

    执行12306.funk12306.py,购票成功最后显示的结果

    输入要购票的乘车人的下标0
    请输入要购买的坐席类型的拼音,如果输入错误,将强行购买无座,能回家就行了,还要tm什么自行车!:yingwo
    {"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"ifShowPassCode":"N","canChooseBeds":"N","canChooseSeats":"N","choose_Seats":"MOP9","isCanChooseMid":"N","ifShowPassCodeTime":"1","submitStatus":true,"smokeStr":""},"messages":[],"validateMessages":{}}
    {"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"count":"0","ticket":"16","op_2":"false","countT":"0","op_1":"false"},"messages":[],"validateMessages":{}}
    此时排队买票的人数为:0
    此时该车次的余票数量为:16
    {'validateMessagesShowId': '_validatorMessage', 'status': True, 'httpstatus': 200, 'data': {'submitStatus': True}, 'messages': [], 'validateMessages': {}}
    {"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"queryOrderWaitTimeStatus":true,"count":0,"waitTime":4,"requestId":6478993261703780471,"waitCount":1,"tourFlag":"dc","orderId":null},"messages":[],"validateMessages":{}}
    {"validateMessagesShowId":"_validatorMessage","status":true,"httpstatus":200,"data":{"errMsg":"网络传输过程中数据丢失,请查看未完成订单,继续支付!","submitStatus":false},"messages":[],"validateMessages":{}}
    
    Process finished with exit code 0
    

    6.2 项目地图

    6.2.1-项目代码地图.png

    6.3 项目文件结构

    6.3.1-项目文件结构.png

    6.3.1 12306.funk12306.py

    
    import re
    import os
    import time
    import json
    import base64
    import requests
    from pprint import pprint
    
    from utils.captcha import getCode
    from utils.parse_date import parseDate
    from utils.stations_dict import stations_dict
    from utils.parse_passenger import parsePassenger
    from utils.parse_seat_type import seat_type_dict
    from utils.parse_trains_infos import parseTrainsInfos
    
    redis_timeout = 180 # redis中cookies_dict的过期时间 单位秒
    
    
    class Funk12306():
        def __init__(self, username, password):
            self.username = username
            self.password = password
            self.s = requests.session()
            self.s.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'
    
        def get_cookies(self):
            print('获取登录前的cookies')
    
            """以上都为获取cookies"""
    
            url = 'https://www.12306.cn/index/'
            self.s.get(url)
    
            url = 'https://kyfw.12306.cn/otn/login/conf'
            self.s.headers['Referer'] = 'https://kyfw.12306.cn/otn/resources/login.html'
            self.s.post(url)
    
            url = 'https://kyfw.12306.cn/otn/index12306/getLoginBanner'
            resp = self.s.get(url)
            print(resp.text)
    
            # 检查用户是否登录
            url = 'https://kyfw.12306.cn/passport/web/auth/uamtk-static'
            resp = self.s.post(url, data={'appid': 'otn'})
            print(resp.text)
    
            # 获取登录二维码
            url = 'https://kyfw.12306.cn/passport/web/create-qr64'
            resp = self.s.post(url, data={'appid': 'otn'})
            print(resp.text)
            uuid = json.loads(resp.text)['uuid']
    
            # 查询二维码状态
            url = 'https://kyfw.12306.cn/passport/web/checkqr'
            resp = self.s.post(url, data={'appid': 'otn', 'uuid': uuid})
            print(resp.text)
    
            """获取图片验证码并手动输入或打码,发送验证请求"""
    
            # 获取验证码图片
            temp = str(time.time() * 1000)[:-5]  # 15421 76058 853
            url = 'https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&_={}'.format(temp)
            resp = self.s.get(url)
            print(resp.text)
            captcha_img_b64 = json.loads(resp.text)['image']
            captcha_img = base64.b64decode(captcha_img_b64)
            with open('./imgs/{}.png'.format(temp), 'wb') as f:
                f.write(captcha_img)
    
            # 选择打码方式并获取结果
            create_type = input(' 1 为手动打码 or 2 为收费平台自动打码,请选择:')
            if create_type == '1': # 手动打码
                answer_num = input('输入图片编号,从1开始:')
            elif create_type == '2': # 接入打码平台
                answer_num = getCode('./imgs/{}.png'.format(temp))  # 23
            else:
                raise Exception('输入错误! 1 为手动打码 or 2 为收费平台自动打码')
    
            # 改图片名字并获取点击坐标
            answer_dict = { '1': '37,46,',
                            '2': '110,46,',
                            '3': '181,46,',
                            '4': '253,46,',
                            '5': '37,116,',
                            '6': '110,116,',
                            '7': '181,116,',
                            '8': '253,116,' }
            os.rename('./imgs/{}.png'.format(temp),
                      './imgs/{}_{}.png'.format(temp, answer_num))
            answer = ''
            for i in answer_num:
                answer += answer_dict[i]
            answer = answer[:-1]
    
            # 验证图片验证码
            url = 'https://kyfw.12306.cn/passport/captcha/captcha-check?answer={}&rand=sjrand&login_site=E&_={}'.format(
                answer, str(time.time() * 1000)[:-4])
            resp = self.s.get(url)
            print(json.loads(resp.text))
    
            """发送登陆请求,以及后续登陆验证"""
    
            # 登录
            url = 'https://kyfw.12306.cn/passport/web/login'
            data = {'username': self.username,
                    'password': self.password,
                    'appid': 'otn',
                    'answer': answer}
            resp = self.s.post(url, data=data)
            print(resp.text)
            uamtk = json.loads(resp.text)['uamtk']
    
            # 进入登录后的页面 发生302跳转
            url = 'https://kyfw.12306.cn/otn/login/userLogin' # 302跳转
            self.s.get(url)
            url = 'https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin'
            self.s.get(url)
    
            # 获取newapptk
            url = 'https://kyfw.12306.cn/passport/web/auth/uamtk'
            self.s.headers['Referer'] = 'https://kyfw.12306.cn/otn/passport?redirect=/otn/login/userLogin'
            resp = self.s.post(url, data={'appid': 'otn'})
            print(json.loads(resp.text))
            newapptk = json.loads(resp.text)['newapptk']
    
            # 登录后验证
            url = 'https://kyfw.12306.cn/otn/uamauthclient'
            resp = self.s.post(url, data={'tk': newapptk})
            print(json.loads(resp.text))
    
        def buy_ticket(self):
            self.s.headers.pop('Referer') # 清除referer
    
            # 获取城市(车站)编码
            from_station = input('输入出发城市或车站:')
            to_station = input('输入到达城市或车站:')
            train_date = input('输入出行日期,格式为2018-12-03:')
            from_station_code = stations_dict.get(from_station, '')
            to_station_code = stations_dict.get(to_station, '')
    
            # 查询车量信息日志get
            url = 'https://kyfw.12306.cn/otn/leftTicket/log?leftTicketDTO.train_date=%s&leftTicketDTO.from_station=%s&leftTicketDTO.to_station=%s&purpose_codes=ADULT' % (train_date, from_station_code, to_station_code)
            resp = self.s.get(url)
            print(resp.text)
            # 查询车量具体信息query
            url = 'https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=%s&leftTicketDTO.from_station=%s&leftTicketDTO.to_station=%s&purpose_codes=ADULT' % (train_date, from_station_code, to_station_code)
            response = self.s.get(url)
    
            # 解析获取trains_list
            trains_list = parseTrainsInfos(json.loads(response.content)['data']['result'])
            print('查询的列车信息如下:')
            pprint(trains_list)
            # 获取选择的列车
            train_info_dict = trains_list[int(input('请输入选中车次的下标:'))]
            print('选中了列车信息为:')
            pprint(train_info_dict)
            # 列车信息
            secretStr = train_info_dict['secretStr']
            leftTicket = train_info_dict['leftTicket']
            train_location = train_info_dict['train_location']
    
            # 检查用户是否保持登录成功
            url = 'https://kyfw.12306.cn/otn/login/checkUser'
            data = {'_json_att': ''}
            resp = self.s.post(url, data=data)
            print(json.loads(resp.text))
    
            # 点击预定
            url = 'https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest'
            data = {
                'secretStr': secretStr,
                'train_date': train_date,
                'back_train_date': train_date,
                'tour_flag': 'dc',  # dc 单程 wf 往返
                'purpose_codes': 'ADULT',  # 成人
                'query_from_station_name': from_station,
                'query_to_station_name': to_station,
                'undefined': ''
            }
            resp = self.s.post(url, data=data)
            print(resp.text)
    
            # 订单初始化 获取REPEAT_SUBMIT_TOKEN key_check_isChange
            url = 'https://kyfw.12306.cn/otn/confirmPassenger/initDc'
            data = {'_json_att': ''}
            response = self.s.post(url, data=data)
            repeat_submit_token = re.search(r"var globalRepeatSubmitToken = '([a-z0-9]+)';",
                                            response.content.decode()).group(1)
            key_check_isChange = re.search("'key_check_isChange':'([A-Z0-9]+)'", response.content.decode()).group(1)
    
            # 获取用户信息
            # 需要 REPEAT_SUBMIT_TOKEN
            url = 'https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs'
            data = {'_json_att': '',
                    'REPEAT_SUBMIT_TOKEN': repeat_submit_token}
            response = self.s.post(url, data=data)
    
            # 解析并构造乘客信息列表
            passenger_list = parsePassenger(json.loads(response.content))
            print('获取乘客信息有:')
            pprint(passenger_list)
            passenger_info_dict = passenger_list[int(input('输入要购票的乘车人的下标'))]
    
            # 坐席类型
            try:
                seat_type = seat_type_dict[input('请输入要购买的坐席类型的拼音,如果输入错误,将强行购买无座,能回家就行了,还要tm什么自行车!:')]
            except:
                seat_type = seat_type_dict['wuzuo']
    
            # 构造乘客信息
            passengerTicketStr = '%s,0,1,%s,%s,%s,%s,N' % (
                seat_type, passenger_info_dict['passenger_name'],
                passenger_info_dict['passenger_id_type_code'],
                passenger_info_dict['passenger_id_no'],
                passenger_info_dict['passenger_mobile_no'])
            oldPassengerStr = '%s,%s,%s,1_' % (
                passenger_info_dict['passenger_name'],
                passenger_info_dict['passenger_id_type_code'],
                passenger_info_dict['passenger_id_no'])
    
            # 检查选票人信息
            url = 'https://kyfw.12306.cn/otn/confirmPassenger/checkOrderInfo'
            data = {
                'cancel_flag': '2',  # 未知
                'bed_level_order_num': '000000000000000000000000000000',  # 未知
                'passengerTicketStr': passengerTicketStr.encode('utf-8'),  # O,0,1,靳文强,1,142303199512240614,18335456020,N
                'oldPassengerStr': oldPassengerStr.encode('utf-8'),  # 靳文强,1,142303199512240614,1_
                'tour_flag': 'dc',  # 单程
                'randCode': '',
                'whatsSelect': '1',
                '_json_att': '',
                'REPEAT_SUBMIT_TOKEN': repeat_submit_token
            }
            resp = self.s.post(url, data=data)
            print(resp.text)
    
            # 提交订单,并获取排队人数,和车票的真实余数
            url = 'https://kyfw.12306.cn/otn/confirmPassenger/getQueueCount'
            data = {
                'train_date': parseDate(train_date),  # Fri Nov 24 2017 00:00:00 GMT+0800 (中国标准时间)
                'train_no': train_info_dict['train_no'],  # 6c0000G31205
                'stationTrainCode': train_info_dict['stationTrainCode'],  # G312
                'seatType': seat_type,  # 席别
                'fromStationTelecode': train_info_dict['from_station'],  # one_train[6]
                'toStationTelecode': train_info_dict['to_station'],  # ? one_train[7]
                'leftTicket': train_info_dict['leftTicket'],  # one_train[12]
                'purpose_codes': '00',
                'train_location': train_info_dict['train_location'],  # one_train[15]
                '_json_att': '',
                'REPEAT_SUBMIT_TOKEN': repeat_submit_token
            }
            resp = self.s.post(url, data=data)
            print(resp.text)
            print('此时排队买票的人数为:{}'.format(json.loads(resp.text)['data']['count']))
            ticket = json.loads(resp.text)['data']['ticket']
            print('此时该车次的余票数量为:{}'.format(ticket))
            if ticket == '0':
                print('没有余票,购票失败')
                return '没有余票,购票失败'
    
            # 确认订单,进行扣票 需要 key_check_isChange
            url = 'https://kyfw.12306.cn/otn/confirmPassenger/confirmSingleForQueue'
            data = {
                'passengerTicketStr': passengerTicketStr.encode('utf-8'),
                'oldPassengerStr': oldPassengerStr.encode('utf-8'),
                'randCode': '',
                'purpose_codes': '00',
                'key_check_isChange': key_check_isChange,
                'leftTicketStr': leftTicket,
                'train_location': train_location,  # one_train[15]
                'choose_seats': '',  # 选择坐席 ABCDEF 上中下铺 默认为空不选
                'seatDetailType': '000',
                'whatsSelect': '1',
                'roomType': '00',
                'dwAll': 'N',  # ?
                '_json_att': '',
                'REPEAT_SUBMIT_TOKEN': repeat_submit_token
            }
            resp = self.s.post(url, data=data)
            print(json.loads(resp.text))
            if json.loads(resp.text)['status'] == False or json.loads(resp.text)['data']['submitStatus'] == False:
                print('扣票失败')
                return '扣票失败'
    
            # 排队等待 返回waittime  获取 requestID 和 orderID
            timestamp = str(int(time.time() * 1000))  # str(time.time() * 1000)[:-4]
            url = 'https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime?random=%s&tourFlag=dc&_json_att=&REPEAT_SUBMIT_TOKEN=%s' % (
                timestamp, repeat_submit_token)
            resp = self.s.get(url)
            print(resp.text)
            try:
                orderID = json.loads(resp.text)['data']['orderId']
            except:
                # 排队等待 返回waittime  获取 requestID 和 orderID
                timestamp = str(int(time.time() * 1000)) # str(time.time() * 1000)[:-4]
                url = 'https://kyfw.12306.cn/otn/confirmPassenger/queryOrderWaitTime?random=%s&tourFlag=dc&_json_att=&REPEAT_SUBMIT_TOKEN=%s' % (
                    timestamp, repeat_submit_token)
                resp = self.s.get(url)
                print(resp.text)
                try:
                    orderID = json.loads(resp.text)['data']['orderId']
                except:
                    return '购票失败'
    
            # 订单结果
            url = 'https://kyfw.12306.cn/otn/confirmPassenger/resultOrderForDcQueue'
            data = {
                'orderSequence_no': orderID,
                '_json_att': '',
                'REPEAT_SUBMIT_TOKEN': repeat_submit_token
            }
            resp = self.s.post(url, data=data)
            print(resp.text)
    
        def run(self):
            # 登录 获取cookies
            self.get_cookies()
            # 买票
            self.buy_ticket()
    
    
    
    if __name__ == '__main__':
    
        username = input('请输入12306账号:')
        password = input('请输入12306密码:')
    
        funk = Funk12306(username, password)
        funk.run()
    

    6.3.2 12306.get_stations_dict.py

    
    import re
    import json
    import requests
    
    # 获取车站编号字符串 station_version=1.9076
    url = 'https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9076'
    resp = requests.get(url)
    stations_str = re.search("'(.*)'", resp.text).group(1)
    
    # 获取{城市(车站):编码, ...} 键值对
    stations_dict = {}
    for station in stations_str.split('@'):
        if station == '': # 按@切会切出空字符串
            continue
        stations_dict[station.split('|')[1]] = station.split('|')[2]
    
    with open('./utils/stations_dict.py', 'w', encoding='utf8') as f:
        f.write('stations_dict = ')
        json.dump(stations_dict, f, ensure_ascii=False, indent=4)
    

    6.3.3 12306.utils.captcha.py

    
    import hashlib
    import requests
    from datetime import datetime
    
    RUOUSER = 'xxxx'
    RUOPASS = 'xxxx'
    
    # 若快 12306打码 直接传入本地文件路径
    def getCode(img):
        url = "http://api.ruokuai.com/create.json"
        fileBytes = open(img, "rb").read()
        paramDict = {
            'username': RUOUSER,
            'password': RUOPASS,
            'typeid': 6113, # 专门用来识别12306图片验证的类型id
            'timeout': 90,
            'softid': 117157, # 推广用的
            'softkey': '70acaa1e477a4374a7736264a24b974b' # 推广用的
        }
        paramKeys = ['username',
                     'password',
                     'typeid',
                     'timeout',
                     'softid',
                     'softkey'
                     ]
        result = http_upload_image(url, paramKeys, paramDict, fileBytes)
        return result['Result']
    
    
    # 若快12306打码 上传图片
    def http_upload_image(url, paramKeys, paramDict, filebytes):
        timestr = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        boundary = '------------' + hashlib.md5(timestr.encode("utf8")).hexdigest().lower()
        boundarystr = '\r\n--%s\r\n' % (boundary)
    
        bs = b''
        for key in paramKeys:
            bs = bs + boundarystr.encode('ascii')
            param = "Content-Disposition: form-data; name=\"%s\"\r\n\r\n%s" % (key, paramDict[key])
            # print param
            bs = bs + param.encode('utf8')
        bs = bs + boundarystr.encode('ascii')
    
        header = 'Content-Disposition: form-data; name=\"image\"; filename=\"%s\"\r\nContent-Type: image/gif\r\n\r\n' % ('sample')
        bs = bs + header.encode('utf8')
    
        bs = bs + filebytes
        tailer = '\r\n--%s--\r\n' % (boundary)
        bs = bs + tailer.encode('ascii')
    
        headers = {'Content-Type': 'multipart/form-data; boundary=%s' % boundary,
                   'Connection': 'Keep-Alive',
                   'Expect': '100-continue',
                   }
        response = requests.post(url, params='', data=bs, headers=headers)
        return response.json()
    
    
    if __name__ == '__main__':
        # 测试
        ret = getCode('../imgs/1544627949970.png')
        print(ret)
    

    6.3.4 12306.utils.parse_date.py

    
    import datetime
    
    
    def parseDate(train_date):
        """
        :param train_date: '2017-12-12'
        :return:
        """
        week_name = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
        month_name = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split()
        y, m, d = map(int, train_date.split("-"))
        weekday = datetime.datetime(y, m, d).weekday()
        # Fri Nov 24 2017 00:00:00 GMT+0800 (中国标准时间)
        return "{0} {1} {2} {3} 00:00:00 GMT+0800 (中国标准时间)".format(week_name[weekday], month_name[m - 1], d, y)
    
    

    6.3.5 12306.utils.parse_passenger.py

    
    def parsePassenger(passenger_dict):
        passengers_infos_list = passenger_dict['data']['normal_passengers']
        passenger_list = []
        for passenger_info in passengers_infos_list:
            passenger_info_dict = {}
            passenger_info_dict['passenger_name'] = passenger_info.get('passenger_name', '')
            passenger_info_dict['passenger_gender'] = passenger_info.get('sex_name', '')
            passenger_info_dict['passenger_id_type_code'] = passenger_info.get('passenger_id_type_code', '')
            passenger_info_dict['passenger_id_no'] = passenger_info.get('passenger_id_no', '')
            passenger_info_dict['passenger_mobile_no'] = passenger_info.get('mobile_no', '')
            passenger_list.append(passenger_info_dict)
        return passenger_list
    

    6.3.6 12306.utils.parse_seat_type.py

    
    seat_type_dict = {
        "erdengzuo": "O",  # 二等座
        "yingwo": "3",  # 硬卧
        "yingzuo": "1",  # 硬座
        "wuzuo": "1",  # 无座
        "ruanwo": "4",  # 软卧
        "ruanzuo": "2",  # 软座
        "dongwo": "F",  # 动卧
        "yidengzuo": "M",  # 一等座
        "gaojiruanwo": "6",  # 高级软座
        "shangwuzuo": "9",  # 商务座
        "tedengzuo": "P",  # 特等座
    }
    

    6.3.7 12306.utils.parse_trains_infos.py

    import urllib.parse
    
    
    def parseTrainsInfos(trains_list):
        """
        解析列车信息列表, 返回列车信息列表
        """
        trains_infos_list = []
    
        if trains_list == []:
            return []
    
        for train_info in trains_list:
            train_info_list = train_info.split('|')
            train_info_dict = {}
            # 构造列车信息
            train_info_dict['secretStr'] = urllib.parse.unquote(train_info_list[0])  # secretStr ;为''时无法购买车票
            # train_info_list[1]  预定/列车停运
            train_info_dict['train_no'] = urllib.parse.unquote(train_info_list[2])  # train_no
            train_info_dict['stationTrainCode'] = urllib.parse.unquote(train_info_list[3])  # stationTrainCode 即车次 # 展示
            train_info_dict['start_station'] = urllib.parse.unquote(train_info_list[4])  # 始发站 # 展示
            train_info_dict['end_station'] = urllib.parse.unquote(train_info_list[5])  # 终点站 # 展示
            train_info_dict['from_station'] = urllib.parse.unquote(train_info_list[6])  # 出发站 # 展示
            train_info_dict['to_station'] = urllib.parse.unquote(train_info_list[7])  # 到达站 # 展示
            train_info_dict['from_time'] = urllib.parse.unquote(train_info_list[8])  # 出发时间 # 展示
            train_info_dict['to_time'] = urllib.parse.unquote(train_info_list[9])  # 到达时间 # 展示
            train_info_dict['use_time'] = urllib.parse.unquote(train_info_list[10])  # 时长 # 展示
            train_info_dict['buy_able'] = urllib.parse.unquote(train_info_list[11])  # 能否购买 Y 可以购买 N 不可以购买 IS_TIME_NOT_BUY 停运 # 展示
            train_info_dict['leftTicket'] = urllib.parse.unquote(train_info_list[12])  # leftTicket
            train_info_dict['start_time'] = urllib.parse.unquote(train_info_list[13])  # 车次始发日期 # 展示
            train_info_dict['train_location'] = urllib.parse.unquote(train_info_list[15])  # train_location 不知道是啥??
            train_info_dict['from_station_no'] = urllib.parse.unquote(train_info_list[16])  # 出发站编号
            train_info_dict['to_station_no'] = urllib.parse.unquote(train_info_list[17])  # 到达站编号
            # 14,18,19,20,27,34,35未知
            train_info_dict['gaojiruanwo'] = urllib.parse.unquote(train_info_list[21])  # 高级软卧 # 展示
            train_info_dict['qita'] = urllib.parse.unquote(train_info_list[22])  # 其他 # 展示
            train_info_dict['ruanwo'] = urllib.parse.unquote(train_info_list[23])  # 软卧 # 展示
            train_info_dict['ruanzuo'] = urllib.parse.unquote(train_info_list[24])  # 软座 # 展示
            train_info_dict['tedengzuo'] = urllib.parse.unquote(train_info_list[25])  # 特等座 # 展示
            train_info_dict['wuzuo'] = urllib.parse.unquote(train_info_list[26])  # 无座 # 展示
            train_info_dict['yingwo'] = urllib.parse.unquote(train_info_list[28])  # 硬卧 # 展示
            train_info_dict['yingzuo'] = urllib.parse.unquote(train_info_list[29])  # 硬座 # 展示
            train_info_dict['erdengzuo'] = urllib.parse.unquote(train_info_list[30])  # 二等座 # 展示
            train_info_dict['yidengzuo'] = urllib.parse.unquote(train_info_list[31])  # 一等座 # 展示
            train_info_dict['shangwuzuo'] = urllib.parse.unquote(train_info_list[32])  # 商务座 # 展示
            train_info_dict['dongwo'] = urllib.parse.unquote(train_info_list[33])  # 动卧 # 展示
            
            trains_infos_list.append(train_info_dict)
            
        return trains_infos_list
    
    

    6.3.8 12306.utils.stations_dict.py

    该文件由 12306.get_stations_dict.py运行生成

    stations_dict = {
        "北京北": "VAP",
        "北京东": "BOP",
        "北京": "BJP",
        ......
    

    小结
    1. 了解 购票的整个逻辑

    相关文章

      网友评论

          本文标题:47.测试运行以及完整代码

          本文链接:https://www.haomeiwen.com/subject/nfeerktx.html