当前位置: 首页 > news >正文

python实现自动登录12306抢票 -- selenium

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

python实现自动登录12306抢票 -- selenium

  • 前言
    • 其实网上也出现了很多12306的代码,但是都不是最新的,我也是从网上找别人的帖子,看B站视频,然后写成了这个程序,想分享一下。其中我会说自己遇到的问题以及自己的一个改进。
  • 一、遇到的问题?
    • 1.url-正确的表头:就是首先url不要写错了,然后一定要加正确的表头,才可以拿到数据,就是我日期填写错误,然后生成的url就有问题,浪费了好多时间。日期:2024-01-09 ,不要加两个杠。。。
    • 2.:注意用网页显示的user-agent:
    • 3.拿到车票信息的json数据--代码展示
    • 4. 12306的城市对应的代码json文件,大家可以去网上找下,然后自己编程写一下,我这个也花了一些时间锻炼自己
    • 4.对拿到的车次json数据进行可视化处理,也生成一个列表信息,代码如下
    • 5.程序进入到自动化代码 -- 自动登录 --自动抢票,这里要注意有些操作一定要有时间等待,time.sleep(2)等,是不可以删除的否则会报错,因为操作太快,浏览器没有反应过来。
    • 至此,这个程序完全结束了。这也是最近春节要抢票我特意写的。主要都是学习别人的代码,但是有几个改进是自己学了爬虫,然后结合网页的变化(很多程序是2021,2022的,现在12306的网页有所改变),所写的。
  • 二、改进
    • 1.xpath语法中@id 或者说可以@元素,但是selenium不可以要拆成两部来写。,而且新的selenium语法和前几年的也有所区别。
    • 2.预定按钮的元素定位我没有写死可以自己定义,也就是可以自己选择预定那躺车,比如1,3,4,11等,随便选择。因为这里是用了xpath语法去找到了所有的预订按钮。这个num你也可以放在login.json当中,这样更方面抢票。login.json就是一个字典序列,我是将要填写的东西都放进去。这样不用手动填写。
    • 3.源代码完整展示
  • 三、进阶--展望
    • 1.首先可以将自动化操作用try--except,这样不会一直报错,更为规范。
    • 2.免登录:因为登录其实要验证码,这样抢票也不方便。于是我就又继续学习了一些,发现了两种方法一是可以保存浏览器的数据,因为selenium每次打开的是一个新的程序,但是我们可以通过设置参数,让他打开是有记忆的,但是没有用。第二种,是cookie,是没有什么问题的,目前已经实现,接下尝试各种方法的cookie看行不行。后续我会发此程序。
    • 3.多线程多进程:主要我已经实现cookie免登录,我想着是否可以打开多个页面,然后多个账号,一起抢他们所需要的票呢。
  • 总结
    • 1.最开始跟着写这个程序只会照着抄,然后根本不懂,后面就是差了一点点成功,也不会找错误。
    • 2.后面学习了一下爬虫,更明白一点语法以及自己也更会如何定位元素了。还有就是request的一个请求,这些代码也更看得懂了
    • 3.想着结合多线程然后实现批量抢票,同时也希望代价的容错率高,也就是说在自动化不用点几下程序就不行了,让它可以有更好的性能。-- 未来学习的一个点。加油!!!


前言

其实网上也出现了很多12306的代码,但是都不是最新的,我也是从网上找别人的帖子,看B站视频,然后写成了这个程序,想分享一下。其中我会说自己遇到的问题以及自己的一个改进。


提示:以下是本篇文章正文内容,下面案例可供参考

一、遇到的问题?

1.url-正确的表头:就是首先url不要写错了,然后一定要加正确的表头,才可以拿到数据,就是我日期填写错误,然后生成的url就有问题,浪费了好多时间。日期:2024-01-09 ,不要加两个杠。。。

2.:注意用网页显示的user-agent:

在这里插入图片描述

3.拿到车票信息的json数据–代码展示


