目录

一、说明

1.1、背景

1.2、说明

二、步骤

2.1、切换视角检索乘车乘客

2.2、选择乘客

2.3、关闭学生票选择界面

2.4、提交订单

2.5、选择座位并确认

三、完整代码与视频演示

3.1、完整源代码如下

3.2、视频演示代码运行

四、结果

4.1、代码运行结果

五、总结与完善

5.1、总结

5.2、完善


一、说明

1.1、背景

接前面一、二部分解决抢不到票的问题,本部分解决乘客选择与车票提交问题,并完整完成自动化购票功能。

1.2、说明

操作系统:win 10

编辑器:pycharm edu

语言及版本:python 3.10

使用的库:selenium

实现思路:使用selenium模拟人的行为,进行自动化操作

关于代码:完整代码已放出

第一部分内容-->已解决登录问题

第一部分内容链接:第一部分内容

第二部分内容-->已解决车次查找与预定车次问题

第二部分内容链接:第二部分内容

浏览器下载与驱动的安装:火狐浏览器下载与驱动下载

浏览器闪退说明:大概率是因为下载的浏览器和浏览器驱动版本不一致,建议使用搜索引擎查找大佬分享的内容解决

tips:以下url不会放真实的,拿来测试注意识别并自行更改。

二、步骤

当前界面默认进入乘客选择界面,因为之前的内容已经进入到该界面了。

2.1、切换视角检索乘车乘客

需要先把这个提示内容去掉,在输入需要购买车票的乘客名字进行检索,如下图1;

    # 进入订单界面,切换视角
    driver.switch_to.window(driver.window_handles[-1])
    time.sleep(3)  # 给加载时间
    # 进入乘客选择
    driver.find_element(By.XPATH, '//*[@id="quickQueryPassenger_id"]').click()  # 先点击,把提示内容去除
    driver.find_element(By.XPATH, '//*[@id="quickQueryPassenger_id"]').send_keys("乘客名字")  # 输入乘客姓名

 图1

2.2、选择乘客

乘客检索出来后,进行乘客的选择,如下图2;

    time.sleep(0.5)  # 给加载时间
    driver.find_element(By.XPATH, '//*[@id="normalPassenger_0"]').click()  # 选择乘客

 图2

2.3、关闭学生票选择界面

选择乘客后,如果是学生会出现学生票购买提示页面,需要关闭这个页面,如下图3;

    time.sleep(2)  # 给加载时间
    driver.find_element(By.XPATH, '//*[@id="dialog_xsertcj_cancel"]').click()  # 关闭学生票选项

图3

2.4、提交订单

一切准备就绪,可以进行提交订单了,如下图4;

    driver.find_element(By.XPATH, '//*[@id="submitOrder_id"]').click()  # 提交订单

 图4

2.5、选择座位并确认

座位选择的是F靠窗位置,座位不选择直接提交订单,随机座位也是可以的;

    # 选择座位,这里选择的是靠窗的F座位,不选择座位也是可以的
    driver.find_element(By.XPATH, '//*[@id="1F"]').click()
    # 点击确认订单
    driver.find_element(By.XPATH, '//*[@id="qr_submit_id"]').click()

三、完整代码与视频演示

3.1、完整源代码如下

from selenium.webdriver import Firefox  # 导入火狐
from selenium.webdriver.common.action_chains import ActionChains  # 导入时间链
from selenium.webdriver.common.by import By  # 导入需要的组件
from selenium.webdriver.common.keys import Keys


import time


