ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python 抢票程序

2021-10-30 11:06:43  阅读:244  来源: 互联网

标签:python 抢票 self 程序 seat lst station driver id


#ticket.py
import  openpyxl
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,ElementNotVisibleException
driver=webdriver.Chrome() #创建浏览器对象
class TrainSpider(object):
    #定义类属性
    login_url='https://kyfw.12306.cn/otn/resources/login.html' #登录的页面
    profile_url='https://kyfw.12306.cn/otn/view/index.html' #个人中心的网址
    left_ticket='https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc' #余票查询页面
    confirm_url='https://kyfw.12306.cn/otn/confirmPassenger/initDc' #确认乘车人和座席

    #定义init初始化方法
    def __init__(self,from_station,to_station,train_date,trains,passenger_name_lst):
        self.from_station=from_station
        self.to_station=to_station
        self.train_date=train_date
        self.station_code=self.init_station_code()  #selft.station_code结果为dict
        self.trains=trains
        self.passenger_name_lst=passenger_name_lst
        self.selected_no=None
        self.selected_seat=None

    #登录的方法
    def login(self):
        # 打开登录的页面
        driver.get(self.login_url)

        WebDriverWait(driver,1000).until(
            ec.url_to_be(self.profile_url) #等待直到URL成为个人中心页面
        )
        print('登录成功')

    #查询余票
    def search_ticket(self):
        # 打开查询余票的网站
        driver.get(self.left_ticket)

        #找到出发站到达站的 隐藏的HTML标签
        from_station_input=driver.find_element_by_id('fromStation')
        to_station_input=driver.find_element_by_id('toStation')

        #找到出发时间的的input标签
        train_date_input=driver.find_element_by_id('train_date')

        #根据key获取value
        from_station_code=self.station_code[self.from_station]  #根据出发地找到出发地的代号
        to_station_code=self.station_code[self.to_station] #根据目的地找到目的地的代码

        #执行js代码
        driver.execute_script('arguments[0].value="%s"' % from_station_code,from_station_input)
        driver.execute_script('arguments[0].value="%s"' % to_station_code,to_station_input)

        driver.execute_script('arguments[0].value="%s"' % self.train_date, train_date_input)

        #执行点击查询按钮,执行查询操作
        query_ticket_tag=driver.find_element_by_id('query_ticket')
        query_ticket_tag.click()

        #解析车次,显示等待,等待tbody的出现
        WebDriverWait(driver,1000).until(
            ec.presence_of_element_located((By.XPATH,'//tbody[@id="queryLeftTable"]/tr'))
        )
        #筛选出有数据的tr,去掉属性为datatran的tr
        trains=driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
        is_flag=False #标记是否有余票 ,没有余票为False,有余票为True
        while True:

            # 分别遍历每个车次
            for train in trains:
                # print(train.text)
                infos = train.text.replace('\n', ' ').split(' ')
                # print(infos)
                train_no = infos[0]  # 列表中索引为0的为车次
                if train_no in self.trains:
                    # 根据key获取值  席别是一个列表
                    seat_types = self.trains[train_no]
                    for seat_type in seat_types:  # 遍历席位的列表
                        if seat_type == 'O':  # 说明是二等座
                            count = infos[9]  # 索引为9的是二等座
                            if count.isdigit() or count == '有':
                                is_flag = True
                                break  # 退出了遍历席位的循环

                        elif seat_type == 'M':  # 说明是一等座
                            count = infos[8]  # 索引为8的是一等座
                            if count.isdigit() or count == '有':
                                is_flag = True
                                break
                    # 判断是否有余票
                    if is_flag:
                        self.selected_no = train_no
                        # 有票就可以执行单击预订
                        order_btn = train.find_element_by_xpath('.//a[@class="btn72"]')
                        order_btn.click()
                        return  # 退出的是遍历车次的循环


    def confirm(self):
        #等待来到确认乘车人界面
        WebDriverWait(driver,1000).until(
            ec.url_to_be(self.confirm_url)
        )
        #等待乘车人标签显示出来
        WebDriverWait(driver,1000).until(
            ec.presence_of_element_located((By.XPATH,'//ul[@id="normal_passenger_id"]/li/label'))
        )
        #获取所有的乘车人
        passengers=driver.find_elements_by_xpath('//ul[@id="normal_passenger_id"]/li/label')
        for passenger in passengers: #分别遍历每一位乘车人 (label标签)
            name=passenger.text  #获取乘车人的姓名
            if name in self.passenger_name_lst:
                passenger.click()   #label标签的单击

        #确认席位
        seat_select=Select(driver.find_element_by_id('seatType_1'))
        seat_types=self.trains[self.selected_no] #根据key获取值 self.trains是要抢票的车次的字典,self.selected_no 要抢票的车次的key
        for seat_type in seat_types:
            try:
                seat_select.select_by_value(seat_type)
                self.selected_seat=seat_type #记录有票的座席

            except NoSuchElementException:
                continue
            else:
                break
        WebDriverWait(driver,1000).until(
            ec.element_to_be_clickable((By.ID,'submitOrder_id')) #等待到a标签可以单击的时候
        )
        #提交订单
        submit_btn=driver.find_element_by_id('submitOrder_id')
        submit_btn.click()

        #显示等待,等待到模式对话框窗口出现
        WebDriverWait(driver,1000).until(
            ec.presence_of_element_located((By.CLASS_NAME,'dhtmlx_window_active'))
        )
        #等待按钮可以点击
        WebDriverWait(driver,1000).until(
            ec.element_to_be_clickable((By.ID,'qr_submit_id'))

        )
        submit_btn=driver.find_element_by_id('qr_submit_id')
        while submit_btn:
            try:
                submit_btn.click()
                submit_btn = driver.find_element_by_id('qr_submit_id')
            except ElementNotVisibleException:
                break
        print(f'恭喜{self.selected_no}的{self.selected_seat}抢票成功!!!')

    #负责调用其它方法(组织其它的代码)
    def run(self):
        # 1.登录
        self.login()
        # 2.余票查询
        self.search_ticket()

        # 3.确认乘车人和订单
        self.confirm()

    def init_station_code(self):
        wb=openpyxl.load_workbook('车站代码.xlsx')
        ws=wb.active #使用活动表
        lst=[] #存储所有车站名称及代号
        for row in ws.rows: #遍历所有行
            sub_lst=[] #用于存储每行中的车站名称,车站代号
            for cell in row: #遍历一行中的单元格
                sub_lst.append(cell.value)
            lst.append(sub_lst)
        #print(dict(lst)) #将列表转成字典类型
        return  dict(lst)

#启动爬虫程序
def start():                                   # O 表示的是二等座,M 代表是一等座
    spider=TrainSpider('长春','北京','2020-11-28',{'D30':['O','M']},['杨淑娟'])
    spider.run()
    #spider.init_station_code()

if __name__ == '__main__':
    start()
 

#demo.py
import  requests
import  re
import  openpyxl
def get_station():
    url='https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9151'
    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36'}
    resp=requests.get(url,headers=headers)
    resp.encoding='utf-8'
    #print(resp.text)
    stations=re.findall('([\u4e00-\u9fa5]+)\|([A-Z]+)',resp.text)
    #print(stations)
    return  stations #stations是一个列表

def save(lst):
    wb=openpyxl.Workbook() #创建工作薄对象
    ws=wb.active #使用活动表
    for item in lst:
        ws.append(item)  #每执行一次append将向sheet中添加一行
    wb.save('车站代码.xlsx')

if __name__ == '__main__':
    lst=get_station()
    save(lst)
 

标签:python,抢票,self,程序,seat,lst,station,driver,id
来源: https://blog.csdn.net/qq_53944807/article/details/121047983

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有