(六)Python查询12306余票:升级版-----图形化界面代码
2018-01-04 19:04
357 查看
上一篇–>添加票价信息
实现效果:
ProAPI.py:包含需要使用的一些我封装好的API
代码中涉及的字典、列表等:
Resources.py:
还有全国车站列表,用于将车站拼音、中文、简拼—>车站代码和车站代码—>中文的stationsInfo.py:
https://pan.baidu.com/s/1i4FTjgD
实现效果:
主要代码观看
12306.py:from tkinter import * import re import tkinter.messagebox as messagebox from tkinter import ttk import time from Resources import info from tkinter.ttk import Treeview from ProApi import * K = [] D = [] G = [] Z = [] T = [] arguments = { '-g': '', '-d': '', '-z': '', '-t': '', '-k': '' } tickets = [] pos = [] def GetStation(): clean(K, D, G, Z, T) del tickets[:] for item in tree.get_children(): tree.delete(item) from_station = var_from.get().strip() to_station = var_to.get().strip() from_time = number.get() info = inputArgs(from_station, to_station, from_time) if info['from_station'] !='' and info['to_station'] != '' and info['flag'] != 'False': ticket_list = [] countsStr=days.get().strip() if countsStr=='': messagebox.showinfo('ERROR', '查询天数必须输入,请输入') return counts = int(countsStr.strip()) if counts <= 0: messagebox.showinfo('ERROR', '查询天数必须大于等于1,请重新输入') return else: ticket_list = operate(counts) i=0 for item in ticket_list: if re.match(r'^K', item[1]): K.append(i) if re.match(r'^D', item[1]): D.append(i) if re.match(r'^G|C', item[1]): G.append(i) if re.match(r'^Z', item[1]): Z.append(i) if re.match(r'^T', item[1]): T.append(i) i = i + 1 length = len(ticket_list) for i in range(length): tickets.append(ticket_list[i]) pos = FilterFun() for i in pos: tree.insert('', i, values=ticket_list[i]) children = tree.get_children() for num in range(len(children)): if (num % 2 == 0): tree.item(children[num], tags=["evenLine"]) else: tree.item(children[num], tags=["evenLine2"]) tree.tag_configure("evenLine", background='#DEF1EC') tree.tag_configure("evenLine2", background='#F1EBDE') ticket_list = [] def selectall(): if all.get() == '1': g.set('1') d.set('1') z.set('1') t.set('1') k.set('1') else: g.set('0') d.set('0') z.set('0') t.set('0') k.set('0') FilterFun2() def filterG(): all.set('0') FilterFun2() def filterD(): all.set('0') FilterFun2() def filterZ(): all.set('0') FilterFun2() def filterT(): all.set('0') FilterFun2() def filterK(): all.set('0') FilterFun2() def cleanTree(): clean(K, D, G, Z, T) del tickets[:] for item in tree.get_children(): tree.delete(item) all.set('0') selectall() days.set('1') def cleanTree2(): for item in tree.get_children(): tree.delete(item) def FilterFun(): temp = [] if d.get() == '1': for i in D: temp.append(i) if k.get() == '1': for i in K: temp.append(i) if z.get() == '1': for i in Z: temp.append(i) if t.get() == '1': for i in T: temp.append(i) if g.get() == '1': for i in G: temp.append(i) if g.get() == '0' and d.get() == '0' and k.get() == '0' and z.get() == '0' and t.get() == '0': for i in range(len(tickets)): temp.append(i) return temp def FilterFun2(): cleanTree2() pos = FilterFun() for i in pos: tree.insert('', i, values=tickets[i]) children = tree.get_children() for num in range(len(children)): if (num % 2 == 0): tree.item(children[num], tags=["evenLine"]) else: tree.item(children[num], tags=["evenLine2"]) tree.tag_configure("evenLine", background='#DEF1EC') tree.tag_configure("evenLine2", background='#F1EBDE') def operate(counts): temp = [] today = date.today() lastday = today + timedelta(days=15) from_station = info['from_station'] to_station = info['to_station'] from_date = info['from_date'] mdate = date(int(from_date[:4]), int(from_date[5:7]), int(from_date[8:])) for i in range(counts): # 执行查询 ndate = mdate + timedelta(days=i) if today <= ndate and ndate < lastday: lists = resolveData(from_station, to_station, ndate) for item in lists: temp.append(item) else: break return temp root = Tk() root.geometry('1135x600') root.title('火车票查询系统') root.iconbitmap('icon.ico') # 更换tk图标 TopFrame = Frame(root, width=1135, height=150) TLFrame = Frame(TopFrame, width=985, height=150) TRFrame = Frame(TopFrame, width=150, height=150) TLTFrame = Frame(TLFrame, width=985, height=75) TLBFrame = Frame(TLFrame, width=985, height=75) # 查询信息输入 Label(TLTFrame, text='始发站:', font=('宋体', (11))).pack(side=LEFT) var_from = StringVar() from_s = Entry(TLTFrame, textvariable=var_from, width=14).pack(side=LEFT) Label(TLTFrame, text='终点站:', font=('宋体', (11)),padx=20).pack(side=LEFT) var_to = StringVar() to_s = Entry(TLTFrame, textvariable=var_to, width=14).pack(side=LEFT) # 创建一个下拉列表 Label(TLTFrame, text='出发日期:', font=('宋体', (11)),padx=20).pack(side=LEFT) number = StringVar() numberChosen = ttk.Combobox(TLTFrame, width=12, textvariable=number) numberChosen['values'] = (1, 2, 4, 42, 100) # 设置下拉列表的值 values = [] y = int(time.strftime("%Y", time.localtime())) m = int(time.strftime("%m", time.localtime())) d = int(time.strftime("%d", time.localtime())) i = 0 yy = y mm = m dd = d while i < 15:#15天数据 if m in (1, 3, 5, 7, 8, 10, 12): if d + i > 31: dd = d + i - 31 mm = m + 1 if mm > 12: yy = y + 1 mm = mm - 12 else: dd = d + i elif m in (4, 6, 9, 11): if d + i > 30: dd = d + i - 30 mm = m + 1 if mm > 12: yy = y + 1 mm = mm - 12 else: dd = d + i else: if (m % 400 == 0) or ((m % 4 == 0) and (m % 100 != 0)): if d + i > 29: dd = d + i - 29 mm = m + 1 if mm > 12: yy = y + 1 mm = mm - 12 else: dd = d + i else: if d + i > 28: dd = d + i - 28 mm = m + 1 if mm > 12: yy = y + 1 mm = mm - 12 else: dd = d + i s = '%d-%02d-%02d' % (yy, mm, dd) values.append(s) i += 1 numberChosen['values'] = tuple(values) numberChosen.current(0) # 设置下拉列表默认显示的值,0为 numberChosen['values'] 的下标值 numberChosen.pack(side=LEFT) Label(TRFrame, text='查询天数:', font=('宋体', (11)),padx=5).pack(side=LEFT) days = StringVar() daysEntry = Entry(TRFrame, textvariable=days, width=5).pack(side=LEFT) days.set('1') Label(TRFrame, text=' ', font=('宋体', (11)), padx=5).pack(side=LEFT) search = Button(TRFrame, text='查询余票', width=10, command=GetStation,bg='#8EDEF0').pack(side=LEFT) Label(TRFrame, text=' ', font=('宋体', (11)), padx=5).pack(side=LEFT) filterType = Button(TRFrame, text='复 位', width=10, command=cleanTree,bg='#BBEF8A').pack(side=LEFT) TLFrame.pack(side=LEFT) TLTFrame.pack(side=TOP) TLBFrame.pack(side=BOTTOM) TRFrame.pack(side=RIGHT) TopFrame.pack(side=TOP, pady=5) # 车型选择 Label(TLBFrame, text='车次类型:', font=('宋体', (11))).pack(side=LEFT) all = StringVar() g = StringVar() d = StringVar() z = StringVar() t = StringVar() k = StringVar() Checkbutton(TLBFrame, text = '全部',padx=10,variable = all,command=selectall).pack(side=LEFT) Checkbutton(TLBFrame, text = 'G/C-高铁/城际',padx=10, command=filterG, variable = g).pack(side=LEFT) Checkbutton(TLBFrame, text = 'D-动车',padx=10,variable = d,command=filterD).pack(side=LEFT) Checkbutton(TLBFrame, text = 'Z-直达',padx=10,variable = z,command=filterZ).pack(side=LEFT) Checkbutton(TLBFrame, text = 'T-特快',padx=10,variable = t,command=filterT).pack(side=LEFT) Checkbutton(TLBFrame, text = 'K-快车',padx=10,variable = k,command=filterK).pack(side=LEFT) all.set('0') d.set('0') g.set('0') t.set('0') k.set('0') z.set('0') # 车票展示 ShowFrame = Frame(root, width=780, height=450, bg='pink') ShowFrame.pack(side=TOP) scrollBar = Scrollbar(ShowFrame) scrollBar.pack(side=RIGHT,fill=Y) tree = Treeview(ShowFrame, columns=('c0','c1','c2','c3','c4','c5','c6','c7','c8','c9','c10','c11','c12','c13','c14','c15','c16'), show="headings", height=540, yscrollcommand=scrollBar.set) tree.column('c0',width=100,anchor='center') tree.column('c1',width=50,anchor='center') tree.column('c2',width=100,anchor='center') tree.column('c3',width=100,anchor='center') tree.column('c4',width=50,anchor='center') tree.column('c5',width=60,anchor='center') tree.column('c6',width=60,anchor='center') tree.column('c7',width=60,anchor='center') tree.column('c8',width=60,anchor='center') tree.column('c9',width=60,anchor='center') tree.column('c10',width=60,anchor='center') tree 1d866 .column('c11',width=60,anchor='center') tree.column('c12',width=60,anchor='center') tree.column('c13',width=60,anchor='center') tree.column('c14',width=60,anchor='center') tree.column('c15',width=60,anchor='center') tree.column('c16',width=60,anchor='center') #显示车次,出发/到达站,出发/到达时间,历时,商务座,一等座,二等座,软卧,动卧,硬卧,硬座,无座 tree.heading('c0',text='出发日期') tree.heading('c1',text='车次') tree.heading('c2',text='出发/到达站') tree.heading('c3',text='出发/到达时间') tree.heading('c4',text='历时') tree.heading('c5',text='商务座') tree.heading('c6',text='一等座') tree.heading('c7',text='二等座') tree.heading('c8',text='高级软卧') tree.heading('c9',text='软卧') tree.heading('c10',text='动卧') tree.heading('c11',text='硬卧') tree.heading('c12',text='软座') tree.heading('c13',text='硬座') tree.heading('c14',text='无座') tree.heading('c15',text='其他') tree.heading('c16',text='备注') tree.pack(side=LEFT,fill=BOTH) root.resizable(width=False,height=False) root.mainloop()
ProAPI.py:包含需要使用的一些我封装好的API
import re, urllib.parse, urllib.request, http.cookiejar, json, datetime, time from stationsInfo import stationLists, stations2CN, stations2CODE from prettytable import PrettyTable from datetime import timedelta, date import tkinter.messagebox as messagebox from Resources import * """获取数据""" def getData(url): data = '' while 1: try: headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'} req = urllib.request.Request(url=url, headers=headers) data = urllib.request.urlopen(req).read().decode('utf-8') # print(url) # print(data) # if data['status'] == False: # break if data.startswith(u'\ufeff'): data = data.encode('utf8')[3:].decode('utf-8') break except: continue return data """解析响应数据""" def resolveData(from_station, to_station, date): #拼接出查询链接 url = 'https://kyfw.12306.cn/otn/leftTicket/queryA?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 = [] 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' or item[0] == '' or item[1] == '列车运行图调整,暂停发售': data['note_num'] = '不可预订' else: data['note_num'] = item[1] train_no = item[2] from_station_no = item[16] to_station_no = item[17] types = item[35] for pos in name: if data[pos] == '': data[pos] = '-' cont.append(data) tickets = [] for x in cont: tmp = [] for y in name2: if y == "from_station_name": s = stations2CN[x[y]] + '--' + stations2CN[x["to_station_name"]] tmp.append(s) elif y == "start_time": s = x[y] + '--' + x["arrive_time"] tmp.append(s) elif y == "station_train_code": s = x[y] tmp.append(s) elif y == 'date': tmp.append(date.strftime('%Y-%m-%d')) else: tmp.append(x[y]) tickets.append(tmp) return tickets def clean(K,D,G,Z,T): del K[:] del D[:] del Z[:] del G[:] del T[:] #检查输入信息from_station, to_station, d def inputArgs(from_station, to_station, d): # 校验 flag1 = False flag2 = False from_index = stationLists.count(from_station) to_index = stationLists.count(to_station) # 始发站在车站列表中,并且始发站和终点站不同 if from_index > 0 and to_station != from_station: flag1 = True # 终点站在车站列表中,并且始发站和终点站不同 if to_index > 0 and to_station != from_station: flag2 = True if not flag1: info['flag'] = 'False' messagebox.showinfo('ERROR', '输入的出发站有误,请重新输入') if not flag2: info['flag'] = 'False' messagebox.showinfo('ERROR', '输入的终点站有误,请重新输入') info['from_station'] = from_station info['to_station'] = to_station info['from_date'] = d return info
代码中涉及的字典、列表等:
Resources.py:
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": '' } name2 = [ "date", "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" ] 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" ] info = { 'from_station': '', 'to_station': '', 'from_date': '', 'flag':'' } pricesDic = { 'A': '', 'B': '', 'C': '', 'D': '', 'E': '', 'F': '', 'G': '', 'H': '', 'I': '', 'J': '' } priceName = [ "swz_num", "dw_num", "zy_num", "ze_num", "gr_num", "rw_num", "yw_num", "rz_num", "yz_num", "wz_num" ]
还有全国车站列表,用于将车站拼音、中文、简拼—>车站代码和车站代码—>中文的stationsInfo.py:
https://pan.baidu.com/s/1i4FTjgD
相关文章推荐
- python采集系统(小练手:爬取12306余票查询页面)
- Python的图形化界面
- 基于ExtJs框架实现高级查询界面的代码
- Python操作Mysql实例代码教程在线版(查询手册)_python
- Python查询Mysql时返回字典结构的代码
- 10 行 Python 代码写的模糊查询
- python代码查询港澳通行证办理进度
- Python查询IP地址归属完整代码
- Python操作Mysql实例代码教程在线版(查询手册)
- python 查询12306班车情况
- Python操作Mysql实例代码教程在线版(查询手册)
- 使用Python和Splinter实现12306火车票查询与抢票
- GeoPython 随笔:空间数据查询——测试代码
- Python爬取12306实现火车票查询
- Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
- 图形化界面,如何上传本地代码到Github?
- 21. Python脚本学习笔记二十一图形化界面
- (二)、Python查询12306余票:联网查询余票信息并解析
- 很方便的工具——代码生成工具之Winform查询列表界面生成
- PySide——Python图形化界面入门教程(二)