selenium实现疫情下12306买票 Edge

#所有流程

 

!!!不要修改为抢票,遵守法律法规是每一个中国公民应尽的责任,盗用并造成不良后果自负!!!

'''

#可以实现买学生票,儿童票,残疾票,成人票和所有能选的座位类别。

2022-05-22目前为止还是完全正常运行的,之后网页改动就不一定了哦!!!!!!
12306官网模拟买票:
1.输入账号密码登录
2.取消疫情通告对话框
3.点击车票,点击单程
4.取消第二个疫情通告变更框
5.键入出发地,目的地,出发时间,剩下为默认
6.点击查询按钮
7.1.没有车票则回到5修改条件
7.2.有车票则展示所有列车名字和信息
8.用户选择列车的名字(名字错误将重新选择)
9.点击预定按钮
10.点击乘车人(默认为第一乘车人,且暂时选择为成人)
11.根据展示出的票种和序列,用户选择票种(序号)
12.根据展示出的席别和序号,用户选择席别(序号)
13.点击提交订单
14.点击确定提交(不可选择位置)
15.在12306app上交钱
'''

 

 

 

#最熟悉的导包

from selenium import webdriver
from time import sleep
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

 

'''
如果测试,请把最后的确认购买按钮注释掉
'''

#规避检测

#实测这个无效,在控制台还是能发现被检测出来
caps={
'ms:edgeOptions':{
'excludeSwitches':['enable-automation']}
}

#Edge驱动 括号里面的是驱动的路径
bro = webdriver.Edge('C:/Program Files (x86)/Microsoft/Edge/Application/msedgedriver',capabilities=caps)

 

 

#登录

def denglu(bro):

bro.get('https://www.12306.cn/index/')
sleep(4)
#bro.set_window_size(1920, 1080)
#点击登录按钮
button = bro.find_element_by_id('J-btn-login')
button.click()


#定位账号密码
username = bro.find_element_by_id('J-userName')
password = bro.find_element_by_id('J-password')

#输入账号密码
username.send_keys('xxx')
password.send_keys('xxx')

#点击登录
login_button = bro.find_element_by_xpath('//div[@class="login-btn"]/a')
login_button.click()

#定位弹窗按钮
#等待需要定位的元素加载出来再进行
WebDriverWait(bro, 15).until(EC.presence_of_element_located((By.XPATH,'//*[@class="dzp-confirm"]/div[2]/div[3]/a')))
tanchuang_button = bro.find_element_by_xpath('//*[@class="dzp-confirm"]/div[2]/div[3]/a')
tanchuang_button.click()

 

#购买单程! 往返不行哦
def buy_one_way(bro):
#车票菜单
ticket_botton = bro.find_element_by_xpath('//*[@id="J-chepiao"]/a/i')
ticket_botton.click()
#单程菜单
one_way_ticket_botton = bro.find_element_by_xpath('//*[@id="megamenu-3"]/div[1]/ul/li[1]/a')
one_way_ticket_botton.click()

#等待提示框缓冲完成
WebDriverWait(bro, 10).until(EC.presence_of_element_located((By.XPATH,'//*[@id="qd_closeDefaultWarningWindowDialog_id"]')))
tip_botton = bro.find_element_by_xpath('//*[@id="qd_closeDefaultWarningWindowDialog_id"]')
tip_botton.click()


#编辑出发地和目的地
#看看是否有票
havesign = False

#只要没有车则需要重新输入起始和终点地,出发时间

while(1):



departure_textbox = bro.find_element_by_id('fromStationText')
departure_textbox.click()
#标记出发地
departure_text = (input('输入起始站: '))
#departure_text = '北京'
departure_textbox.send_keys(departure_text)
departure_textbox.click()
departure_textbox.send_keys(departure_text)
departure_textbox.send_keys(Keys.ENTER)

destination_textbox = bro.find_element_by_id('toStationText')
destination_textbox.click()
destination_textbox.send_keys(input('输入终点站: '))
#destination_textbox.send_keys('天津')
destination_textbox.send_keys(Keys.ENTER)





#sleep(2)
#编辑出发时间
gotime = bro.find_element_by_xpath('//*[@id="train_date"]')
ActionChains(bro).double_click(gotime).click(gotime).perform()
gotime.send_keys(Keys.BACKSPACE)
gotime.send_keys(input('输入出发时间: xxxx-xx-xx : '))
#gotime.send_keys('2022-05-05')

#查询按钮
query_ticket_botton = bro.find_element_by_id('query_ticket')
query_ticket_botton.click()


#等待缓冲完成
try:
WebDriverWait(bro, 10).until(EC.presence_of_element_located((By.XPATH,'//tbody[@id="queryLeftTable"]/tr')))
except:
sleep(1)
pass


#看看是否有票
try:
bro.find_element_by_xpath('//tbody[@id="queryLeftTable"]/tr')

except:
havesign = False
else:
havesign = True

if(havesign) :
break
else:
print('没有车,请重新搜索。')



#等待查票信息加载
sleep(5)



#WebDriverWait(bro, 1000).until(EC.prsesece_of_element_located((By.XPATH,'//tr/td[1]/div/div[1]/div/a')))
#ticket_list = bro.find_element_by_xpath('//tr/td[1]/div/div[1]/div/a')
#元素多就用复数!!!!!!!!!!!


#定位到所有车次所在的行
ticket_ele_list = bro.find_elements_by_xpath('//*[@id="queryLeftTable"]/tr[not(@datatran)]')
#for t in ticket_ele_list:
# ticket_list.append(t.text)
#print(ticket_ele_list,len(ticket_ele_list))


#定义火车名字和火车信息
train_name_list = []
#二维的
train_info_list = []
#列表外围长度为火车数,内层为信息数,大概3,5个把
for i in range(len(ticket_ele_list)):
train_info_list.append([])