import requests
from prettytable import PrettyTable
# 下面的模块就是打开浏览器的操作模块
from selenium import webdriver
from selenium.webdriver.common.keys import Keys# 获取浏览器的用户数据
# chrome ==> chrome://version/
# 个人资料路径 C:\Users\hl\AppData\Local\Temp\scoped_dir18416_1206036739\Default
# 路径的Default要去掉
path = r'D:\game\chromedriver.exe'
user_data_dir = r'C:\Users\hl\AppData\Local\Temp\scoped_dir18416_1206036739'from pypinyin import pinyin, Style
import json
import time"""
发送请求:模拟浏览器对于url地址发送请求
"""
"""根据用户自行输入相关信息,进行查票搜索"""
# 读取城市文件
f = open('city_all.json', encoding='utf-8').read()
city_data = json.loads(f)
print(city_data)# 输入出发和目的城市
# 输入时间
train_date = '2025-01-09'
from_city = input('请输出你出发的城市:')
to_city = input('请输出你要出行的城市:')
print(city_data[from_city])
print(city_data[to_city])headers = {'user-agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36',}# 请求网址
# https://kyfw.12306.cn/otn/leftTicket/queryG?leftTicketDTO.train_date=2025-01-06&leftTicketDTO.from_station=SZQ&leftTicketDTO.to_station=EFG&purpose_codes=ADULT
url = f'https://kyfw.12306.cn/otn/leftTicket/queryG?leftTicketDTO.train_date={train_date}&leftTicketDTO.from_station={city_data[from_city]}&leftTicketDTO.to_station={city_data[to_city]}&purpose_codes=ADULT'# 发送请求 使用request
response = requests.get(url=url, headers=headers)
print(url)
print(response.status_code)
print(response.text)
# 获取数据
json_data = response.json()

4. 12306的城市对应的代码json文件,大家可以去网上找下,然后自己编程写一下,我这个也花了一些时间锻炼自己

在这里插入图片描述

4.对拿到的车次json数据进行可视化处理,也生成一个列表信息,代码如下

import requests
from prettytable import PrettyTable
# 下面的模块就是打开浏览器的操作模块
from selenium import webdriver
from selenium.webdriver.common.keys import Keys# 获取浏览器的用户数据
# chrome ==> chrome://version/
# 个人资料路径 C:\Users\hl\AppData\Local\Temp\scoped_dir18416_1206036739\Default
# 路径的Default要去掉
path = r'D:\game\chromedriver.exe'
user_data_dir = r'C:\Users\hl\AppData\Local\Temp\scoped_dir18416_1206036739'from pypinyin import pinyin, Style
import json
import time"""
发送请求:模拟浏览器对于url地址发送请求
"""
"""根据用户自行输入相关信息,进行查票搜索"""
# 读取城市文件
f = open('city_all.json', encoding='utf-8').read()
city_data = json.loads(f)
print(city_data)# 输入出发和目的城市
# 输入时间
train_date = '2025-01-09'
from_city = '深圳'
to_city = '广州'
print(city_data[from_city])
print(city_data[to_city])headers = {'cookie':f'_uab_collina=173526990403562156621352; JSESSIONID=1B8F19FC6675BDA9782FEA7B06BDC256; route=9036359bb8a8a461c164a04f8f50b252; BIGipServerotn=1725497610.24610.0000; BIGipServerpassport=1005060362.50215.0000; guidesStatus=off; highContrastMode=defaltMode; cursorStatus=off; _jc_save_fromStation=%u6DF1%u5733%2CSZQ; _jc_save_toStation=%u4FE1%u4E30%2CEFG; _jc_save_fromDate={train_date}; _jc_save_wfdc_flag=dc; _jc_save_toDate=2024-12-28','user-agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36',}# 请求网址
# https://kyfw.12306.cn/otn/leftTicket/queryG?leftTicketDTO.train_date=2025-01-06&leftTicketDTO.from_station=SZQ&leftTicketDTO.to_station=EFG&purpose_codes=ADULT
url = f'https://kyfw.12306.cn/otn/leftTicket/queryG?leftTicketDTO.train_date={train_date}&leftTicketDTO.from_station={city_data[from_city]}&leftTicketDTO.to_station={city_data[to_city]}&purpose_codes=ADULT'# 发送请求 使用request
response = requests.get(url=url, headers=headers)
print(url)
print(response.status_code)
print(response.text)
# 获取数据
json_data = response.json()# 解析数据--字典取值:
result = json_data['data']['result']# 实例化对象
tb = PrettyTable()
tb.field_names = ['序号','车次','出发时间','到达时间','耗时','特等座','一等座','二等座','软卧','硬卧','硬座','无座',
]# 定义一个打印序号page
page = 1
# for循环遍历,提取列表里面的元素
for i in result:# 字符串分割,返回列表index = i.split('|')# 通过列表索引位置取值num = index[3] # 车次star_time = index[8] # 出发时间arrive_time = index[9] # 到达时间use_time = index[10] # 耗时special_class = index[32]  # 特等座frist_class = index[31]  # 一等座second_class = index[30] # 二等座hard_sleeper = index[28] # 硬卧hard_seat = index[29] # 硬座no_seat = index[26] # 无座soft_sleeper  = index[23]# 软卧dict = {'序号':'page','车次':'num','出发时间':'star_time','到达时间':'arrive_time','耗时':'use_time','特等座':'special_class','一等座':'frist_class','二等座':'second_class','软卧':'soft_sleeper','硬卧':'hard_sleeper','硬座':'hard_seat','无座': 'no_seat'}tb.add_row([page, #序号索引num, # 车次star_time,# 出发时间arrive_time,# 到达时间use_time, # 耗时special_class, # 特等座frist_class,  # 一等座second_class,# 二等座soft_sleeper,  # 软卧hard_sleeper,# 硬卧hard_seat, # 硬座no_seat,# 无座])page += 1
print(tb)

