构造时间参数以及下单购票

学习目标
  1. 了解 构造时间参数
  2. 了解 下单购票逻辑

5.1 构造时间参数

# 12306.utils.parse_dateimport datetimedef 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)

5.2 下单购票

# 12306.funk12306.Funk12306.buy_ticket# 提交订单,并获取排队人数,和车票的真实余数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_isChangeurl = '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 和 orderIDtimestamp = 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 和 orderIDtimestamp = 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)

5.3 组织运行逻辑

# 12306.funk12306.Funk12306.rundef run(self):# 登录 获取cookiesself.get_cookies()# 买票self.buy_ticket()if __name__ == '__main__':username = input('请输入12306账号:')password = input('请输入12306密码:')funk = Funk12306(username, password)funk.run()

小结
  1. 了解 构造时间参数
  2. 了解 下单购票逻辑

测试运行以及完整代码

学习目标
  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.3 项目文件结构

6.3.1 12306.funk12306.py


import re
import os
import time
import json
import base64
import requests
from pprint import pprintfrom 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 parseTrainsInfosredis_timeout = 180 # redis中cookies_dict的过期时间 单位秒class Funk12306():def __init__(self, username, password):self.username = usernameself.password = passwordself.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 853url = '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))  # 23else: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)# 获取newapptkurl = '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, '')# 查询车量信息日志geturl = '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)# 查询车量具体信息queryurl = '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_listtrains_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_isChangeurl = '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_TOKENurl = '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_isChangeurl = '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 和 orderIDtimestamp = 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 和 orderIDtimestamp = 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):# 登录 获取cookiesself.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 == '': # 按@切会切出空字符串continuestations_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 datetimeRUOUSER = '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 parambs = 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 + filebytestailer = '\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 datetimedef 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.parsedef 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_notrain_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])  # leftTickettrain_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",......

小结

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. 了解 购票的整个逻辑

测试运行以及完整代码相关推荐

  1. 人脸识别门禁系统:基于Android的人脸识别门禁系统 毕业设计完整代码详细教程

    完整代码:https://download.csdn.net/download/qq_38735017/87382371 一.研究目的 传统的门禁系统以钥匙作为验证手段,便捷程度低,丢失钥匙之后会导致 ...

  2. 【YOLOV4】(7) 特征提取网络代码复现(CSPDarknet53+SPP+PANet+Head),附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 TensorFlow 构建YOLOV4目标检测算法的特征提取网络. 完整代码在我的Gitee中,有需要的自取:https://gitee.com/dgvv4/y ...

  3. 【神经网络】(19) ConvNeXt 代码复现,网络解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 构建 ConvNeXt 卷积神经网络模型. 论文地址:https://arxiv.org/pdf/2201.03545.pdf 完整代码在 ...

  4. 【图像分类案例】(2) DenseNet 天气图片四分类(权重迁移学习),附Tensorflow完整代码

    各位同学好,今天和大家分享一下使用 Tensorflow 构建 DenseNet 卷积神经网络模型,并使用预训练模型的权重,完成对四种天气图片的分类. 完整代码在我的 Gitee 中,有需要的自取: ...

  5. 【图像分类案例】(1) ResNeXt 交通标志四分类,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 构建 ResNeXt 神经网络模型,通过案例实战 ResNeXt 的训练以及预测过程.每个小节的末尾有网络.训练.预测的完整代码.想要数据 ...

  6. 【神经网络】(18) EfficientNetV2 代码复现,网络解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 搭建 EfficientNetV2 卷积神经网络模型. EfficientNetV2 在 EfficientNetV1 的基础上进行了改进 ...

  7. 【神经网络】(17) EfficientNet 代码复现,网络解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 复现 EfficientNet 卷积神经网络模型. EfficientNet 的网络结构和 MobileNetV3 比较相似,建议大家在学 ...

  8. 【神经网络】(16) MobileNetV3 代码复现,网络解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 构建 MobileNetV3 轻量化网络模型. MobileNetV3 做了如下改动(1)更新了V2中的逆转残差结构:(2)使用NAS搜索 ...

  9. 【神经网络】(15) Xception 代码复现,网络解析,附Tensorflow完整代码

    各位同学好,今天和大家分享一下如何使用 Tensorflow 构建 Xception 神经网络模型. 在前面章节中,我已经介绍了很多种轻量化卷积神经网络模型,感兴趣的可以看一下:https://blo ...

最新文章

  1. eplan文本怎么换行_EPLAN几个使用的小技巧,非常有用
  2. CentOS镜像下载地址
  3. Oracle procedure调用实例
  4. 在RHEL-4下半小时搭建Sendmail邮件服务器(下)
  5. 线程、进程、多线程、多进程和多任务有啥关系?
  6. matlab矩阵及其基本运算—特征值分解和svd奇异值分解
  7. 初次联系导师短信模板_2020考研复试:提前联系导师的6点注意事项(附邮件模板)...
  8. MathType与Origin是怎么兼容的
  9. VMWARE 之 vSphere vCenter 安装基本配置
  10. 安卓系统车牌离线识别,优秀的车牌识别算法
  11. 新视野大学英语(第三版) 读写教程4 课后答案
  12. latex 琐粹记录
  13. ffmpeg 编码器AVCodecContext 的配置参数
  14. 华硕笔记本k555拆机图解_「华硕k401n」华硕K401笔记本电脑拆机清灰步骤详解 - seo实验室...
  15. 一个所谓的“文字创作者”的焦虑
  16. 无法将值vmware-tray.exe写入注册表
  17. 30天自制操作系统Day3
  18. 湖南省郴州市谷歌高清卫星地图下载
  19. 非常专业的数据统计软件-SPSS提供下载
  20. 详解容灾架构中的数据复制技术

热门文章

  1. 【Java杂货铺】JVM#Java高墙之内存模型
  2. 2022年湖南省自考考试学前儿童发展练习题及答案
  3. Cython-bbox pip 安装报错
  4. vba 保存word里面的图片_word表格技巧:如何对表格进行样式批处理
  5. 3-1、React-Router基础使用plus
  6. php lottery,PHP+Ajax+lottery.js抽奖整个流程
  7. 51单片机实训项目之“万年历”代码原理详解
  8. 流量分析——安恒科技(八月CTF)
  9. Excel万金油公式IINDEX-SMALL-IF-ROW-超级匹配
  10. dedecms模板教程:织梦模板网站SEO优化教程