print('------------------------------------------\n')
print('载入列车信息中......')
#添加车名字
for tn in ticket_ele_list:
#tn.find_很重要,定位到当前列表定位的位置,从此开始继续操作
train_name_list.append(tn.find_element_by_xpath('./td[1]/div/div[1]/div/a').text)
#print(train_name_list)

#print(ticket_ele_list)
#添加车信息
i_count = 0
for ti in ticket_ele_list:

train_info_list[i_count].append(('始终站: ' + ti.find_element_by_xpath('./td[1]/div/div[2]/strong[1]').text + '-->' + ti.find_element_by_xpath('./td[1]/div/div[2]/strong[2]').text))
train_info_list[i_count].append(('始终时间: ' + ti.find_element_by_xpath('./td[1]/div/div[3]/strong[1]').text + '---' + ti.find_element_by_xpath('./td[1]/div/div[3]/strong[2]').text))
train_info_list[i_count].append(('历时: ' + ti.find_element_by_xpath('./td[1]/div/div[4]/strong[1]').text + '(' + ti.find_element_by_xpath('./td[1]/div/div[4]/span').text + ')'))

i_count +=1
#print(train_info_list)

#把车名字和信息封装为字典
name_info_dic = dict(zip(train_name_list,train_info_list))

for name,info in name_info_dic.items():
print('%6s'%str(name) + ' : ' + str(info))


#定位用户键入火车名字的行(index),以便于进行操作
train_name_index = 0

 

#当输入的车名和列表中展示的车名不一样的时候需要重新输入车名直到正确为止
while(1):
#input_train_name = 'C2007'
input_train_name = input('输入火车名: ')
if input_train_name in train_name_list:
train_name_index = train_name_list.index(input_train_name) + 1
#print(train_name_index)
break
else:
print('车名错误,重新搜索.')


#判断是否有车 sign 为真则有
sign = False
try:
sleep(1)
bro.find_element_by_xpath('//*[@id="queryLeftTable"]/tr[not(@datatran)][%d]/td[13]/a'%train_name_index).text
sign = True
except:
pass

#根据sign 给出提示
if(sign):
print('该车目前有票')
#点击预定按钮转跳网页
sleep(0.5)
yuding_botton = bro.find_element_by_xpath('//*[@id="queryLeftTable"]/tr[not(@datatran)][%d]/td[13]/a'%train_name_index)
yuding_botton.click()


#选择乘车人

#需要提前添加一个乘车人,本程序默认选择第一个乘车人
sleep(0.5)
first_passenger_botton = bro.find_element_by_xpath('//*[@id="normalPassenger_0"]')
first_passenger_botton.click()
sleep(0.5)

#确认是学生票弹出窗口(先取消掉)
try:
query_stu_botton = bro.find_element_by_xpath('//*[@id="dialog_xsertcj_cancel"]')
query_stu_botton.click()

except:
pass


#解析到票种列表
ticket_type_ele_list = bro.find_elements_by_xpath('//*[@id="ticketType_1"]/option')
#将列表中的文本提取到改列表中
ticket_type_list = []
for i in range(len(ticket_type_ele_list)):
ticket_type_list.append('%d : '%(i+1) + bro.find_element_by_xpath('//*[@id="ticketType_1"]/option[%d]'%(i+1)).text)

#给用户展示票种列表
print('票种类型: ')
print(ticket_type_list)

#用户输入选择的票种序号
#ticket_type_sel_num = 3
ticket_type_sel_num = int(input('选择你的票种序号, 输入序号: '))

#定位票种框
ticket_type_optin_botton = bro.find_element_by_xpath('//*[@id="ticketType_1"]')
ticket_type_optin_botton.click()

#定位票种
ticket_type_sel_botton = bro.find_element_by_xpath('//*[@id="ticketType_1"]/option[%d]'%ticket_type_sel_num)
ticket_type_sel_botton.click()

#如果不是成人票会有弹窗确认
try:
type_query_botton = bro.find_element_by_xpath('//*[@id="dialog_xsertcj_ok"]')
type_query_botton.click()
except:
pass




#选择席别
xibie_botton = bro.find_element_by_xpath('//*[@id="seatType_1"]')
xibie_botton.click()

#席别选择列表
xibie_sel_list =[]
#席别种类
xibie_ele_list = bro.find_elements_by_xpath('//*[@id="seatType_1"]/option')
#将席别种类加入选择列表中,并加上序号
for i in range(len(xibie_ele_list)):
xibie_sel_list.append('%d : '%(i+1) + bro.find_element_by_xpath('//*[@id="seatType_1"]/option[%d]'%(i+1)).text)


#让用户选择席别类,用数字替代汉字
print('席别类型: ')
print(xibie_sel_list)
sel_num = int(input('选择你的席别序号, 输入序号: '))
#sel_num = 1

#用户选择的转换为列表索引,在转换为网页里面的,其实就是不用改
xibie_sel_botton = bro.find_element_by_xpath('//*[@id="seatType_1"]/option[%d]'%sel_num)
sleep(0.5)
xibie_sel_botton.click()



#提交订单按钮
submit_order_botton = bro.find_element_by_xpath('//*[@id="submitOrder_id"]')
submit_order_botton.click()

#核对信息按钮

#此按钮点击后在app上支付即可,若是实验,注释掉后面的确定即可,12306每天有3次无后果取消订单的机会
sleep(1)
query_submit_order_botton = bro.find_element_by_xpath('//*[@id="qr_submit_id"]')
sleep(1)
query_submit_order_botton.click()

print('购票成功, 感谢你的使用')

else:
print('该车目前无票')
return



denglu(bro)
buy_one_way(bro)

 

标签: python

添加新评论