python+selenium实现12306抢票

一、准备工作

1、要先下载相关的包,selenium、interval。最好使用国内清华源

pip install (which package) -i https://pypi.tuna.tsinghua.edu.cn/simple

2、还要下载对应浏览器的驱动:

2.1 安装chromedriver

谷歌浏览器驱动的网址为link 注意:谷歌浏览器的驱动版本要匹配谷歌浏览器的版本

随机点击一个版本:

用python抢票犯法吗 python 抢票_开发语言


点击notes.txt

用python抢票犯法吗 python 抢票_selenium_02

2.2 安装FireFox驱动(我用的是这个)

火狐驱动下载网址:link 然后一样的下载对应的驱动版本

2.3 最后把下载好的驱动解压,移动到/usr/bin文件夹(linux系统)中或者放入python一级目录下就好了

二、具体实现过程(代码有具体注释)

from selenium import webdriver
from time import sleep#页面等待时间
from  import By#定位元素
from selenium.webdriver import ActionChains#完成一系列自动化操作
from selenium.webdriver.common.keys import Keys#完成键盘上的操作
from collections import defaultdict#初始化字典,value为列表
import re#用于正则表达式
# from datetime import datetime
from interval import IntervalSet#用于定义时间区间
# import json

class TrainTicketLogin(object):
    def __init__(self):
        #12306登录网页的网址
        self.url='https://kyfw.12306.cn/otn/resources/login.html'
        #你自己的用户名
        self.userName='XXXXXXXXXXX'
        #你自己的密码
        self.passWord='XXXXXX'
        #我用的是火狐浏览器,如果用的是谷歌,要提前下载好对应浏览器的驱动,这里实例化一个浏览器操作对象
        self.options=webdriver.Firefox()
    def login(self,url):
        self.options.get(self.url)
        login_method=self.options.find_element(By.XPATH,'//div[@class="login-box"]/ul/li[1]/a')
        login_method.click()
        userName_tag=self.options.find_element(,"J-userName")
        passWord_tag=self.options.find_element(,"J-password")
        userName_tag.send_keys(self.userName)
        passWord_tag.send_keys(self.passWord)
        btn=self.options.find_element(,"J-login")
        btn.click()
        sleep(3)
        slide_btn=self.options.find_element(By.XPATH,'//*[@id="nc_1_n1z"]')
        self.Verification(slide_btn)
    def Verification(self,button):
        action1=ActionChains(self.options)
        # 防止12306网站禁止selenium而出现的error
        script = 'Object.defineProperty(navigator,"webdriver",{get:()=>undefined,});'
        self.options.execute_script(script)
        action1.click_and_hold(button)
        action1.move_by_offset(300,0).perform()
        #释放鼠标
        action1.release().perform()
        sleep(1)
    def get_ticket(self):
        chepiao_button=self.options.find_element(By.XPATH,'//a[@id="link_for_ticket"]')
        chepiao_button.click()
        sleep(3)
        origin=self.options.find_element(,"fromStationText")
        arrival=self.options.find_element(,"toStationText")
        date=self.options.find_element(,"train_date")
        my_chufa=IntervalSet.between(self.l_time_interval_left,self.l_time_interval_right)
        my_daoda=IntervalSet.between(self.a_time_interval_left,self.a_time_interval_right)
        #出发地键入
        origin.click()
        origin.send_keys(self.loc_l)
        origin.send_keys(Keys.ARROW_DOWN)
        origin.send_keys(Keys.ENTER)
        sleep(1)
        #目的地键入
        arrival.click()
        arrival.send_keys(self.loc_a)
        arrival.send_keys(Keys.ARROW_DOWN)
        arrival.send_keys(Keys.ENTER)
        sleep(1)
        #出发日期键入
        date.clear()
        date.send_keys(self.go_date)
        date.send_keys(Keys.ENTER)
        #是否选择学生票(若为普通票则注释掉以下代码)
        # self.options.find_element(,"sf2").click()
        #点击查询操作
        query_button=self.options.find_element(By.XPATH,'//div[@class="btn-area"]/a')
        query_button.click()
        #请输入选择的train型号(K字头还是G字头还是D字头还是其他)
        sleep(5)
        #进行正则匹配
        ex='<tr id="ticket_(.*?)" class.*?>'
        train_info=defaultdict(list)
        train_type=re.findall(ex,self.options.page_source)
        for train in train_type:
            xpath_1='//tr[@id=\"{}\"]/td[1]/div/div[3]/strong[1]'.format('ticket_'+train)
            xpath_2='//tr[@id=\"{}\"]/td[1]/div/div[3]/strong[2]'.format('ticket_'+train)
            origin_time=self.options.find_element(By.XPATH,xpath_1).text
            arrive_time=self.options.find_element(By.XPATH,xpath_2).text
            train_info[train]=[origin_time,arrive_time]
        #预览一下火车的信息
        # print(train_info)
        #请输入你理想的乘车时间区间和到达时间区间
        for key,value in train_info.items():
            if self.train_ in key.split('_')[0]:
                xpath_3='//*[@id=\"{}\"]'.format(self.type+'_'+key.split('_')[0])
                left_tickets=self.options.find_element(By.XPATH,xpath_3).text
                if value[0] in my_chufa and value[1] in my_daoda and \
                    (left_tickets.isdigit() or left_tickets=='有'):
                    xpath_4='//tr[@id=\"{}\"]//*[@class="btn72"]'.format('ticket_'+key)
                    self.options.find_element(By.XPATH,xpath_4).click()
                    #请选择乘车人,这里选择默认乘车人(第一个人)
                    sleep(2)
                    self.options.find_element(By.XPATH,'//*[@id="normalPassenger_0"]').click()
                    sleep(2)
                    self.options.find_element(By.XPATH,'//*[@id="submitOrder_id"]').click()
                    #确定买票(等待较长时间才能锁定席位)
                    sleep(2)
                    self.options.find_element(By.XPATH,'//*[@id="qr_submit_id"]').click()
                    #返回修改
                    # sleep(2)
                    # self.options.find_element(By.XPATH,'//*[@id="back_edit_id"]').click()
                    


        
        

        

        

    def run(self):
        self.login(self.url)
        sleep(5)
        hint=self.options.find_element(By.XPATH,'//div[@class="modal-ft"]/a')
        hint.click()
        sleep(3)
        self.loc_l=input("请输入出发地:")
        self.loc_a=input("请输入目的地:")
        self.go_date=input("请输入出发日期(格式为%Y-%m-%d的形式):")
        self.l_time_interval_left=input("请输入理想出发时间的左端点:")
        self.l_time_interval_right=input("请输入理想出发时间的右端点:")
        self.a_time_interval_left=input("请输入理想到达时间的左端点:")
        self.a_time_interval_right=input("请输入理想到达时间的右端点:")
        self.train_=input("你想坐高铁还是火车还是动车(G、K、D、T):")
        if self.train_ in ['K','T']:
            # 如果选择火车(软卧、硬卧、硬座)
            self.type=input("请输入你要乘坐的类型(RW、YW、YZ):")
        else:
            self.type=input("请输入你要乘坐的类型(SWZ(商务座)、ZY(一等座)、ZE(二等座)):")
        self.get_ticket()

        # self.options.quit()
if __name__=='__main__':
    Spider=TrainTicketLogin()
    Spider.run()