selenium登录铁路12306进行模拟购票

selenium实现12306购票

初衷: 练习一下selenium的知识点 一定可以的

第一步 登录
  • 不要把驱动写到我们的类里面。因为这样会随着类的销毁驱动也会消失,我们要放到全局变量里面
  • 登录成功之后 做了一个显示等待 条件是 个人中心的页面
第二步 车次以及余票查询
## https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc
  • 由个人详情页面跳转到了车次查询界面
  • 获取所有的站点以及对应的编号 --> 保存到了一个字典当中 key name value code
  • 要在 出发地 目的地 出发日期 这些 input标签里面进行设置
    。1 定位input标签
    。2 获取编号
    。3 execute_scrip()方法来设置隐藏标签
driver.execute_script('arguments[0].value="%s"' % self.train_data,
train_data_input
  • 点击查询 出现车次列表
第三步 解析车次列表

显示等待车次列表(条件 这些tr标签加载完成)
车次列表分析 tbody标签下面的tr标签 过滤车次信息 把 [not(@datatran)]
替换并拼接的方式把车次信息放到一个列表当中
init方法里面初始化了一个用户车次 先获得车次 做判断 这个数据是在我们的车次列表
确定乘坐的席位 点击这个席位的预定按钮 xpath
确认乘客信息的界面

第四步 确认乘客信息和席位
  • 显示等待 条件是判断是否确认乘客信息

  • 补充 显示等待 乘客标签有没有加载出来 label ( input 标签选不中)

  • init 方法里面进行初始化了乘客信息 [‘xxx’,‘xxxx’]

  • 人对应了一个它的席位 name —> value

  • 席位是select标签 下标/ value

  • 二等座正好没有了 NoSuchElementException try catch处理
    。最终的提交订单
    。等待弹框的页面加载出来
    。定位确定按钮 提交订单 就会生成订单

  • 有可能点击不住那个提交订单的按钮 (无限循环去点击这个按钮 直到点击成功 出现那个提示为止

完整代码

import csv
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
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException, ElementNotInteractableException

driver = webdriver.Chrome()


class TrainSpider():
    login_url = 'https://kyfw.12306.cn/otn/resources/login.html'  # 登录的界面
    person_url='https://kyfw.12306.cn/otn/view/index.html' #登录后的一个url地址
    left_ticket_url='https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc' # 车次余票的url
    confirm_passengers_url='https://kyfw.12306.cn/otn/confirmPassenger/initDc' # 确认乘客信息的地址

    def __init__(self, from_station, to_station, train_data,trains,passengers):
        '''

        :param from_station: 出发地
        :param to_station: 目的地
        :param train_data: 出发日期
        :param trains: 需要购买的车次以及车次所对应的席位 {'G1972':['M','O']}
        :param passengers: 乘车人姓名 他是一个列表['张三','李四']
        '''
        self.from_station = from_station
        self.to_station = to_station
        self.train_data = train_data
        self.trains=trains
        self.passengers=passengers
        self.selected_number=None
        self.station_codes = {}
        self.init_station_code()

    def init_station_code(self):

        with open('stations.csv', 'r', encoding='utf-8') as f1:
            reader = csv.DictReader(f1)
            for line in reader:
                name = line['name']
                code = line['code']
                self.station_codes[name]=code

    def login(self):  # 登录模块
        driver.get(self.login_url)
        WebDriverWait(driver,1000).until(
            EC.url_contains(self.person_url) # 包含登录后的url 进行显示等待
        )
        print("登录成功!")


    def search_left_ticket(self): # 2.车次以及余票查询
        driver.get(self.left_ticket_url) #加载余票查询的界面
        #出发地
        from_station_input=driver.find_element_by_id("fromStation")
        from_station_code=self.station_codes[self.from_station]
        driver.execute_script('arguments[0].value="%s"'%from_station_code,from_station_input)#实际上已经设计进去了出发地

        #目的地
        to_station_input=driver.find_element_by_id("toStation")
        to_station_code=self.station_codes[self.to_station]
        driver.execute_script('arguments[0].value="%s"' % to_station_code, to_station_input)  # 实际上已经设计进去了出发地

        #出发日期
        train_data_input=driver.find_element_by_id('train_date')
        driver.execute_script('arguments[0].value="%s"' % self.train_data, train_data_input)

        #执行查询操作
        trun_btn=driver.find_element_by_id('qd_closeDefaultWarningWindowDialog_id')
        trun_btn.click()
        serach_btn=driver.find_element_by_id('query_ticket')
        serach_btn.click()

        #解析车次信息
        WebDriverWait(driver,1000).until(
            EC.presence_of_element_located((By.XPATH,'//tbody[@id="queryLeftTable"]/tr')) #加载一个元素出来结束显示等待
        )
        #获取tr标签 把含有datatran的标签过滤掉
        train_trs=driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
        is_searched=False
        for train_tr in train_trs:
            infos=train_tr.text.replace('\n',' ').split(' ')
            number=infos[0] # 车次
            if number in self.trains:
                seat_types=self.trains[number]
                for seat_type in seat_types:
                    if seat_type =='O':
                        #二等座
                        count=infos[9]
                        if count=="有" or count.isdigit():
                            is_searched=True
                            break
                    elif seat_type=='M':
                        #一等座
                        count = infos[8]
                        if count == "有" or count.isdigit():
                            is_searched = True
                            break

                if is_searched:
                    self.selected_number=number
                    #点击预订
                    order_btn=train_tr.find_element_by_xpath('.//a[@class="btn72"]')
                    order_btn.click()
                    break


    def confirm_passengers(self):
        WebDriverWait(driver,1000).until(
            EC.url_contains(self.confirm_passengers_url)
        )
        #如果出现无法点击提交按钮
        WebDriverWait(driver, 1000).until(
            EC.presence_of_element_located((By.XPATH,'//ul[@id="normal_passenger_id"]/li/label'))
        )

        #确认需要购买车票的乘客
        passenger_labels=driver.find_elements_by_xpath('//ul[@id="normal_passenger_id"]/li/label')
        for passenger_label in passenger_labels:
            name=passenger_label.text
            if name in self.passengers:
                passenger_label.click()

        #确认需要购买座位信息
        seat_select=Select(driver.find_element_by_id('seatType_1'))
        seat_types=self.trains[self.selected_number]
        for seat_type in seat_types:
            try:
                seat_select.select_by_value(seat_type)
            except NoSuchElementException:
                continue
            else:
                break

        #提交订单
        subm_btn=driver.find_element_by_id("submitOrder_id")
        subm_btn.click()

        WebDriverWait(driver,1000).until(
            EC.presence_of_element_located((By.CLASS_NAME,'dhtmlx_window_active'))
        )

        #确定按钮
        btn=driver.find_element_by_id('qr_submit_id')
        while btn:
            try:
                btn.click()
                btn = driver.find_element_by_id('qr_submit_id')
            except ElementNotInteractableException:
                break

    def run(self):
        # 1.登录
        self.login()
        #2.车次以及余票查询
        self.search_left_ticket()
        #3.确认乘客信息与车次信息
        self.confirm_passengers()


def main():
    spider = TrainSpider('兰州', '上海', '2021-01-13',{'G1972':['O','M']},['龙悟选'])
    spider.run()


if __name__ == '__main__':
    main()

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值