28. 实战:基于selenium实现12306自动购票

这篇具有很好参考价值的文章主要介绍了28. 实战:基于selenium实现12306自动购票。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

目的

思路

代码实现

1. 进入登录界面,输入账号密码

2. 点击登录按钮,完成滑块验证

3. 在个人中心点击购票,跳转

4. 输入出发地、目的地,从控制台输入得到

5. 文本框输入出发日

6. 若是学生票则切换票型

7. 点击查询

8. 定位预定按钮,点击跳转购票页面

9. 选择学生乘客,并在弹窗中确认购买学生票

10. 提交订单,等待付款

完整代码

运行效果

总结


前言

我们已经学会了selenium的基本操作,并且学会了用它处理验证码、跳转网页、处理内联框架等操作,现在可以进行实战:本节选取12306火车购票作为案例,用自动化测试工具selenium实现自动访问网页并下单等待购票。

2023-01-20更新:完善了全部功能并可以完整运行


目的

手动在控制台输入乘车人(新增), 出发地、目的地、出发日、是否购买学生票,确认后自动跳转12306网站购票。


思路

1. 首先获取登陆页面的URL,随后定位账号密码的输入框,用sendkey接口输入个人信息;

2. 获取登录控件的XPATH地址,点击发现弹窗出现滑块验证,使用drag_and_drop_by_offset接口实现拖拽滑块到终点的操作;

3. 登陆以后默认在个人中心,获取购票按钮XPATH地址,点击访问;

4. 分析购票界面,点击文本框以后可以清空当前文本框,所以动作链应当为:点击 -> 输入 -> 按下回车。因为输入以后会弹出选项,所以我们还得点一下回车,直接切换其他文本框会清空;

5. 出发日文本框点击的时候不会清空,所以用clear接口清空文本框,然后输入正确的日期格式yyyy-mm-dd形式;

6. 如果是学生票,切换学生票;

7. 点击查询,拿到可预定车票列表;

8. 用显示等待定位预定按钮,点击跳转购票页面;

9. 用条件等待选择学生乘客,并在弹窗中确认购买学生票 ; 或直接选择一般乘客购票;

10. 提交订单,等待付款。


代码实现

1. 进入登录界面,输入账号密码

opt = Options()
# option.add_experimental_option('excludeSwitches', ['enable-automation'])
opt.add_argument('--disable-blink-features=AutomationControlled')
opt.add_experimental_option('detach', True)
opt.add_argument('--start-maximized')  # 浏览器窗口最大

web = Chrome(options=opt)

web.get("https://kyfw.12306.cn/otn/resources/login.html")

web.find_element(By.XPATH, '//*[@id="toolbar_Div"]/div[2]/div[2]/ul/li[1]/a').click()

time.sleep(1)

# TODO 输入用户名和密码
web.find_element(By.XPATH, '//*[@id="J-userName"]').send_keys("username")
web.find_element(By.XPATH, '//*[@id="J-password"]').send_keys("password")

2. 点击登录按钮,完成滑块验证

# 点击登录
web.find_element(By.XPATH, '//*[@id="J-login"]').click()

time.sleep(3)

# 拖拽
btn = web.find_element(By.XPATH, '//*[@id="nc_1_n1z"]')
ActionChains(web).drag_and_drop_by_offset(btn, 300, 0).perform()
time.sleep(3)

ActionChains里面有许多动作序列,可以帮助我们完成许多仿人类动作,记得在最后加perform,不然动作序列是不会执行的。

3. 在个人中心点击购票,跳转

# 车票预定
web.find_element(By.XPATH, '//*[@id="link_for_ticket"]').click()

4. 输入出发地、目的地,从控制台输入得到

从控制台获得信息:

更新 : 增加了乘车人,便于定位后续购票人

# 初始化购票信息
print("***欢迎使用自动购票系统***")
print("请依次输入购票信息...")
print("=" * 30)
fromStationText = input("请输入出发地(示例:介休东)...\n")
toStationText = input("请输入目的地(示例:成都东)...\n")
train_date = input("请输入出发日(示例:2023-01-19)...\n")
is_student = input("是否购买学生票?(y/n)\n")
print("=" * 30)
print("处理信息中...\n", "处理完毕,请检查您输入的信息...\n", fromStationText, toStationText, train_date)
confirm = input("是否确认上述信息?(y/n)\n")
if confirm == 'y':
    print("=" * 30)
    print("初始化完毕,开始运行系统...")
