Python爬虫-使用selenium+chromedriver实现12306自动抢票

实现功能:
  1、让浏览器打开12306的登录界面,然后手动进行登录;
  2、登录完成后让浏览器跳转到购票的界面;
  3、手动输入出发地、目的地、出发日,检测到以上三个信息都输入完成后,然后找到查询按钮,执行点击事件,进行车次查询;
  4、查找我们需要的车次,然后看对应的席位是否还有余票(有、数字),找到这个车次的预订按钮,然后执行点击事件,如果没有出现以上两个(有、数字),那么我们就让循环这个查询工作;
  5、一旦检测到有票(有、数字),就执行预订按钮的点击事件,来到预订的界面后,找到对应的乘客,然后找到这个乘客的checkbox,执行点击事件,再找到提交订单的按钮,执行点击事件;
  点击完提交订单按钮以后,会弹出一个确认的对话框,然后找到“确认”按钮,执行点击事件,这样就完成了抢票。

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

class robTickets(object):
    # 初始化函数
    def __init__(self):
        self.loginUrl = "https://kyfw.12306.cn/otn/resources/login.html"
        self.userCenterUrl = "https://kyfw.12306.cn/otn/view/index.html"
        self.searchTicketUrl = "https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc"
        self.selectPassengerUrl = "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
        driverPath = r"D:\chromedriver\chromedriver.exe"
        self.driver = webdriver.Chrome(executable_path=driverPath)  # 驱动Chrome浏览器进行操作

    def waitInput(self):
        self.fromStation = input("出发地:")
        self.toStation = input("目的地:")
        # 时间格式必须为yyyy-MM-dd的形式
        self.trainDate = input("出发日(格式:2020-04-01):")
        self.passengers = input("乘客姓名(如有多个乘客,用英文逗号隔开):").split(",")
        self.trains = input("车次(如有多个车次,用英文逗号隔开):").split(",")

    # _login只想在类中调用
    def _login(self):
        self.driver.get(self.loginUrl)  # 打开登录页面
        WebDriverWait(self.driver, timeout=1000).until(
            EC.url_to_be(self.userCenterUrl)
        )
        print("恭喜你,已成功登录!")

    def _orderTicket(self):
        # 跳转到查询余票的页面
        self.driver.get(self.searchTicketUrl)

        # 等待出发地是否输入正确
        WebDriverWait(self.driver, timeout=1000).until(
            EC.text_to_be_present_in_element_value((By.ID, "fromStationText"), self.fromStation)
        )

        # 等待目的地是否输入正确
        WebDriverWait(self.driver, timeout=1000).until(
            EC.text_to_be_present_in_element_value((By.ID, "toStationText"), self.toStation)
        )

        # 等待出发日是否输入正确
        WebDriverWait(self.driver, timeout=1000).until(
            EC.text_to_be_present_in_element_value((By.ID, "train_date"), self.trainDate)
        )

        # 等待查询按钮是否可用
        WebDriverWait(self.driver, timeout=1000).until(
            EC.element_to_be_clickable((By.ID, "query_ticket"))
        )

        # 如果可以点击了,那么就找到这个查询按钮,执行点击事件
        searchBtn = self.driver.find_element_by_id("query_ticket")
        searchBtn.click()

        # 在点击查询按钮后,等待车次信息是否显示出来
        WebDriverWait(self.driver, timeout=1000).until(
            EC.presence_of_element_located((By.XPATH, ".//tbody[@id='queryLeftTable']/tr"))
        )

        # 找到所有没有datatran属性的tr标签,这些标签是存储了车次信息的
        trList = self.driver.find_elements_by_xpath(".//tbody[@id='queryLeftTable']/tr[not(@datatran)]")

        # 遍历所有的满足条件的tr标签
        for tr in trList:
            trainNum = tr.find_element_by_class_name("number").text
            if trainNum in self.trains:
                leftTicket = tr.find_element_by_xpath(".//td[4]").text  # 找到第4个标签下的文本
                if leftTicket == "有" or leftTicket.isdigit():   # 判断输入的车次是否在列表中
                    orderBtn = tr.find_element_by_class_name("btn72")
                    orderBtn.click()

                    # 等待是否来到乘客选择页面
                    WebDriverWait(self.driver, 1000).until(EC.url_to_be(self.selectPassengerUrl))

                    # 等待所有乘客信息是否被加载完毕
                    WebDriverWait(self.driver, timeout=1000).until(
                        EC.presence_of_element_located((By.XPATH, ".//ul[@id = 'normal_passenger_id']/li"))
                    )

                    # 获取所有的乘客信息
                    passengerLabels = self.driver.find_elements_by_xpath(".//ul[@id='normal_passenger_id']/li/label")
                    # 遍历所有的label标签
                    for passengerLabel in passengerLabels:  # 遍历所有的label标签
                        name = passengerLabel.text
                        if name in self.passengers: # 判断姓名是否在之前输入的姓名列表中
                            passengerLabel.click()  # 执行点击操作
                    # 获取提交按钮
                    submitBtn = self.driver.find_element_by_id("submitOrder_id")
                    submitBtn.click()

                    # 显示等待确认订单对话框是否出现
                    WebDriverWait(self.driver, timeout=1000).until(
                        EC.presence_of_element_located((By.CLASS_NAME,'dhtmlx_wins_body_outer'))
                    )
                    # 显示等待确认按钮是否加载出现,出现后执行点击操作
                    WebDriverWait(self.driver, timeout=1000).until(
                        EC.presence_of_element_located((By.ID, "qr_submit_id"))
                    )

                    confirmBtn = self.driver.find_element_by_id("qr_submit_id")
                    confirmBtn.click()
                    return

    def run(self):
        self.waitInput()
        self._login()
        self._orderTicket()

if __name__ == '__main__':
    spider = robTickets()
    spider.run()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 还有不到一个月就过春节了,你回家的火车票都买了吗?如果没有买到的话,不妨试用下本文的 Python 程序来帮你抢火...
    张轩1986阅读 707评论 1 1
  • *** 说明***:这不是黑科技,并不是自动购票,请根据自己的需求使用,建议使用抢票 APP 靠谱一些,360 抢...
    於風聽語阅读 1,567评论 0 3
  • 复制 1.复制类型 2.复制原理 3复制常用的用途 4复制如何工作 5配置复制 6给一个已经运行的服务器配置备库 ...
    wwwxi阅读 314评论 0 0
  • 2018.05.03 编号28 日精进701天 今日感悟: 1持续分享对人有帮助的点,身边一定不缺正能量的朋友! ...
    宇宙之爱黄昊贵阅读 170评论 0 0
  • Put out the lamp when thou wishest.
    冬夜里的雪阅读 160评论 1 2

友情链接更多精彩内容