########################################################

# 火车票抢票系统V1.0

########################################################

import requests

import Station_Parse

import threading

import os

from datetime import datetime

from splinter.browser import Browser

from time import sleep

from tkinter import *

from PIL import Image, ImageTk

from tkinter import messagebox

from requests.packages.urllib3.exceptions import InsecureRequestWarning

# 忽视该警告

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

# 车票查询部分

#-------------------------------------------------------------------------------------------------------------------------------------------

# 数据处理+显示

class Trains_Demo():

# 初始化

def __init__(self, txt_show_ticket, raw_trains, option):

self.headers = '车次: 车站: 时间: 历时: 商务/特等座: 一等座: 二等座: 高级软卧: 软卧: 动卧: 硬卧: 软座: 硬座: 无座:'.split()

self.raw_trains = raw_trains

self.option = option

txt_show_ticket.delete(1.0, END)

# 获取出发和到达站

def get_from_to_station_name(self, data_list):

self.from_station_name = data_list[6]

self.to_station_name = data_list[7]

self.from_to_station_name = Station_Parse.parse_station().disparse(self.from_station_name) + '-->' + Station_Parse.parse_station().disparse(self.to_station_name)

return self.from_to_station_name

# 获得出发和到达时间

def get_start_arrive_time(self, data_list):

self.start_arrive_time = data_list[8] + '-->' + data_list[9]

return self.start_arrive_time

# 解析trains数据(与headers依次对应)

def parse_trains_data(self, data_list):

return {

'trips': data_list[3],

'from_to_station_name': self.get_from_to_station_name(data_list),

'start_arrive_time': self.get_start_arrive_time(data_list),

'duration': data_list[10],

'business_premier_seat': data_list[32] or '--',

'first_class_seat': data_list[31] or '--',

'second_class_seat': data_list[30] or '--',

'senior_soft_sleep': data_list[21] or '--',

'soft_sleep': data_list[23] or '--',

'move_sleep': data_list[33] or '--',

'hard_sleep': data_list[28] or '--',

'soft_seat': data_list[24] or '--',

'hard_seat': data_list[29] or '--',

'no_seat': data_list[26] or '--',

}

# 判断是否需要显示

def need_show(self, data_list):

self.trips = data_list[3]

initial = self.trips[0].lower()

if 'a' in self.option:

return self.trips

else:

return(initial in self.option)

# 数据显示

def show_trian_data(self):

self.t_num = 0

for self.train in self.raw_trains:

self.data_list = self.train.split('|')

if self.need_show(self.data_list):

self.values_row = []

self.parsed_train_data = self.parse_trains_data(self.data_list)

self.values_row.append(self.headers[0] + self.parsed_train_data['trips'])

self.values_row.append(self.headers[1] + self.parsed_train_data['from_to_station_name'])

self.values_row.append(self.headers[2] + self.parsed_train_data['start_arrive_time'])

self.values_row.append(self.headers[3] + self.parsed_train_data['duration'])

self.values_row.append(self.headers[4] + self.parsed_train_data['business_premier_seat'])

self.values_row.append(self.headers[5] + self.parsed_train_data['first_class_seat'])

self.values_row.append(self.headers[6] + self.parsed_train_data['second_class_seat'])

self.values_row.append(self.headers[7] + self.parsed_train_data['senior_soft_sleep'])

self.values_row.append(self.headers[8] + self.parsed_train_data['soft_sleep'])

self.values_row.append(self.headers[9] + self.parsed_train_data['move_sleep'])

self.values_row.append(self.headers[10] + self.parsed_train_data['hard_sleep'])

self.values_row.append(self.headers[11] + self.parsed_train_data['soft_seat'])

self.values_row.append(self.headers[12] + self.parsed_train_data['hard_seat'])

self.values_row.append(self.headers[13] + self.parsed_train_data['no_seat'])

self.t_num += 1

txt_show_ticket.insert(END, '第%d班:' % self.t_num + '*'*80)

txt_show_ticket.insert(END, '\n')

txt_show_ticket.insert(END, self.values_row)