if confirm == 'n':
    print("=" * 30)
    print("请重新运行程序!")
    exit(1)

修改:可以精简sendkeys操作,将它们放入一行:将信息输入文本框:

# 输入信息(出发地、目的地、出发日)

# 出发地
web.find_element(By.XPATH, '//*[@id="fromStationText"]').click()
web.find_element(By.XPATH, '//*[@id="fromStationText"]').send_keys(fromStationText, Keys.ENTER)
time.sleep(1)

# 目的地
web.find_element(By.XPATH, '//*[@id="toStationText"]').click()
web.find_element(By.XPATH, '//*[@id="toStationText"]').send_keys(toStationText, Keys.ENTER)
time.sleep(1)

5. 文本框输入出发日

# 出发日
# date = web.find_element(By.XPATH, '//*[@id="train_date"]')
# ActionChains(web).drag_and_drop_by_offset(date, 175, 0).perform()
web.find_element(By.XPATH, '//*[@id="train_date"]').clear()
web.find_element(By.XPATH, '//*[@id="train_date"]').send_keys(train_date)
time.sleep(1)

6. 若是学生票则切换票型

# 点击查询
if is_student == 'y':
    web.find_element(By.XPATH, '//*[@id="sf2_label"]').click()
    time.sleep(1)

7. 点击查询

# 点击查询
web.find_element(By.XPATH, '//*[@id="query_ticket"]').click()
print("=" * 30)
print("查询完毕...")
time.sleep(1)

8. 定位预定按钮,点击跳转购票页面

定位思路有两种,一个是直接找到控件,另一个是相对查找,这里我选用第二种。由于第一种的控件地址隐藏较深,无法直接在源代码定位,藏在js里面,所以我们直接用标头的最后一项相对查找就行了。

# 点击预定
# TODO 待办:定位预订控件
get_ticket = web.find_element(By.XPATH, '//*[@id="float"]/th[16]')
ActionChains(web).move_to_element_with_offset(get_ticket, 55, 70).click().perform()

但是这样很难精准定位,不能适用所有网页,所以还是实践第一种方法:找到控件:

最终确认方法:显示等待

# 点击预定
WebDriverWait(web, 1000).until(EC.presence_of_element_located((By.XPATH, '//*[@id="queryLeftTable"]/tr')))
tr_list = web.find_elements(By.XPATH, '//*[@id="queryLeftTable"]/tr[not(@datatran)]')  # 每一列列车整行信息列表,列车号元素是tr的子元素
if not tr_list:
    print("=" * 30)
    print(f"很抱歉,按您的查询条件,当前未找到从{fromStationText}到{toStationText}的列车。")
    exit(1)
for tr in tr_list:
    train_num = tr.find_element(By.XPATH, './td[1]/div/div[1]/div/a').text  # 取出元素tr里的列车号
    # 动车二等座余票信息
    text_1 = tr.find_element(By.XPATH, "./td[4]").text
    # 火车二等座余票信息
    text_2 = tr.find_element(By.XPATH, "./td[8]").text
    if (text_1 == "有" or text_1.isdigit()) or (text_2 == "有" or text_2.isdigit()):
        # 点击预订按钮
        order_btn = tr.find_element(By.CLASS_NAME, "btn72")
        order_btn.click()
        # 等待订票页面
        WebDriverWait(web, 1000).until(EC.url_to_be('https://kyfw.12306.cn/otn/confirmPassenger/initDc'))
        print("=" * 30)
        print(train_num, "二等座有票!")
        break
    else:
        print("=" * 30)
        print(train_num, "二等座无票!")
        continue

9. 选择学生乘客,并在弹窗中确认购买学生票

修改:用expected condition(EC)选取处理弹窗事件。

# 跳转页面提交订单
# 选定乘车人
web.find_element(By.XPATH, f'//*[@id="normal_passenger_id"]/li/label[contains(text(),"{passenger}")]').click()
# 如果乘客是学生,对提示点击确定
if EC.presence_of_element_located((By.XPATH, '//div[@id="dialog_xsertcj"]')):
    web.find_element(By.ID, 'dialog_xsertcj_ok').click()
    # 提交订单
    web.find_element(By.ID, 'submitOrder_id').click()
    time.sleep(2)