在这里插入图片描述

5.程序进入到自动化代码 – 自动登录 --自动抢票,这里要注意有些操作一定要有时间等待,time.sleep(2)等,是不可以删除的否则会报错,因为操作太快,浏览器没有反应过来。

def selenium_login():# 0.配置谷歌浏览器加载项options = webdriver.ChromeOptions()options.add_argument(f'--user-data-dir={user_data_dir}') # 添加浏览器数剧# 1.将加载项配置到启动浏览器中 打开/创建浏览器对象driver = webdriver.Chrome(executable_path=r'D:\game\chromedriver.exe', options=options)# 2.输入网址driver.get('https://kyfw.12306.cn/otn/view/index.html')# 3.输入账号 -- > 找到账号的输入框 selenium 通过元素面板去定位元素driver.find_element(by="css selector", value="#J-userName").send_keys(login['account'])# 4.输入密码 -- > 找到密码的输入框driver.find_element(by="css selector", value="#J-password").send_keys(login['password'])# 5.点击登录按钮driver.find_element(by="css selector", value="#J-login").click()time.sleep(0.5)# 6.输入身份证后4位driver.find_element(by="css selector", value="#id_card").send_keys(login['id_card'])# 7.点击获取验证码driver.find_element(by="css selector", value="#verification_code").click()# 8.输入验证码code = input("请输入验证码:")driver.find_element(by="css selector", value="#code").send_keys(code)driver.find_element(by="css selector", value="#verification_code").click()# 9.点击确认按钮driver.find_element(by="css selector", value="#sureClick").click()# 有时候报错是需要延时等待 用 driver.implicitly_wait(10)代码 可以实现加载完就就进行下一步,# 而time.sleep(5)则必须等我规定的时间driver.implicitly_wait(5)# 10,点击车票预定按钮driver.find_element(by="css selector", value="#link_for_ticket").click()# 11.1 选择出发的城市--点击那个框driver.find_element(by="css selector", value="#fromStationText").click()# 11.2 选择出发的城市--选择城市driver.find_element(by="css selector", value="#fromStationText").send_keys(from_city)# 11.3 选择出发的城市--回车确定driver.find_element(by="css selector", value="#fromStationText").send_keys(Keys.ENTER)# 12.1 选择目的的城市--点击那个框driver.find_element(by="css selector", value="#toStationText").click()# 12.2 选择目的的城市--选择城市driver.find_element(by="css selector", value="#toStationText").send_keys(to_city)# 12.3 选择目的的城市--回车确定driver.find_element(by="css selector", value="#toStationText").send_keys(Keys.ENTER)# 13.1 选择出发的日期--点击那个框driver.find_element(by="css selector", value="#train_date").clear()# 12.2 选择出发的日期--选择城市driver.find_element(by="css selector", value="#train_date").send_keys(train_date)# 12.3 选择出发的日期--回车确定driver.find_element(by="css selector", value="#train_date").send_keys(Keys.ENTER)# # 12.4 点击--显示全部可预订的车次# driver.find_element(by="css selector", value="avail_ticket").click()# 12.5 点击查询driver.implicitly_wait(5)driver.find_element(by="css selector", value="#query_ticket").click()num = int(input('请输入您想要的车次:'))# 点击预订按钮 -- 选择要预定的是第几躺车 -- 这个代码没有问题# driver.find_element(by="css selector", value='#ticket_65000G279007_01_03 > td.no-br').click()# //div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]/@id -- 但是selenium的find_elements不可以用@id找到元素。ticket_list = driver.find_elements(by="xpath", value='//div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]')ticket_num = ticket_list[num].get_attribute("id")ticket_pre = ticket_num + ' > td.no-br'# 12.6 点击想要车次的预定按钮driver.find_element(by="css selector", value=f"#{ticket_pre}").click()# 13.1 勾选想要的乘车人driver.find_element(by="css selector", value='#normalPassenger_0').click()# 13.2 提交订单driver.find_element(by="css selector", value='#submitOrder_id').click()driver.implicitly_wait(5)# 13.3 选择靠窗的1F的位置# driver.find_element(by="css selector", value='#1F').click() --这种行不通,只能下方这种driver.find_element(by="css selector", value='#erdeng1 > ul:nth-child(4) > li:nth-child(2)').click()# 13.4 再次确认提交time.sleep(2)driver.find_element(by="css selector", value='#qr_submit_id').click()# driver.find_element(by="css selector", value='#qr_submit_id').click()# # 14.  网上支付 -- payButton# driver.find_element(by="css selector", value='#payButton').click()# # 15.  取消订单 -- cancelButton# driver.find_element(by="css selector", value='#cancelButton').click()