txt_show_ticket.insert(END, '\n')

# 车票查询

class Query_Ticket():

# 初始化

def __init__(self, txt_show_ticket, ticket_option, from_station, to_station, date):

# 请求地址的模板

self.url_template = (

'https://kyfw.12306.cn/otn/leftTicket/query{}?leftTicketDTO.'

'train_date={}&'

'leftTicketDTO.from_station={}&'

'leftTicketDTO.to_station={}&'

'purpose_codes=ADULT'

)

self.ticket_option = ticket_option

self.from_station = from_station

self.to_station = to_station

self.date = date

# 获得请求地址

def request_url1(self):

return(self.url_template.format('A', self.date, self.from_station, self.to_station))

def request_url2(self):

return(self.url_template.format('Z', self.date, self.from_station, self.to_station))

# 查询车票

def query(self):

self.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3294.6 Safari/537.36'}

self.res = requests.get(self.request_url1(), headers=self.headers, verify=False)

try:

try:

self.trains = self.res.json()['data']['result']

except:

self.res = requests.get(self.request_url2(), headers=self.headers, verify=False)

self.trains = self.res.json()['data']['result']

Trains_Demo(txt_show_ticket, self.trains, self.ticket_option).show_trian_data()

except:

title = '提示'

message = '出了点小问题,请重新点击按钮!'

messagebox.showinfo(title, message)

#-------------------------------------------------------------------------------------------------------------------------------------------

# 抢票部分

#-------------------------------------------------------------------------------------------------------------------------------------------

# 抢票

class Buy_Tickets(object):

# 初始化

def __init__(self, username, passwd, order, passengers, dtime, starts, ends):

self.url_template = (

'https://kyfw.12306.cn/otn/leftTicket/query{}?leftTicketDTO.'

'train_date={}&'

'leftTicketDTO.from_station={}&'

'leftTicketDTO.to_station={}&'

'purpose_codes=ADULT'

)

self.username = username

self.passwd = passwd

# 日期

self.dtime = dtime

# 乘客名

self.passengers = passengers.split(',')

# 起始地和终点

self.starts = Station_Parse.parse_station().parse(starts)

self.ends = Station_Parse.parse_station().parse(ends)

if self.starts is None or self.ends is None:

self.title = '提示'

self.message = '请输入有效的车站名'

messagebox.showinfo(self.title, self.message)

# 车次

self.order = order

if self.order != '0':

self.order = self.order_transfer()

while(not self.order):

sleep(1)

self.order = self.order_transfer()

# 起始地和终点转为cookie值

self.starts = self.Get_Cookies()[0] + '%2C' + self.starts

self.ends = self.Get_Cookies()[1] + '%2C' + self.ends

self.login_url = 'https://kyfw.12306.cn/otn/login/init'

self.initMy_url = 'https://kyfw.12306.cn/otn/index/initMy12306'

self.ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init'

self.driver_name = 'chrome'

# self.executable_path = 'D:\\Python35\\Scripts\\chromedriver.exe'

# 登录

def login(self):

self.driver.visit(self.login_url)

self.driver.fill('loginUserDTO.user_name', self.username)

self.driver.fill('userDTO.password', self.passwd)

self.title = '提示'

self.message = '请在自动打开的浏览器中输入验证码!'

messagebox.showinfo(self.title, self.message)

while True:

if self.driver.url != self.initMy_url:

sleep(1)

else:

break

# 车次转换

def order_transfer(self):

self.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3294.6 Safari/537.36'}

self.res = requests.get(self.url_template.format('A', self.dtime, self.starts, self.ends), headers=self.headers, verify=False)

try:

try:

self.trains = self.res.json()['data']['result']

except:

self.res = requests.get(self.url_template.format('Z', self.dtime, self.starts, self.ends), headers=self.headers, verify=False)

self.trains = self.res.json()['data']['result']

self.num = 0

for self.train in self.trains:

self.data_list = self.train.split('|')

if self.data_list[3] == self.order:

break

self.num += 1

if self.num == len(self.trains):