else:
    # 提交订单
    web.find_element(By.ID, 'submitOrder_id').click()
    time.sleep(2)

10. 提交订单,等待付款

修改:更新了座位ID无法找到的问题,向上定位XPATH再往后确认

# 选座
print("=" * 30)
seat = input("请尽快进行选座操作([窗]A/B/C/[过道]/D/F[窗])\n")
if seat == 'A':
    web.find_element(By.XPATH, '//*[@id="erdeng1"]/ul[1]/li[1]/a').click()
if seat == 'B':
    web.find_element(By.XPATH, '//*[@id="erdeng1"]/ul[1]/li[2]/a').click()
if seat == 'C':
    web.find_element(By.XPATH, '//*[@id="erdeng1"]/ul[1]/li[3]/a').click()
if seat == 'D':
    web.find_element(By.XPATH, '//*[@id="erdeng1"]/ul[2]/li[1]/a').click()
if seat == 'F':
    web.find_element(By.XPATH, '//*[@id="erdeng1"]/ul[2]/li[2]/a').click()

# 最终确认
web.find_element(By.XPATH, '//*[@id="qr_submit_id"]').click()

print("=" * 30)
print("*"*40, "\n---***<|订单创建完成,请于10分钟内付款|>***---")
print("*"*40)

完整代码

from selenium.webdriver import Chrome
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.chrome.options import Options
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

import time

# 初始化购票信息
print("***欢迎使用自动购票系统***")
print("请依次输入购票信息...")
print("=" * 30)
passenger = input("请输入乘车人(示例:蔡徐坤)...\n")
fromStationText = input("请输入出发地(示例:介休东)...\n")
toStationText = input("请输入目的地(示例:成都东)...\n")
train_date = input("请输入出发日(示例:2023-01-19)...\n")
is_student = input("是否购买学生票?(y/n)\n")
print("=" * 30)
print("处理信息中...\n", "处理完毕,请检查您输入的信息...\n", fromStationText, toStationText, train_date)
confirm = input("是否确认上述信息?(y/n)\n")
if confirm == 'y':
    print("=" * 30)
    print("初始化完毕,开始运行系统...")
if confirm == 'n':
    print("=" * 30)
    print("请重新运行程序!")
    exit(1)

# 2.chrome的版本大于等于88
opt = Options()
# option.add_experimental_option('excludeSwitches', ['enable-automation'])
opt.add_argument('--disable-blink-features=AutomationControlled')
opt.add_experimental_option('detach', True)
opt.add_argument('--start-maximized')  # 浏览器窗口最大

web = Chrome(options=opt)

web.get("https://kyfw.12306.cn/otn/resources/login.html")

web.find_element(By.XPATH, '//*[@id="toolbar_Div"]/div[2]/div[2]/ul/li[1]/a').click()

time.sleep(1)

# TODO 输入用户名和密码
web.find_element(By.XPATH, '//*[@id="J-userName"]').send_keys("18306825490")
web.find_element(By.XPATH, '//*[@id="J-password"]').send_keys("lk020511")

# 点击登录
web.find_element(By.XPATH, '//*[@id="J-login"]').click()

time.sleep(3)

# 拖拽
btn = web.find_element(By.XPATH, '//*[@id="nc_1_n1z"]')
ActionChains(web).drag_and_drop_by_offset(btn, 300, 0).perform()
time.sleep(3)

# 车票预定
web.find_element(By.XPATH, '//*[@id="link_for_ticket"]').click()

# 输入信息(出发地、目的地、出发日)

# 出发地
web.find_element(By.XPATH, '//*[@id="fromStationText"]').click()
web.find_element(By.XPATH, '//*[@id="fromStationText"]').send_keys(fromStationText, Keys.ENTER)
time.sleep(1)

# 目的地
web.find_element(By.XPATH, '//*[@id="toStationText"]').click()
web.find_element(By.XPATH, '//*[@id="toStationText"]').send_keys(toStationText, Keys.ENTER)
time.sleep(1)

# 出发日
web.find_element(By.XPATH, '//*[@id="train_date"]').clear()
web.find_element(By.XPATH, '//*[@id="train_date"]').send_keys(train_date)
time.sleep(1)

# 点击查询
if is_student == 'y':
    web.find_element(By.XPATH, '//*[@id="sf2_label"]').click()
    time.sleep(1)