至此,这个程序完全结束了。这也是最近春节要抢票我特意写的。主要都是学习别人的代码,但是有几个改进是自己学了爬虫,然后结合网页的变化(很多程序是2021,2022的,现在12306的网页有所改变),所写的。


二、改进

1.xpath语法中@id 或者说可以@元素,但是selenium不可以要拆成两部来写。,而且新的selenium语法和前几年的也有所区别。

    # 点击预订按钮 -- 选择要预定的是第几躺车 -- 这个代码没有问题# driver.find_element(by="css selector", value='#ticket_65000G279007_01_03 > td.no-br').click()# //div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]/@id -- 但是selenium的find_elements不可以用@id找到元素。ticket_list = driver.find_elements(by="xpath", value='//div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]')ticket_num = ticket_list[num].get_attribute("id")ticket_pre = ticket_num + ' > td.no-br'

2.预定按钮的元素定位我没有写死可以自己定义,也就是可以自己选择预定那躺车,比如1,3,4,11等,随便选择。因为这里是用了xpath语法去找到了所有的预订按钮。这个num你也可以放在login.json当中,这样更方面抢票。login.json就是一个字典序列,我是将要填写的东西都放进去。这样不用手动填写。

    num = int(input('请输入您想要的车次:'))# 点击预订按钮 -- 选择要预定的是第几躺车 -- 这个代码没有问题# driver.find_element(by="css selector", value='#ticket_65000G279007_01_03 > td.no-br').click()# //div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]/@id -- 但是selenium的find_elements不可以用@id找到元素。ticket_list = driver.find_elements(by="xpath", value='//div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]')ticket_num = ticket_list[num].get_attribute("id")ticket_pre = ticket_num + ' > td.no-br'

login.json的内容展示
在这里插入图片描述

3.源代码完整展示