self.title = '提示'

self.message = '您输入的车次不存在,系统将自动选择任意车次!'

messagebox.showinfo(self.title, self.message)

self.num = '0'

return self.num

except:

title = '提示'

message = '因为网络原因正在重新尝试!'

messagebox.showinfo(title, message)

return None

# 中文转Unicode

def to_unicode(self, string):

self.uni = ''

for s in string:

self.uni += hex(ord(s)).upper().replace('0X', '%u')

return self.uni

# 将起始地和终点转化为相应的Cookies

def Get_Cookies(self):

return [self.to_unicode(self.starts), self.to_unicode(self.ends)]

# 买票

def start_buy(self):

self.driver = Browser(driver_name=self.driver_name) # , executable_path=self.executable_path

self.driver.driver.set_window_size(700, 500)

self.login()

self.driver.visit(self.ticket_url)

try:

self.title = '提示'

self.message = '开始购票!'

messagebox.showinfo(self.title, self.message)

# 加载查询信息

self.driver.cookies.add({"_jc_save_fromStation": self.starts})

self.driver.cookies.add({"_jc_save_toStation": self.ends})

self.driver.cookies.add({"_jc_save_fromDate": self.dtime})

self.driver.reload()

if self.order != '0':

while self.driver.url == self.ticket_url:

self.driver.find_by_text('查询').click()

# self.title = '提示'

# self.message = '开始尝试预订...'

# messagebox.showinfo(self.title, self.message)

try:

self.driver.find_by_text('预订')[self.order].click()

sleep(1.5)

except:

# self.title = '提示'

# self.message = '预订失败...'

# messagebox.showinfo(self.title, self.message)

continue

else:

while self.driver.url == self.ticket_url:

self.driver.find_by_text('查询').click()

# self.title = '提示'

# self.message = '开始尝试预订...'

# messagebox.showinfo(self.title, self.message)

try:

for i in self.driver.find_by_text('预订'):

i.click()

sleep(1)

except:

# self.title = '提示'

# self.message = '预订失败...'

# messagebox.showinfo(self.title, self.message)

continue

self.title = '提示'

self.message = '开始选择用户~~~'

messagebox.showinfo(self.title, self.message)

sleep(1)

for p in self.passengers:

self.driver.find_by_text(p).last.click()

sleep(0.5)

if p[-1] == ')':

self.driver.find_by_id('dialog_xsertcj_ok').click()

self.title = '提示'

self.message = '提交订单中...'

messagebox.showinfo(self.title, self.message)

sleep(1)

self.driver.find_by_id('submitOrder_id').click()

sleep(2)

self.title = '提示'

self.message = '确认选座中...'

messagebox.showinfo(self.title, self.message)

self.driver.find_by_id('qr_submit_id').click()

self.title = '提示'

self.message = '预订成功...'

messagebox.showinfo(self.title, self.message)

self.content = '恭喜您抢票成功,请在半小时内完成支付!!!'

_ = os.system('mshta vbscript:createobject("sapi.spvoice").speak("%s")(window.close)' % self.content)

except:

self.title = '提示'

self.message = '出现了一点小错误,可能是输入信息有误导致的...'

messagebox.showinfo(self.title, self.message)

#-------------------------------------------------------------------------------------------------------------------------------------------

# 界面部分

#-------------------------------------------------------------------------------------------------------------------------------------------

# 界面初始化

root = Tk()

root.title('火车票抢票系统V1.0')

root.resizable(False, False)

root.geometry('650x500+400+120')

# 设置背景图片

image_path = r'bg2_demo.png'

bg = Image.open(image_path)

bgimg = ImageTk.PhotoImage(bg)

lb_bgimg = Label(root, image=bgimg)

lb_bgimg.grid()

# 布局

# 查询功能

class Query_Thread(threading.Thread):

def __init__(self, *args, **kwargs):

super(Query_Thread, self).__init__(*args, **kwargs)

self.__running = threading.Event()

self.__running.set()

def run(self):

while self.__running.isSet():

global txt_show_ticket