web.find_element(By.XPATH, '//*[@id="query_ticket"]').click()
print("=" * 30)
print("查询完毕...")
time.sleep(1)

# 点击预定
WebDriverWait(web, 1000).until(EC.presence_of_element_located((By.XPATH, '//*[@id="queryLeftTable"]/tr')))
tr_list = web.find_elements(By.XPATH, '//*[@id="queryLeftTable"]/tr[not(@datatran)]')  # 每一列列车整行信息列表,列车号元素是tr的子元素
if not tr_list:
    print("=" * 30)
    print(f"很抱歉,按您的查询条件,当前未找到从{fromStationText}到{toStationText}的列车。")
    exit(1)
for tr in tr_list:
    train_num = tr.find_element(By.XPATH, './td[1]/div/div[1]/div/a').text  # 取出元素tr里的列车号
    # 动车二等座余票信息
    text_1 = tr.find_element(By.XPATH, "./td[4]").text
    # 火车二等座余票信息
    text_2 = tr.find_element(By.XPATH, "./td[8]").text
    if (text_1 == "有" or text_1.isdigit()) or (text_2 == "有" or text_2.isdigit()):
        # 点击预订按钮
        order_btn = tr.find_element(By.CLASS_NAME, "btn72")
        order_btn.click()
        # 等待订票页面
        WebDriverWait(web, 1000).until(EC.url_to_be('https://kyfw.12306.cn/otn/confirmPassenger/initDc'))
        print("=" * 30)
        print(train_num, "二等座有票!")
        break
    else:
        print("=" * 30)
        print(train_num, "二等座无票!")
        continue


# 跳转页面提交订单
# 选定乘车人
web.find_element(By.XPATH, f'//*[@id="normal_passenger_id"]/li/label[contains(text(),"{passenger}")]').click()
# 如果乘客是学生,对提示点击确定
if EC.presence_of_element_located((By.XPATH, '//div[@id="dialog_xsertcj"]')):
    web.find_element(By.ID, 'dialog_xsertcj_ok').click()
    # 提交订单
    web.find_element(By.ID, 'submitOrder_id').click()
    time.sleep(2)
else:
    # 提交订单
    web.find_element(By.ID, 'submitOrder_id').click()
    time.sleep(2)

# 选座
print("=" * 30)
seat = input("请尽快进行选座操作([窗]A/B/C/[过道]/D/F[窗])\n")
if seat == 'A':
    web.find_element(By.XPATH, '//*[@id="erdeng1"]/ul[1]/li[1]/a').click()
if seat == 'B':
    web.find_element(By.XPATH, '//*[@id="erdeng1"]/ul[1]/li[2]/a').click()
if seat == 'C':
    web.find_element(By.XPATH, '//*[@id="erdeng1"]/ul[1]/li[3]/a').click()
if seat == 'D':
    web.find_element(By.XPATH, '//*[@id="erdeng1"]/ul[2]/li[1]/a').click()
if seat == 'F':
    web.find_element(By.XPATH, '//*[@id="erdeng1"]/ul[2]/li[2]/a').click()

# 最终确认
web.find_element(By.XPATH, '//*[@id="qr_submit_id"]').click()

print("=" * 30)
print("*"*40, "\n---***<|订单创建完成,请于10分钟内付款|>***---")
print("*"*40)

运行效果

selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python

selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python 

selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python 

 

selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python

selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python

 selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python

selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python

selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python

selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python

 selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python

selenium中如何登录铁路12306,Python爬虫入门、进阶与实战,selenium,测试工具,python


总结

本节是基于selenium的浏览器自动化操作的实例,较为综合,涉及的知识点也比较多,仅供小伙伴们参考学习,请勿用于其他用途!

不太明白的小伙伴可以移步我之前发布过的selenium基础和简单的验证码实战文章来源地址https://www.toymoban.com/news/detail-815690.html