import requests
from prettytable import PrettyTable
# 下面的模块就是打开浏览器的操作模块
from selenium import webdriver
from selenium.webdriver.common.keys import Keys# 获取浏览器的用户数据
# chrome ==> chrome://version/
# 个人资料路径 C:\Users\hl\AppData\Local\Temp\scoped_dir18416_1206036739\Default
# 路径的Default要去掉
path = r'D:\game\chromedriver.exe'
user_data_dir = r'C:\Users\hl\AppData\Local\Temp\scoped_dir18416_1206036739'from pypinyin import pinyin, Style
import json
import time"""
发送请求:模拟浏览器对于url地址发送请求
"""
"""根据用户自行输入相关信息,进行查票搜索"""
# 读取城市文件
f = open('city_all.json', encoding='utf-8').read()
city_data = json.loads(f)
print(city_data)# 输入出发和目的城市
# 输入时间
train_date = '2025-01-09'
from_city = '深圳'
to_city = '广州'
print(city_data[from_city])
print(city_data[to_city])headers = {'cookie':f'_uab_collina=173526990403562156621352; JSESSIONID=1B8F19FC6675BDA9782FEA7B06BDC256; route=9036359bb8a8a461c164a04f8f50b252; BIGipServerotn=1725497610.24610.0000; BIGipServerpassport=1005060362.50215.0000; guidesStatus=off; highContrastMode=defaltMode; cursorStatus=off; _jc_save_fromStation=%u6DF1%u5733%2CSZQ; _jc_save_toStation=%u4FE1%u4E30%2CEFG; _jc_save_fromDate={train_date}; _jc_save_wfdc_flag=dc; _jc_save_toDate=2024-12-28','user-agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36',}# 请求网址
# https://kyfw.12306.cn/otn/leftTicket/queryG?leftTicketDTO.train_date=2025-01-06&leftTicketDTO.from_station=SZQ&leftTicketDTO.to_station=EFG&purpose_codes=ADULT
url = f'https://kyfw.12306.cn/otn/leftTicket/queryG?leftTicketDTO.train_date={train_date}&leftTicketDTO.from_station={city_data[from_city]}&leftTicketDTO.to_station={city_data[to_city]}&purpose_codes=ADULT'# 发送请求 使用request
response = requests.get(url=url, headers=headers)
print(url)
print(response.status_code)
print(response.text)
# 获取数据
json_data = response.json()# 解析数据--字典取值:
result = json_data['data']['result']def print_ticketlist():# 实例化对象tb = PrettyTable()tb.field_names = ['序号','车次','出发时间','到达时间','耗时','特等座','一等座','二等座','软卧','硬卧','硬座','无座',]# 定义一个打印序号pagepage = 1# for循环遍历,提取列表里面的元素for i in result:# 字符串分割,返回列表index = i.split('|')# 通过列表索引位置取值num = index[3] # 车次star_time = index[8] # 出发时间arrive_time = index[9] # 到达时间use_time = index[10] # 耗时special_class = index[32]  # 特等座frist_class = index[31]  # 一等座second_class = index[30] # 二等座hard_sleeper = index[28] # 硬卧hard_seat = index[29] # 硬座no_seat = index[26] # 无座soft_sleeper  = index[23]# 软卧dict = {'序号':'page','车次':'num','出发时间':'star_time','到达时间':'arrive_time','耗时':'use_time','特等座':'special_class','一等座':'frist_class','二等座':'second_class','软卧':'soft_sleeper','硬卧':'hard_sleeper','硬座':'hard_seat','无座': 'no_seat'}tb.add_row([page, #序号索引num, # 车次star_time,# 出发时间arrive_time,# 到达时间use_time, # 耗时special_class, # 特等座frist_class,  # 一等座second_class,# 二等座soft_sleeper,  # 软卧hard_sleeper,# 硬卧hard_seat, # 硬座no_seat,# 无座])page += 1print(tb)# def change_chinese(chinese):
#     """把中文自动转换为拼音"""
#     text = pinyin(chinese, style=Style.NORMAL)
#     string = ''.join(t[0] for t in text)
#     return stringdef selenium_login():# 0.配置谷歌浏览器加载项options = webdriver.ChromeOptions()options.add_argument(f'--user-data-dir={user_data_dir}') # 添加浏览器数剧# 1.将加载项配置到启动浏览器中 打开/创建浏览器对象driver = webdriver.Chrome(executable_path=r'D:\game\chromedriver.exe', options=options)# 2.输入网址driver.get('https://kyfw.12306.cn/otn/view/index.html')# 3.输入账号 -- > 找到账号的输入框 selenium 通过元素面板去定位元素driver.find_element(by="css selector", value="#J-userName").send_keys(login['account'])# 4.输入密码 -- > 找到密码的输入框driver.find_element(by="css selector", value="#J-password").send_keys(login['password'])# 5.点击登录按钮driver.find_element(by="css selector", value="#J-login").click()time.sleep(0.5)# 6.输入身份证后4位driver.find_element(by="css selector", value="#id_card").send_keys(login['id_card'])# 7.点击获取验证码driver.find_element(by="css selector", value="#verification_code").click()# 8.输入验证码code = input("请输入验证码:")driver.find_element(by="css selector", value="#code").send_keys(code)driver.find_element(by="css selector", value="#verification_code").click()# 9.点击确认按钮driver.find_element(by="css selector", value="#sureClick").click()# 有时候报错是需要延时等待 用 driver.implicitly_wait(10)代码 可以实现加载完就就进行下一步,# 而time.sleep(5)则必须等我规定的时间driver.implicitly_wait(5)# 10,点击车票预定按钮driver.find_element(by="css selector", value="#link_for_ticket").click()# 11.1 选择出发的城市--点击那个框driver.find_element(by="css selector", value="#fromStationText").click()# 11.2 选择出发的城市--选择城市driver.find_element(by="css selector", value="#fromStationText").send_keys(from_city)# 11.3 选择出发的城市--回车确定driver.find_element(by="css selector", value="#fromStationText").send_keys(Keys.ENTER)# 12.1 选择目的的城市--点击那个框driver.find_element(by="css selector", value="#toStationText").click()# 12.2 选择目的的城市--选择城市driver.find_element(by="css selector", value="#toStationText").send_keys(to_city)# 12.3 选择目的的城市--回车确定driver.find_element(by="css selector", value="#toStationText").send_keys(Keys.ENTER)# 13.1 选择出发的日期--点击那个框driver.find_element(by="css selector", value="#train_date").clear()# 12.2 选择出发的日期--选择城市driver.find_element(by="css selector", value="#train_date").send_keys(train_date)# 12.3 选择出发的日期--回车确定driver.find_element(by="css selector", value="#train_date").send_keys(Keys.ENTER)# # 12.4 点击--显示全部可预订的车次# driver.find_element(by="css selector", value="avail_ticket").click()# 12.5 点击查询driver.implicitly_wait(5)driver.find_element(by="css selector", value="#query_ticket").click()num = int(input('请输入您想要的车次:'))# 点击预订按钮 -- 选择要预定的是第几躺车 -- 这个代码没有问题# driver.find_element(by="css selector", value='#ticket_65000G279007_01_03 > td.no-br').click()# //div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]/@id -- 但是selenium的find_elements不可以用@id找到元素。ticket_list = driver.find_elements(by="xpath", value='//div//tbody[@id="queryLeftTable"]/tr[contains(@id,"ticket")]')ticket_num = ticket_list[num].get_attribute("id")ticket_pre = ticket_num + ' > td.no-br'# 12.6 点击想要车次的预定按钮driver.find_element(by="css selector", value=f"#{ticket_pre}").click()# 13.1 勾选想要的乘车人driver.find_element(by="css selector", value='#normalPassenger_0').click()# 13.2 提交订单driver.find_element(by="css selector", value='#submitOrder_id').click()driver.implicitly_wait(5)# 13.3 选择靠窗的1F的位置# driver.find_element(by="css selector", value='#1F').click() --这种行不通,只能下方这种driver.find_element(by="css selector", value='#erdeng1 > ul:nth-child(4) > li:nth-child(2)').click()# 13.4 再次确认提交time.sleep(2)driver.find_element(by="css selector", value='#qr_submit_id').click()# driver.find_element(by="css selector", value='#qr_submit_id').click()# # 14.  网上支付 -- payButton# driver.find_element(by="css selector", value='#payButton').click()# # 15.  取消订单 -- cancelButton# driver.find_element(by="css selector", value='#cancelButton').click()f = open('login.json', encoding='utf-8').read()
login = json.loads(f)if __name__ == "__main__":print_ticketlist()selenium_login()