self.ticket_option = str(en_option_var.get()).replace(' ', '')

self.from_station = str(en_starts_var.get()).replace(' ', '')

self.to_station = str(en_ends_var.get()).replace(' ', '')

self.date = str(en_date_var.get()).replace(' ', '')

self.from_station = Station_Parse.parse_station().parse(self.from_station)

self.to_station = Station_Parse.parse_station().parse(self.to_station)

if not self.ticket_option:

self.title = '提示'

self.message = '请输入有效的类型'

messagebox.showinfo(self.title, self.message)

self.__running.clear()

break

if self.from_station is None or self.to_station is None:

self.title = '提示'

self.message = '请输入有效的车站名'

messagebox.showinfo(self.title, self.message)

self.__running.clear()

break

if self.date:

if datetime.strptime(self.date, '%Y-%m-%d') < datetime.now():

self.title = '提示'

self.message = '请输入有效日期'

messagebox.showinfo(self.title, self.message)

self.__running.clear()

break

else:

title = '提示'

message = '请输入有效日期'

messagebox.showinfo(title, message)

self.__running.clear()

break

Query_Ticket(txt_show_ticket, self.ticket_option, self.from_station, self.to_station, self.date).query()

self.__running.clear()

# 查询回调函数

def bt_query_ticket():

t_Query = Query_Thread()

t_Query.start()

# 查询按钮

button_query = Button(root, text='查询', bd=5, width=10, height=2, command=bt_query_ticket, font=('楷体', 12), bg='skyblue')

button_query.place(relx=0.70, rely=0.12, anchor=CENTER)

# 抢票功能

class Buy_Thread(threading.Thread):

def __init__(self, *args, **kwargs):

super(Buy_Thread, self).__init__(*args, **kwargs)

self.__running = threading.Event()

self.__running.set()

def run(self):

while self.__running.isSet():

self.starts = str(en_starts_var.get()).replace(' ', '')

self.ends = str(en_ends_var.get()).replace(' ', '')

self.dtime = str(en_date_var.get()).replace(' ', '')

self.passengers = str(en_passengers_var.get()).replace(' ', '')

self.order = str(en_order_var.get()).replace(' ', '')

self.username = str(en_user_var.get()).replace(' ', '')

self.password = str(en_pwd_var.get()).replace(' ', '')

if self.dtime:

if datetime.strptime(self.dtime, '%Y-%m-%d') < datetime.now():

self.title = '提示'

self.message = '请输入有效日期'

messagebox.showinfo(self.title, self.message)

self.__running.clear()

break

else:

title = '提示'

message = '请输入有效日期'

messagebox.showinfo(title, message)

self.__running.clear()

break

if not self.username or not self.password:

title = '提示'

message = '请输入有效用户名和密码'

messagebox.showinfo(title, message)

self.__running.clear()

break

if not self.passengers:

title = '提示'

message = '请输入有效乘客名'

messagebox.showinfo(title, message)

self.__running.clear()

break

if not self.order:

title = '提示'

message = '请输入有效车次'

messagebox.showinfo(title, message)

self.__running.clear()

break

Buy_Tickets(self.username, self.password, self.order, self.passengers, self.dtime, self.starts, self.ends).start_buy()

self.__running.clear()

# 抢票回调函数

def bt_buy_ticket():

t_Buy = Buy_Thread()

t_Buy.start()

# 抢票按钮

button_buy = Button(root, text='抢票', bd=5, width=10, height=2, command=bt_buy_ticket, font=('楷体', 12), bg='skyblue')

button_buy.place(relx=0.90, rely=0.12, anchor=CENTER)

# 查询显示框

txt_show_ticket = Text(root, bd=4, width=90, height=28, font=('楷体', 10))

txt_show_ticket.bind("", lambda e : "break")

txt_show_ticket.place(relx=0.50, rely=0.60, anchor=CENTER)

# 输入框

# 乘客名

en_passengers_var = StringVar()

lb_passengers = Label(root, text='乘客名:', font=('楷体', 12))

lb_passengers.place(relx=0.10, rely=0.05, anchor=CENTER)

