【Python脚本】轻松实现12306自动抢票脚本,100%成功,假期出行无忧!

news2025/2/24 10:02:35

文章目录

  • 前言
    • 1.导入需要的模块
    • 2.初始化WebDriver:
    • 3.打开12306网站:
    • 4.登录12306账号:
    • 5.进入车票查询页面:
    • 6.查询车票:
    • 7.选择车次和座位:
    • 8.填写乘客信息和提交订单:
    • 9.处理验证码:
    • 10.确认订单和支付:


前言

`
不知道大家有没有之前碰到这样的情况,打算去某一个地方当你规划好了时间准备去买票的时候,你想要的那一列往往没有你想要的票了,尤其是国庆七天假和春节半月假,有时候甚至买不到规定计划时间内的票,真的是太烦躁了

为此我钻研了一下,现在科技如此发达,想要实现自动化还是比较简单的
在这里插入图片描述

Python配套案例源码、资料点击领取福利

在这里插入图片描述

1.导入需要的模块

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

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

2.初始化WebDriver:

driver = webdriver.Chrome()  # 选择合适的浏览器驱动,这里以Chrome为例

3.打开12306网站:

driver.get('https://www.12306.cn')

4.登录12306账号:

首先手动登录一次,然后在浏览器中的开发者工具中找到登录请求的相关信息,提取出关键参数(比如cookies、token等),可以使用工具库来自动提取这些参数。

使用Python的requests库等发送该登录请求,将提取到的关键参数作为请求的header或body发送过去,模拟登录。

5.进入车票查询页面:

# 这里可能需要等待一段时间,直到页面加载完成
# 可以使用WebDriverWait等待特定的元素加载完成
wait = WebDriverWait(driver, 10)  # 设置等待时间为10秒
query_input = wait.until(EC.presence_of_element_located((By.ID, 'query_input')))
query_input.clear()
query_input.send_keys('出发地点')

6.查询车票:

search_btn = driver.find_element_by_id('search_btn')
search_btn.click()

# 这里可能需要等待一段时间,直到查询结果加载完成
# 同样可以使用WebDriverWait等待特定的元素加载完成

7.选择车次和座位:

train_btn = driver.find_element_by_id('train_btn')
train_btn.click()

# 这里可能需要等待一段时间,直到车次详情加载完成

seat_type = driver.find_element_by_id('seat_type')
seat_type.send_keys('座位类型')

buy_btn = driver.find_element_by_id('buy_btn')
buy_btn.click()

上述代码将选择指定的座位类型,你需要根据自己的需求修改。

8.填写乘客信息和提交订单:

passenger_name = driver.find_element_by_id('passenger_name')
passenger_name.send_keys('乘客姓名')

id_number = driver.find_element_by_id('id_number')
id_number.send_keys('乘客身份证号码')

# 填写其他乘客信息,如果有多个乘客

submit_btn = driver.find_element_by_id('submit_btn')
submit_btn.click()

上述代码将填写乘客的姓名、身份证号码等信息,你需要根据自己的需求修改。

9.处理验证码:

12306网站可能会出现验证码,你需要使用图像处理库(如PIL)来处理验证码图片并自动识别验证码。

如果遇到验证码,你可以通过人工干预或使用一些自动化技术(如OCR)处理,以便自动填写验证码。

10.确认订单和支付:

confirm_btn = driver.find_element_by_id('confirm_btn')
confirm_btn.click()

# 这里可能需要等待一段时间,直到支付页面加载完成

# 在该页面处理支付,根据你使用的支付方式进行自动化支付

以上只是一个基本的框架,实际实现可能需要根据12306网站的更新和变化进行相应的调整

那么根据具体时间2023年8月10号为例子,我们来具体操作一下,以下是具体源码:

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from config import Config
from selenium.webdriver.common.keys import Keys
import time
import select
 
# 用抛出异常来判断一个元素存不存在太慢了,需要等5秒钟
# def isElementExist(ele):
#     flag = True
#     result = EC.presence_of_element_located((By.XPATH, '//tbody[@id="queryLeftTable"]/tr[1]/td[13]/a'))
#     try:
#         # ele.find_element(by=By.CLASS_NAME, value='btn72')
#         result(ele)
#         return flag
#     except:
#         flag = False
#         return flag
 
 
def isElementExist(driver):
    flag=True
    ele = driver.find_elements(by=By.CLASS_NAME, value='btn72')
    if len(ele) == 0:
        flag = False
        return flag
    if len(ele) == 1:
        return flag
    else:
        flag = False
        return flag
 
 
def get_ticket(conf, driver, url):
    # 过网站检测,没加这句的话,账号密码登录时滑动验证码过不了,但二维码登录不受影响
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {"source": """Object.defineProperty(navigator, 'webdriver', {
          get: () => undefined})"""})
    driver.maximize_window()
    driver.get(url)
    # 最多等待5秒使页面加载进来,隐式等待
    driver.implicitly_wait(5)
 
    # 获取并点击右上角登录按钮
    login = driver.find_element(by=By.ID, value='J-btn-login')
    login.click()
    driver.implicitly_wait(10)
 
    # 账号密码登录
    username_tag = driver.find_element(by=By.ID, value='J-userName')
    username_tag.send_keys(conf.username)
    password_tag = driver.find_element(by=By.ID, value='J-password')
    password_tag.send_keys(conf.password)
    login_now = driver.find_element(by=By.ID, value='J-login')
    login_now.click()
    time.sleep(20)
 
    # # 过滑动验证码
    # picture_start = driver.find_element(by=By.ID, value='nc_1_n1z')
    # # 移动到相应的位置,并左键鼠标按住往右边拖
    # ActionChains(driver).move_to_element(picture_start).click_and_hold(picture_start).move_by_offset(300, 0).release().perform()
    #
    #
    # # 扫码登录
    # scan_QR = driver.find_element(by=By.XPATH, value='//*[@id="toolbar_Div"]/div[2]/div[2]/ul/li[2]/a')
    # scan_QR.click()
    # driver.implicitly_wait(10)
 
 
    # 点提示框
    # driver.find_element(by=By.XPATH, value='//div[@class="dzp-confirm"]/div[2]/div[3]/a').click()
    # driver.implicitly_wait(5)
 
    # 点击车票预订跳转到预订车票页面
    driver.find_element(by=By.XPATH, value='//*[@id="link_for_ticket"]').click()
    driver.implicitly_wait(10)
 
    # 输入出发地和目的地信息
    # 出发地
    driver.find_element(by=By.XPATH, value='//*[@id="fromStationText"]').click()
    driver.find_element(by=By.XPATH, value='//*[@id="fromStationText"]').clear()
    driver.find_element(by=By.XPATH, value='//*[@id="fromStationText"]').send_keys(conf.fromstation)
    time.sleep(1)
    driver.find_element(by=By.XPATH, value='//*[@id="fromStationText"]').send_keys(Keys.ENTER)
 
    # 目的地
    destination_tag = driver.find_element(by=By.XPATH, value='//*[@id="toStationText"]')
    destination_tag.click()
    destination_tag.clear()
    destination_tag.send_keys(conf.destination)
    time.sleep(1)
    destination_tag.send_keys(Keys.ENTER)
    driver.implicitly_wait(5)
 
    # 出发日期
    date_tag = driver.find_element(by=By.XPATH, value='//*[@id="train_date"]')
    date_tag.click()
    date_tag.clear()
    date_tag.send_keys(conf.date)
    time.sleep(1)
    query_tag = driver.find_element(by=By.XPATH, value='//*[@id="query_ticket"]')
 
    start = time.time()
 
    while True:
        driver.implicitly_wait(5)
        # 点击查询
        driver.execute_script("$(arguments[0]).click()", query_tag)
 
        # 判断页面中有没有“预订”按钮,如果没有预订按钮就不断查询直到车票开售
        if not isElementExist(driver):
            # 车票处于待开售状态
            print(f"15点30分起售,现在是{time.strftime('%H:%M:%S', time.localtime())},还未开始售票")
            # 每隔两分钟刷新一次,否则3分钟内无购票操作12306系统会自动登出
            if time.time() - start >= 120:
                driver.refresh()
                start = time.time()
            # 延时1秒防止过于快速地点击导致查询超时,当然偶尔还是会出现超时现象,不过超时也没关系,一般等待6秒之后就会继续自动查询
            time.sleep(1)
            continue
 
        # 获取所有车票
        tickets = driver.find_elements(by=By.XPATH, value='//*[@id="queryLeftTable"]/tr')
        # 每张车票有两个tr,但是第二个tr没什么用
        tickets = [tickets[i] for i in range(len(tickets) - 1) if i % 2 == 0]
        #print(tickets)
        for ticket in tickets:
            # 如果车票的车次等于想要的车次并且硬卧的状态不是候补则点击预订
            #if ticket.find_element(by=By.CLASS_NAME,value='cdz').text== conf.fromstation:
                #print(ticket.find_element(by=By.CLASS_NAME,value='number').text)
                # value = '//td[8]'表示硬卧,td[10]表示硬座
            if ticket.find_element(by=By.CLASS_NAME,value='number').text == conf.trainnumber and ticket.find_element(by=By.XPATH, value='//td[8]').text != "候补":
                # 点击预订
                #print(ticket.find_element(by=By.CLASS_NAME,value='cdz').text)
                #time.sleep(1)
                ticket.find_element(by=By.CLASS_NAME, value='btn72').click()
                # 这里之后就不能继续使用ticket.find_element()了,因为页面进行了跳转,会出现stale element reference: element is not attached to the page document的错误
                # 我们可以使用driver.find_element()
                # 选择乘车人,如果是学生,则需要确认购买学生票
                driver.find_element(by=By.XPATH, value='//*[@id="normalPassenger_0"]').click()
                # 点击确认购买学生票,如果不是学生,把这行注释了就行
                #driver.find_element(by=By.XPATH, value='//*[@id="dialog_xsertcj_ok"]').click()
                # 第二个乘车人
                # driver.find_element(by=By.XPATH, value='//*[@id="normalPassenger_1"]').click()
                # 如果第二个乘车人也是学生,则需要点击确认第二个人也购买学生票
                # driver.find_element(by=By.XPATH, value='//*[@id="dialog_xsertcj_ok"]').click()
                # 提交订单
                driver.find_element(by=By.XPATH, value='//*[@id="submitOrder_id"]').click()
                # 选座  F座
                #time.sleep(1)
                #move = driver.find_element(By.ID, value='1F')
                #ActionChains(driver).move_to_element(move).perform()
                # time.sleep(1)
                #这里直接使用id和xpath定位不到,所以直接加上他的路径,可以不用这么长,但是懒得删
                driver.find_element(by=By.XPATH, value='//html/body/div[5]/div/div[5]/div[1]/div/div[2]/div[2]/div[3]/div[2]/div[2]/ul[2]/li[2]/a[@id="1F"]').click()
                # 确认提交订单,然后这里和上面是一样的
                driver.find_element(by=By.XPATH, value='//html/body/div[5]/div/div[5]/div[1]/div/div[2]/div[2]/div[8]/a[2][@id="qr_submit_id"]').click()
                print(f"{conf.trainnumber}次列车抢票成功,请尽快在10分钟内支付!")
                return
 
 
if __name__ == '__main__':
    # 有关车票的配置信息保存在该类里
    # 请事先在config.py里填好相关信息
    conf = Config()
 
    url = 'https://www.12306.cn/index/'
 
    # chromedriver.exe版本为104,可以根据自己浏览器版本重新下载chromedriver.exe替换
    # chromedriver.exe下载地址:http://chromedriver.storage.googleapis.com/index.html
    # s = Service(r'chromedriver.exe')
    driver = webdriver.Chrome()
    get_ticket(conf, driver, url)
    time.sleep(10)
    driver.quit()
↓ ↓ ↓ 加下方名片找我,直接拿源码还有案例 ↓ ↓ ↓

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/926972.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

powerJob的正确部署方式(server部署,其他worker统统指定这个server)

PowerJob 的设计目标为企业级的分布式任务调度平台,即成为公司内部的任务调度中间件。整个公司统一部署调度中心 powerjob-server,旗下所有业务线应用只需要依赖 powerjob-worker 即可接入调度中心获取任务调度与分布式计算能力。 实现PowerJob的设计目标…

nginx 中新增url请求参数

1、nginx中新增配置: set $args "$args&参数名参数值"; 示例: set $args "$args&demo1cn_yaojin&demo2123123&myip$remote_addr"; location / {add_header Access-Control-Allow-Origin *;add_header Access-Contro…

小红书达人种草指南,投放总结!

提到针对小红书的品牌和产品传播,人们总会提起一个词语,那就是达人种草。今天就来为大家分享一下小红书达人种草指南,投放总结! 一、什么是达人种草 小红书达人种草是一种以达人为核心的产品传播方式。借助达人在粉丝中的影响力&a…

解析直播美颜SDK功能算法:肤色识别、特征增强与实时渲染

在这个数字化时代,美颜技术在直播中的应用愈发受到重视,为主播和观众创造更加美好的视觉体验。本文将深入探讨直播美颜SDK 的核心功能算法,包括肤色识别、特征增强与实时渲染,揭示其背后的技术原理与工作机制。 一、肤色识别算法…

无脑007--Yolov7推理测试

此次项目是为了下一个项目做准备,打算学习一下docker和迁移学习的技术。 1.下载代码和模型 首先从github下载yolov7的官方代码: https://github.com/WongKinYiu/yolov7 直接点击绿色的code,然后点Download zip进行下载 我们把下载好的文件统…

水库大坝安全监测的主要内容包括哪些?

在水库大坝的实时监测中,主要任务是通过无线传感网络监测各个监测点的水位、水压、渗流、流量、扬压力等数据,并在计算机上用数据模式或图形模式进行实时反映,以掌握整个水库大坝的各项变化情况。大坝安全监测系统能实现全天候远程自动监测&a…

EVE-NG MPLS L3VPN 基本组网

1 拓扑 2 配置步骤 2.1 在MPLS节点上配置接口IP 和路由协议 PE1 interface LoopBack 0ip address 1.1.1.9 32 quitinterface GigabitEthernet4/0ip address 172.1.1.1 24quitospf 1area 1network 1.1.1.9 0.0.0.0network 172.1.1.0 0.0.0.255quitquit P interface LoopBac…

数字世界的入口:二维码生成器 API 的实用指南

前言 当今数字化世界中,二维码已经成为了无处不在的存在。无论是商业领域、社交媒体,还是个人生活中,我们都可以看到二维码的身影。它们不仅是一种信息传递的便捷方式,还可以用于营销、身份验证、跟踪和更多用途。本文将介绍二维…

uview2.0实现picker省市区选择以及默认选择

vue文件 <template><view class"invite"><u-cell title"点击选则" isLink :value"value" click"change()"></u-cell><u-picker :show"show" ref"uPicker" :columns"columns&quo…

路面病害识别新方法,省时省力又高效!

在日常生活中&#xff0c;我们经常会遇到路面出现各种各样的病害&#xff0c;比如坑洼、龟裂等。这些路面病害不仅给行车带来不便&#xff0c;还会对交通安全造成一定的影响。因此&#xff0c;及时准确地识别路面病害显得尤为重要。 路面病害可以分为多种不同的类型&#xff0…

Slippage-robust Gaze Tracking for Near-eye Display

论文&#xff1a;Slippage-robust Gaze Tracking for Near-eye Display 中文&#xff1a;基于滑动鲁棒的近眼显示器凝视跟踪 地址&#xff1a;2210.11637v1.pdf (arxiv.org)https://arxiv.org/pdf/2210.11637v1.pdf 目录 摘要 1 介绍 2 相关工作 3 系统概述 A 硬件设置 …

用svn上传idea和webstorm代码(有图详解)

本文从以下几个方面讲svn上传及注意事项&#xff1a; 1. 前端项目上传svn 2. 后端项目上传svn 3. 删除之前的svn信息&#xff08;删除svn的小对勾&#xff09; 4. 设置idea中svn的忽略提交文件 5. 设置webstorm的忽略提交文件 svn如何安装&#xff0c;请参考这篇文章&#xf…

Redis常用数据类型及命令

Redis 常用数据类型 常用数据类型 主要是指value类型 key都是字符串类型的 各种数据类型对应的特点 应用场景 哈希&#xff1a;一般来存储一些对象 列表&#xff1a;存一些跟顺序有关系的数据&#xff0c;比如朋友圈点赞 集合&#xff1a;一般用来做运算&#xff0c;交集&a…

揭秘DISC模型:团队协作的神秘力量

DISC模型简介 DISC的起源与发展 DISC模型最初是由美国心理学家William Moulton Marston在20世纪初提出的。他在1928年的著作《情感的正常与异常》中首次描述了这一模型。这一理论的核心思想是&#xff0c;人们的行为可以被归类为四个主要的类型&#xff0c;这四种类型是相互关…

【夏令时】用@JsonFormat(pattern = “yyyy-MM-dd“)注解,出生日期竟然年轻了一天

前言 &#x1f34a;缘由 用JsonFormat(pattern “yyyy-MM-dd”&#xff09;注解&#xff0c;出生日期竟然年轻了一天 艺术源于生活&#xff0c;bug源于开发。 起因是艰苦奋战一个月&#xff0c;测试及验收都顺利通过&#xff0c;上线也稳稳的成功。但是毒奶总是在不经意给你…

基于Jenkins构建生产CICD环境(第三篇)

目录 基于Jenkins自动打包并部署docker环境 1、安装docker-ce 2、阿里云镜像加速器 3、构建tomcat 基础镜像 4、构建一个Maven项目 基于Jenkins自动化部署PHP环境 基于rsync部署 基于Jenkins自动打包并部署docker环境 1、安装docker-ce 在192.168.2.123 机器上&#x…

QT初始学习中的个人基础认知

整体感觉 安装的时候感觉更像python的库安装和编译器版本的配合安装。进入创建工程时&#xff0c;感觉是c语言的创建工程的感觉&#xff0c;而且可以看到main和h的头文件&#xff0c;整体来看是C来编写的程序。完成整个工程个人感觉是C编写功能&#xff0c;使用VB实现界面设计…

没有办公室,种子轮却融了4个亿的开源机器学习框架AI表——MindsDB

近日,一条融资消息引起了我的关注,一家将机器学习(ML)引入数据库的开源机器学习(ML)初创公司,成功获得英伟达旗下NVentures的投资。至此,这家被英伟达、Benchmark,以及Mayfield等众多机构投资的种子轮,总额达到5410万美元(近4亿元)。 这家公司叫MindsDB,成立于2017年,…

C 语言编程规范 -- 华为

1. 代码总体原则 1.1 清晰第一&#xff0c;清晰性是易于维护&#xff0c;易于重构的程序必须具备的特征 代码首先是给人读的&#xff0c;好的代码应当可以像文章一样发生朗诵出来&#xff0c;“程序必须为阅读它的人而编写&#xff0c;只是顺便用于机器执行” – Harold Abel…

js深拷贝三种方法

使用递归函数实现深拷贝 const obj {name: zzz,age: 18,hobby: [篮球, 足球],family: {baby: baby}} // 深拷贝 数组 对象 一定要先筛数组再筛对象,因为万物皆对象function deepcopy(newObj, oldObj) {for (const k in oldObj) {// 判断值是否属于array类if (oldObj[k] i…