三、进阶–展望

1.首先可以将自动化操作用try–except,这样不会一直报错,更为规范。

2.免登录:因为登录其实要验证码,这样抢票也不方便。于是我就又继续学习了一些,发现了两种方法一是可以保存浏览器的数据,因为selenium每次打开的是一个新的程序,但是我们可以通过设置参数,让他打开是有记忆的,但是没有用。第二种,是cookie,是没有什么问题的,目前已经实现,接下尝试各种方法的cookie看行不行。后续我会发此程序。

3.多线程多进程:主要我已经实现cookie免登录,我想着是否可以打开多个页面,然后多个账号,一起抢他们所需要的票呢。

总结

1.最开始跟着写这个程序只会照着抄,然后根本不懂,后面就是差了一点点成功,也不会找错误。

2.后面学习了一下爬虫,更明白一点语法以及自己也更会如何定位元素了。还有就是request的一个请求,这些代码也更看得懂了

3.想着结合多线程然后实现批量抢票,同时也希望代价的容错率高,也就是说在自动化不用点几下程序就不行了,让它可以有更好的性能。-- 未来学习的一个点。加油!!!

相关文章:

python实现自动登录12306抢票 -- selenium

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 python实现自动登录12306抢票 -- selenium 前言其实网上也出现了很多12306的代码,但是都不是最新的,我也是从网上找别人的帖子,看B站视频&…...