en_passengers = Entry(root, textvariable=en_passengers_var, width=10)

en_passengers.place(relx=0.10, rely=0.10, anchor=CENTER)

# 出发地

en_starts_var = StringVar()

lb_starts = Label(root, text='出发地:', font=('楷体', 12))

lb_starts.place(relx=0.22, rely=0.05, anchor=CENTER)

en_starts = Entry(root, textvariable=en_starts_var, width=10)

en_starts.place(relx=0.22, rely=0.10, anchor=CENTER)

# 目的地

en_ends_var = StringVar()

lb_ends = Label(root, text='目的地:', font=('楷体', 12))

lb_ends.place(relx=0.34, rely=0.05, anchor=CENTER)

en_ends = Entry(root, textvariable=en_ends_var, width=10)

en_ends.place(relx=0.34, rely=0.10, anchor=CENTER)

# 日期

en_date_var = StringVar()

lb_date = Label(root, text='日期: ', font=('楷体', 12))

lb_date.place(relx=0.46, rely=0.05, anchor=CENTER)

en_date = Entry(root, textvariable=en_date_var, width=10)

en_date.place(relx=0.46, rely=0.10, anchor=CENTER)

# 类型(查询用)

en_option_var = StringVar()

lb_option = Label(root, text='类型(查询用):', font=('楷体', 10))

lb_option.place(relx=0.12, rely=0.15, anchor=CENTER)

en_option = Entry(root, textvariable=en_option_var, width=10)

en_option.place(relx=0.26, rely=0.15, anchor=CENTER)

# 车次(抢票用)

en_order_var = StringVar()

lb_order = Label(root, text='车次(抢票用):', font=('楷体', 10))

lb_order.place(relx=0.40, rely=0.15, anchor=CENTER)

en_order = Entry(root, textvariable=en_order_var, width=10)

en_order.place(relx=0.54, rely=0.15, anchor=CENTER)

# 用户名(抢票用)

en_user_var = StringVar()

lb_user = Label(root, text='用户名(抢票):', font=('楷体', 10))

lb_user.place(relx=0.12, rely=0.20, anchor=CENTER)

en_user = Entry(root, textvariable=en_user_var, width=10)

en_user.place(relx=0.26, rely=0.20, anchor=CENTER)

# 密码(抢票用)

en_pwd_var = StringVar()

lb_pwd = Label(root, text='密码(抢票): ', font=('楷体', 10))

lb_pwd.place(relx=0.40, rely=0.20, anchor=CENTER)

en_pwd = Entry(root, textvariable=en_pwd_var, show='*', width=10)

en_pwd.place(relx=0.54, rely=0.20, anchor=CENTER)

root.mainloop()

#-------------------------------------------------------------------------------------------------------------------------------------------