到了这里,关于28. 实战:基于selenium实现12306自动购票的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python selenium 简单的实现大麦网自动购票过程

    大麦网是中国综合类现场娱乐票务营销平台,业务覆盖演唱会、 话剧、音乐剧、体育赛事等领域 今天,我们要用代码来实现他的购票过程 先来看看完成后的效果是怎么样的 开发环境 版 本:anaconda(python3.8.8) 编辑器:pycharm 代码实现步骤 实现免登陆 选座并且下单 初始化加

    2023年04月14日
    浏览(38)
  • python爬虫(三)12306自动抢票--- selenium

    一、 二 、 python爬虫入门篇 https://blog.csdn.net/weixin_64050468/article/details/130583771?spm=1001.2014.3001.5501 文章目录 前言 一、按照selenuim模块+配置+可能报错解释 二、selenium部分代码解读  三、开始操作 抢票代码 爬取数据代码 后面文章主打用爬虫整活了 边学边玩 win + r 打开cmd 然后输入

    2024年02月08日
    浏览(46)
  • python+selenium实现12306抢票

    1、要先下载相关的包,selenium、interval。最好使用国内清华源 2、还要下载对应浏览器的驱动: 2.1 安装chromedriver 谷歌浏览器驱动的网址为link 注意:谷歌浏览器的驱动版本要匹配谷歌浏览器的版本 随机点击一个版本: 点击notes.txt 2.2 安装FireFox驱动(我用的是这个) 火狐驱动

    2024年02月01日
    浏览(49)
  • Java项目实战笔记--基于SpringBoot3.0开发仿12306高并发售票系统--(二)项目实现-第二篇-前端模块搭建及单点登录的实现

    本文参考自 Springboot3+微服务实战12306高性能售票系统 - 慕课网 (imooc.com) 本文是仿12306项目实战第(二)章——项目实现 的第二篇,详细讲解使用Vue3 + Vue CLI 实现前端模块搭建的过程,同时其中也会涉及一些前后端交互的实现,因此也会开发一些后端接口;搭建好前端页面后,

    2024年03月26日
    浏览(58)
  • 【Python】selenium项目实战:从12306网站获取特定时间段二等座有票的车次

    工具: python+pycharm+selenium 12306网址: https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc 出发地: 南京 目的地: 上海 发车日期: 当天日期的第二天 发车时间: 06:00–12:00 目的: 打印所有二等座有座的车次 id=\\\"queryLeftTable\\\"标签下的第4个td标签下的符合class=yes的元素,xpath: //*[@id=\\\"

    2024年02月16日
    浏览(41)
  • Java项目实战--基于SpringBoot3.0开发仿12306高并发售票系统--(一)前置知识

    本文参考自 Springboot3+微服务实战12306高性能售票系统 - 慕课网 (imooc.com) 本章将介绍仿12306售票系统实战开发的开发环境、项目核心技术和功能、项目模块和架构设计、开发所需前置知识,若想直接开始编写代码实现,请关注作者,看后面的第二章——项目实现 后端: JDK 17

    2024年04月12日
    浏览(40)
  • 基于Selenium的Web UI自动化测试框架开发实战

    1、自研自动化测试框架 首先进行需求分析。概要设计包括以下三大模块: 公共函数库模块(包括可复用函数库、日志管理、报表管理及发送邮件管理); 测试用例仓库模块(具体用例的相关管理); 可视化页面管理模块(单独针对Web页面进行抽象,封装页面元素和操作方

    2024年01月20日
    浏览(71)
  • Python用selenium实现自动登录和下单的项目实战

    前言 学python对selenium应该不陌生吧 Selenium 是最广泛使用的开源 Web UI(用户界面)自动化测试套件之一。Selenium 支持的语言包括C#,Java,Perl,PHP,Python 和 Ruby。目前,Selenium Web 驱动程序最受 Python 和 C#欢迎。 Selenium 测试脚本可以使用任何支持的编程语言进行编码,并且可以

    2024年01月24日
    浏览(40)
  • 基于Springboot3+微服务实现12306高性能售票系统

    💗博主介绍:全网CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者。 专注于Java、小程序技术领域和毕业项目实战💗 ✌Java、SSM+Vue、SpringBoot+Vue、NodeJS+Vue、微信小程序、Python、大数据、安卓。 你想要的我

    2024年02月20日
    浏览(77)
  • 使用selenium如何实现自动登录

      回顾使用requests如何实现自动登录一文中,提到好多网站在我们登录过后,在之后的某段时间内访问该网页时,不会给出请登录的提示,时间到期后就会提示请登录!这样在使用爬虫访问网页时还要登录,打乱我们的节奏,并详细介绍了使用requests爬取网页时为实现自动登

    2024年02月12日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包