使用Diffusion Models进行图像超分辩重建

Diffusion Models专栏文章汇总:入门与实战 前言:图像超分辨率重建是一个经典CV任务,其实LR(低分辨率)和 HR(高分辨率)图像仅在高频细节上存在差异。通过添加适当的噪声,LR 图像将变得与其 HR 对应图像无法区分。这篇博客介绍一种方式巧妙利用这个规律使用Diffusion Mod…...

吾杯网络安全技能大赛——Misc方向WP

吾杯网络安全技能大赛——Misc方向WP Sign 题目介绍: 浅浅签个到吧 解题过程: 57754375707B64663335376434372D333163622D343261382D616130632D3634333036333464646634617D 直接使用赛博橱子秒了 flag为 WuCup{df357d47-31cb-42a8-aa0c-6430634ddf4a} 原神启动…...

Web安全 - “Referrer Policy“ Security 头值不安全

文章目录 概述原因分析风险说明Referrer-Policy 头配置选项1. 不安全的策略no-referrer-when-downgradeunsafe-url 2. 安全的策略no-referreroriginorigin-when-cross-originsame-originstrict-originstrict-origin-when-cross-origin 推荐配置Nginx 配置示例 在 Nginx 中配置 …...

C#OPC(上)

OPC(OLE for Process Control),用于过程控制的OLE,是一个工业标准,管理这个标准的国际组织是OPC基金会,OPC基金会现有会员以超过220家。遍布全球,包括世界上所有主要的自动化控制系统、仪器仪表及过程控制系统的公司。基于微软的O…...

Imgui + Cmake + OpenGL + GLFW 隐藏控制台窗口

网上一般是VS&#xff0c;如何在属性里面把控制台改为窗口 本文&#xff0c;使用Clion Cmake&#xff0c;实现如何隐藏控制台窗口 环境&#xff1a;OpenGL3 GLFW 添加头文件#include <windows.h>把main函数入口改为int WinMain(HINSTANCE hInstance, HINSTANCE hPrevI…...

Spring Boot(七):Swagger 接口文档

1. Swagger 简介 1.1 Swagger 是什么&#xff1f; Swagger 是一款 RESTful 风格的接口文档在线自动生成 功能测试功能软件。Swagger 是一个规范和完整的框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。目标是使客户端和文件系统作为服务器以同样的…...

RabbitMQ - 4 ( 22000 字 RabbitMQ 入门级教程 )

一&#xff1a; RabbitMQ 高级特性 前面主要讲解了 RabbitMQ 的概念和应用。RabbitMQ 实现了 AMQP 0-9-1 规范&#xff0c;并在此基础上进行了多项扩展。在 RabbitMQ 官方网站中详细介绍了其特性&#xff0c;我们将其中一些重要且常用的特性挑选出来进行讲解。 1.1 消息确认 …...

印象笔记07——试一试PDF标注

印象笔记07——试一试PDF标注 [!CAUTION] 根据第六期&#xff0c;我再次查询了资料&#xff0c;印象笔记还是有一些可圈可点的功能的&#xff08;当然部分有平替&#xff09;&#xff0c;针对会员作用&#xff0c;开发使用场景虽然是逆向的&#xff0c;但我坚信这是一部分人的现…...