python查火车票_Python查询火车票(三)相关推荐

  1. python查天气预报_python查询全国天气预报

    [实例简介] [实例截图] [核心代码] from tkinter import * import tkinter as tk import requests from PIL import Imag ...

  2. python查天气预报_Python编写一个天气预报查询系统

    Python编写一个天气预报查询系统 学了Python这么久 可以用它来做许多好玩的小程序哦! 这里给 大家做了个查询天气预报的小程序! 可以查询未来几天的天气! 需要大家自己修改下代码即可! 首先我 ...

  3. python查题_python 数据库连表查询习题

    # 多表查询 # 连表查 # 内连接 必须左表和右表中条件互相匹配的项才会被显示出来 # 表1 inner join 表2 on 条件 # 外链接 会显示条件不匹配的项 # left join 左表显 ...

  4. python项目实践_Python 项目实践三(Web应用程序)第二篇

    接着上节的继续学习,使用Django创建网页的过程通常分三个阶段:定义URL.编写视图和编写模板.首先,你必须定义URL模式,每个URL都被映射到特定的视图--视图函数获取并处理网页所需的数据.视图函 ...

  5. python神经网络作用_Python · 神经网络(三*)· 网络

    (这里是最终成品的 GitHub 地址) (这里是本章用到的 GitHub 地址) 推荐先修章节:Python · 神经网络(二*)· 层 Python · 神经网络(三)· 网络 由于分形这个东西是 ...

  6. python请输入_python中的三种输入方式

    python中的三种输入方式 python2.X python2.x中以下三个函数都支持: raw_input() input() sys.stdin.readline() raw_input( )将 ...

  7. python常用格式化_python的常用三种格式化方法

    最近看别人代码时,发现一个新的打印输出格式,很有意思,print(f'{}'),所以找了些资料学习总结了一下,现把几个常用的方法记录下来. 神奇的 % 号 % 号格式化字符串沿用的是C语言的方法,py ...

  8. python通信原理_python入门第三十三天--网络通信原理(补充)

    1.互联网的本质就是一系列的网络协议 一台硬设有了操作系统,然后装上软件你就可以正常使用了,然而你也只能自己使用 像这样,每个人都拥有一台自己的机器,然而彼此孤立 英语成为世界上所有人通信的统一标准, ...

  9. python是谁_Python逻辑推理:三对情侣到底谁和谁结婚

    今天分享并实现一下 @潘石屹 (微博地址:http://blog.sina.com.cn/panshiyi)微博中的题目(#潘石屹用Python解决100个问题#). 一.题目描述 有3对情侣结婚,假 ...

  10. python 逐行调试工具_Python调试的三个工具

    对于 python 代码的调试我们通常都是使用 IDE 自带的调试功能.但是 IDE 提供的调试功能存在局限性,例如在测试服务器上调试代码,但是又不可能在测试服务器上安装 IDE 进行调试.这时我们就 ...

最新文章

  1. 土豆上的小霉菌引发百万人死亡和逃难,却造就全球7千万后裔
  2. django设置mysql数据库连接_django如何设置连接mysql数据库
  3. gis怎么通过水库划分子流域_ArcGIS提取小流域——以北京为例,提取出密云水库...
  4. 欢迎来到 C# 9.0(Welcome to C# 9.0)
  5. 《The Art of Readable Code》学习笔记(一)
  6. 管理软件实施(1)——什么是管理软件
  7. 学维修电脑要多久_开奶茶店要学多久?预算大概要多少?
  8. AttributeError: 'dict' object has no attribute 'has_key'
  9. 随机森林:对UCI数据集的分类实现
  10. 后深度学习的挑战与思考(PRCV 焦李成 报告记录)
  11. 影响塑料制品注塑质量的因素,以及解决方案
  12. 一、什么是统一社会信用代码
  13. [WinError 193] %1 不是有效的 Win32 应用程序问题解决
  14. 【Day2.7】在华欣夜市吃海鲜大餐
  15. 支持ECSHOP 2.73手机客户端
  16. 如何将电脑下载的电子书导入手机kindle APP
  17. lcd1602显示和led显示的区别在哪里
  18. 自学C++之自定义数据类型与自定义类之数组使用4例
  19. 嵌入式Linux--根文件系统(一)简介
  20. 浙江大学计算机科学与技术学院分数,2019浙江大学在本省的录取分数线多少分?浙江大学是双一流吗?...

热门文章

  1. 判断是否是支付宝客户端环境和支付宝版本
  2. 坚果J10的真实流明到底怎么样?坚果J10有哪些缺点
  3. 可汗学院公开课: 统计学_1 统计学基本知识、二项及泊松分布
  4. 子午线弧长计算公式matlab,椭球面上的几种弧长计算和大地线
  5. 报道|香港科大校友“盐马行”活动成功举办
  6. C语言中u8 u16 u32含义,有关stm32的问题,程序里面的u8、u16这些是什么意思啊
  7. android网络工程师,网络工程师考试app下载-网络工程师考试 安卓版v3.0.7-PC6安卓网...
  8. java怎么重新开始游戏_添加开始,停止,重置按钮到简单的Java游戏
  9. Hexo个人免费博客(二) 创建主界面分页签和新博客
  10. pidgin qq_Pidgin入门:Skype的开源替代品