def login_shop():
    login_url = "这里是12306登录的url"  # 登录界面url
    trains = ['G4362', 'K1208']  # 这里是你要购买票的车次名称

    driver = Firefox()
    driver.get(login_url)

    script = 'Object.defineProperty(navigator,"webdriver",{get:()=>false,});'
    driver.execute_script(script)

    driver.find_element(By.XPATH, '//*[@id="J-userName"]').send_keys("你的账户")
    driver.find_element(By.XPATH, '//*[@id="J-password"]').send_keys("你的密码")
    driver.find_element(By.XPATH, '//*[@id="J-login"]').click()
    time.sleep(5)
    push_btu = driver.find_element(By.XPATH, '//*[@id="nc_1_n1z"]')
    # 拖动滑块后,会跳转新窗口                     //*[@id="nc_1_n1z"]

    ActionChains(driver).drag_and_drop_by_offset(push_btu, 300, 0).perform()
    # 切换到新窗口
    driver.switch_to.window(driver.window_handles[-1])
    time.sleep(3)
    # 刷新
    driver.refresh()
    time.sleep(3)
    # 在新窗口点击前往订票,又会跳转到新窗口
    driver.find_element(By.XPATH, '//*[@id="link_for_ticket"]').click()
    # 这里也生成了一个新窗口,需要切换
    driver.switch_to.window(driver.window_handles[-1])
    time.sleep(5)
    # 出发地
    driver.find_element(By.XPATH, '//*[@id="fromStationText"]').click()
    driver.find_element(By.XPATH, '//*[@id="fromStationText"]').send_keys("深圳北", Keys.ENTER)
    # 目的地
    driver.find_element(By.XPATH, '//*[@id="toStationText"]').click()
    driver.find_element(By.XPATH, '//*[@id="toStationText"]').send_keys("百色", Keys.ENTER)
    # 日期,先清除默认内容,在输入
    driver.find_element(By.XPATH, '//*[@id="train_date"]').click()
    driver.find_element(By.XPATH, '//*[@id="train_date"]').clear()
    driver.find_element(By.XPATH, '//*[@id="train_date"]').send_keys("2023-01-20")
    # 点击查询
    driver.find_element(By.XPATH, '//*[@id="query_ticket"]').click()
    # 保存加载出来的车次信息,并进行筛选判断
    time.sleep(6)  # 确保页面内容加载完成
    # print(driver.current_url)
    tr_list = driver.find_elements(By.XPATH, ".//tbody[@id='queryLeftTable']/tr[not(@datatran)]")
    #                                            //*[@id="queryLeftTable"]
    for tr in tr_list:  # 遍历所有车次信息
        train_number = tr.find_element(By.CLASS_NAME, "number").text  # 车次
        print(train_number)
        if train_number in trains:  # 如果该车次在输入的车次里
            left_ticker_td = tr.find_element(By.XPATH, './/td[4]').text
            if left_ticker_td == '有' or left_ticker_td.isdigit():  # 如果该车次有票
                print(train_number+'有票')
                btn72 = tr.find_element(By.CLASS_NAME, 'btn72')  # 找到该车次的预订按钮
                btn72.click()
                break  # 这里点击了之后一定要退出,否则程序继续循环会导致报错
    # 进入订单界面,切换视角
    driver.switch_to.window(driver.window_handles[-1])
    time.sleep(3)  # 给加载时间
    # 进入乘客选择
    driver.find_element(By.XPATH, '//*[@id="quickQueryPassenger_id"]').click()  # 先点击,把提示内容去除
    driver.find_element(By.XPATH, '//*[@id="quickQueryPassenger_id"]').send_keys("乘客名称")  # 输入乘客姓名
    time.sleep(0.5)  # 给加载时间
    driver.find_element(By.XPATH, '//*[@id="normalPassenger_0"]').click()  # 选择乘客
    time.sleep(2)  # 给加载时间
    driver.find_element(By.XPATH, '//*[@id="dialog_xsertcj_cancel"]').click()  # 关闭学生票选项
    driver.find_element(By.XPATH, '//*[@id="submitOrder_id"]').click()  # 提交订单
    # 选择座位,这里选择的是靠窗的F座位,不选择座位也是可以的
    driver.find_element(By.XPATH, '//*[@id="1F"]').click()
    # 点击确认订单
    driver.find_element(By.XPATH, '//*[@id="qr_submit_id"]').click()

if __name__ == '__main__':
    login_shop()

3.2、视频演示代码运行

视频已经制作好了,但是有些奇怪不知道为啥电脑接收不了,所以就不上传了,需要视频请在评论区评论或者私聊我。

四、结果

4.1、代码运行结果

如下图5:

图5

五、总结与完善

5.1、总结

1)将一个大问题分析若干部分解决,将会变得轻松;

2)多学习;

5.2、完善

1)在以上的代码中用到了很多延时来确保页面可以加载成功,导致抢票慢,那么如何改进呢?

有两个库可以解决这个问题;

from selenium.webdriver.support.ui import WebDriverWait  # 条件等待
from selenium.webdriver.support import expected_conditions  # 导入判断条件

加入限定条件,确保页面加载完成了在进行下一步代码的执行,就不需要一直time.sleep了;

2)我们简陋的程序如何能抢得过各大抢票平台呢?

使用服务器进行代码的持续运行,增加购票成功的几率;

3)我们代码只能进行单次的抢票,如何进行多次抢票呢?

使用循环,或者其它条件,指定时间就执行一次代码,进行查票购票等操作即可;

4)买到票之后,只有10分钟的付款时间,抢到票如何进行快速通知呢?

Python实现用QQ邮箱发邮件进行提醒等;

总之,购票平台的自动化购票对我而言是一次很好的锻炼,以上内容是粗略记录该过程,之后更加完善自动化购票功能在进行分享,欢迎批评指正;

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