Vue3实战教程》24:Vue3自定义指令

如果您有疑问&#xff0c;请观看视频教程《Vue3实战教程》 自定义指令​ 介绍​ 除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外&#xff0c;Vue 还允许你注册自定义的指令 (Custom Directives)。 我们已经介绍了两种在 Vue 中重用代码的方式&#xff1a;组件和组…...

【2025优质学术推荐】征稿控制科学、仪器、智能系统、通信、计算机、电子信息、人工智能、大数据、机器学习、软件工程、网络安全方向

【2025优质学术推荐】征稿控制科学、仪器、智能系统、通信、计算机、电子信息、人工智能、大数据、机器学习、软件工程、网络安全方向 【2025优质学术推荐】征稿控制科学、仪器、智能系统、通信、计算机、电子信息、人工智能、大数据、机器学习、软件工程、网络安全方向 文章目…...

【ArcGIS Pro/GeoScene Pro】可视化时态数据

可视化过去二十年新西兰国际旅游业的发展变化 工程数据下载 ArcGIS Pro 快速入门指南—ArcGIS Pro | 文档 添加数据 数据为中国旅客数据 转置表字段 列数据转行数据...

Linux buildroot和ubuntu的异同点

Buildroot 和 Ubuntu 都是 Linux 系统的操作环境,但它们的设计理念和使用场景有很大的不同。 一、定义与目标 Buildroot Buildroot 是一个用于生成嵌入式 Linux 系统的工具集,专注于交叉编译和构建嵌入式设备的最小 Linux 环境。它的目标是为嵌入式系统提供定制化和优化的…...

k8s系列--通过docker拉取的镜像导入到 containerd中

要将通过 docker pull 拉取的镜像导入到 containerd 中&#xff0c;可以按照以下步骤操作&#xff1a; 步骤 1&#xff1a;使用 docker 将镜像保存为 tar 文件 docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.11.1 docker save registry.cn-ha…...

Spring Boot(快速上手)

Spring Boot 零、环境配置 1. 创建项目 2. 热部署 添加依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional> </dependency&…...

note 41:账务系统开发规范

目录 系统设计 防重控制 流量控制 并发控制 异常处理 备份机制 系统开发​​​​​​​ 前端队列操作 外系统交互 ​​​​​​​​​​​​​​ 系统设计 防重控制 对于进入到系统中的数据&#xff08;文件导入、手工录入、系统直连等&#xff09;以及本系统发往外…...

基于嵌入式无人机UAV通信系统的实时最优资源分配算法matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于嵌入式无人机UAV通信系统的实时最优资源分配算法matlab仿真。具体参考文献&#xff1a; 考虑使用UAV作为中继辅助节点的设备到设备&#xff08;D2D&#xff09;无线信息和…...

《Vue3实战教程》35:Vue3测试

如果您有疑问&#xff0c;请观看视频教程《Vue3实战教程》 测试​ 为什么需要测试​ 自动化测试能够预防无意引入的 bug&#xff0c;并鼓励开发者将应用分解为可测试、可维护的函数、模块、类和组件。这能够帮助你和你的团队更快速、自信地构建复杂的 Vue 应用。与任何应用一…...

【Java设计模式-3】门面模式——简化复杂系统的魔法

在软件开发的世界里&#xff0c;我们常常会遇到复杂的系统&#xff0c;这些系统由多个子系统或模块组成&#xff0c;各个部分之间的交互错综复杂。如果直接让外部系统与这些复杂的子系统进行交互&#xff0c;不仅会让外部系统的代码变得复杂难懂&#xff0c;还会增加系统之间的…...

log4j2的Strategy、log4j2的DefaultRolloverStrategy、删除过期文件

文章目录 一、DefaultRolloverStrategy1.1、DefaultRolloverStrategy节点1.1.1、filePattern属性1.1.2、DefaultRolloverStrategy删除原理 1.2、Delete节点1.2.1、maxDepth属性 二、知识扩展2.1、DefaultRolloverStrategy与Delete会冲突吗&#xff1f;2.1.1、场景一&#xff1a…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...