草庐IT

python+selenium实现12306抢票

TAO-LaVine 2024-07-06 原文

python+selenium实现12306抢票

一、准备工作

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

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

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

2.1 安装chromedriver

谷歌浏览器驱动的网址为link
注意:谷歌浏览器的驱动版本要匹配谷歌浏览器的版本
随机点击一个版本:

点击notes.txt

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

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

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

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

from selenium import webdriver
from time import sleep#页面等待时间
from selenium.webdriver.common.by 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(By.ID,"J-userName")
        passWord_tag=self.options.find_element(By.ID,"J-password")
        userName_tag.send_keys(self.userName)
        passWord_tag.send_keys(self.passWord)
        btn=self.options.find_element(By.ID,"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(By.ID,"fromStationText")
        arrival=self.options.find_element(By.ID,"toStationText")
        date=self.options.find_element(By.ID,"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(By.ID,"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()

有关python+selenium实现12306抢票的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  3. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  4. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  5. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  6. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  7. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  8. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  9. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  10. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

随机推荐