zoukankan      html  css  js  c++  java
  • python+splinter实现12306网站刷票并自动购票流程

    python+splinter实现12306网站刷票并自动购票流程

    通过python+splinter,实现在12306网站刷票并自动购票流程(无法自动识别验证码)。

    此类程序只是提高了12306网站的 <查询> 刷新频率(默认自动查询的刷新频率为5秒)。对于学习splinter感觉还是不错的,但是想通过装个类似刷票程序成功购票的 还是多花点钱升级升级硬件设备,提高提高网速吧。

    程序写的有点乱,随时修改ing。

    #!/usr/bin/env python3
    # encoding: utf-8
      
    from splinter.browser import browser
    import time
      
    #12306的账号,密码
    user_name = 'xxxxxxxxxx' #自行修改
    pass_word = 'xxxxxxxxxx'
      
    # 通过splinter,登录12306网站(登录验证码需要手动验证)
    b = browser(driver_name = 'firefox') # 设置火狐浏览器
    b.visit('https://kyfw.12306.cn/otn/leftticket/init') # 打开12306界面
    b.find_by_id(u'login_user') # 点击登录按钮
      
    b.fill('loginuserdto.user_name',user_name) # 填写账号
    b.fill('userdto.password',pass_word) # 填写密码
      
    # 手动填写验证码并登录,登录成功后等待自动跳转到购票页面。
    '''
    跳转页面过程中:
    程序可能会报错:[winerror 10053] 您的主机中的软件中止了一个已建立的连接。
    原因:未知
    解决办法:写一个循环,程序不停的尝试链接跳转页面(总会成功),成功后跳出循环。
    '''
    while true:
      if b.url == 'https://kyfw.12306.cn/otn/index/initmy12306': # 判断是否登录成功
        try:
          b.visit('https://kyfw.12306.cn/otn/leftticket/init') # 访问购票页面
        except connectionabortederror: #捕捉可能出现的异常,继续访问
          b.visit('https://kyfw.12306.cn/otn/leftticket/init')
        if b.url == 'https://kyfw.12306.cn/otn/leftticket/init': # 判断是否跳转购票页面成功
          break
      
    # 添加、加载cookies信息,查询余票。(自动添加出发地、目的地、日期,例如:北京-郑州)
    b.cookies.add({'_jc_save_fromdate':'2018-08-11'}) # 出发日期
    b.cookies.add({'_jc_save_fromstation':u'%u5317%u4eac%2cbjp'}) # 出发站信息(北京)
    b.cookies.add({'_jc_save_todate':'2018-08-11'}) # 到达日期
    b.cookies.add({'_jc_save_tostation':u'%u90d1%u5dde%2czzf'}) # 目的地信息(郑州)
    b.reload() # 重新加载cookies
    b.find_by_text(u'查询').click() #点击查询
      
    # 添加车次类型
    l = ['gc-高铁/城际','d-动车','z-直达','t-特快','k-快速','其他']#在列表里可以去掉不需要的车次类型
    for i in l:
      btn = b.find_by_text(i)
      btn.click()
       
    # 下拉订票帮手(此步骤可跳过) 
    b.find_by_id(u'show_more').click()
      
      
    # 设置坐席
    def the_seat():
      
      '''
      添加坐席后,网站会自动勾选<自动提交>、<自动查询>功能。
      <自动查询> 默认的是5秒刷新一次(慢),所以我们要关闭此选项,提高刷新频率。
      '''
      seat =['二等座','软卧','硬卧','硬座','无座'] #设置一个坐席列表
      b.find_by_xpath('/html/body/div[6]/div[5]/div[2]/div[7]/div[2]/span/a').click()#打开坐席选择的菜单窗口
      for i in seat:
        b.find_by_name(i).click() #添加坐席
      b.find_by_xpath('/html/body/div[11]/div[1]/a').click()#关闭弹窗
      b.find_by_text(u'开启自动查询').click()# 点击关闭<自动查询>选项(慢)。关闭自动查询功能后,自动提交功能也会关闭。
      
      
    # 购票
    def train_ticket_purchase():
       
      the_seat() #设置坐席
      b.find_by_id(u'show_more').click() # 关闭订票帮手(此步骤可跳过)
      
      #查询订票
      while b.url != 'https://kyfw.12306.cn/otn/confirmpassenger/initdc': #以预订成功跳转页面为判断条件
        try:
          b.find_by_text(u'查询').click() # 点击查询
          if b.is_element_present_by_text(u'预订') == true: #判断是否有<预订>
            for i in b.find_by_text(u'预订'): # b.fin_by_text(u'预订'),返回包含<预订>元素的列表,其中有些可以点击‘预订'购票,有些‘预订'显灰色无票状态,无法点击预订购票的。
              if i.has_class('btn72'): #筛选<预订>元素,区分可以点击预订的和不可以点击的(可以点击<预订>的元素,都包含属性class('btn72'))
                i.click()#点击预订购票
               
                if b.is_element_present_by_xpath('//*[@id="content_defaultwarningalert_hearder"]') == true: #可能会弹窗提示:当前时间不可预订
                  b.find_by_xpath('//*[@id="gb_closedefaultwarningwindowdialog_id"]').click() # 关闭提示弹窗
                  print('当前时间不可预订,请关闭程序稍后再运行。')
                  break
      
                if b.is_element_present_by_xpath('//*[@id="content_defaultwarningalert_title"]') == true: #可能会弹窗提示:您选择的列车距开车时间很近了,请确保有足够的时间抵达车站,并办理换取纸质车票、安全检查、实名制验证及检票等手续,以免耽误您的旅行。
                  b.find_by_xpath('//*[@id="qd_closedefaultwarningwindowdialog_id"]').click() #关闭弹窗(注意:关闭弹窗,但是仍然会购票)
                 
                b.find_by_text(u'xxx')[1].click() #自行添加乘车人名字(注意:登录账号本人的名字元素可能会有两个(一个账号,一个乘车人),注意区分开)
                b.find_by_text(u'提交订单').click()
      
                #确认订单(不知道为什么 b.find_by_xpath()方法不行。。。。)
                b.find_by_css('html body#body_id.dhtmlx_winviewport.dhtmlx_skin_dhx_terrace div.dhtmlx_window_active div.dhtmlx_wins_body_outer div.dhtmlx_wins_body_inner.dhtmlx_wins_no_header div div#checkticketinfo_id div#content_checkticketinfo_id.up-box.w664 div.up-box-bd.ticket-check div#confirmdiv.lay-btn a#qr_submit_id.btn92s').click()
                print('预订成功,退出程序')
                break
              else:
                print('暂时没票,继续查询中...')
          else:
            print('暂时没票,继续查询中...')     
        except:
          print('不可预订,请稍后再次运行程序...')
          break
      
      
    if __name__ == '__main__':
      train_ticket_purchase()

  • 相关阅读:
    Sql server2008如何导入Excel文件数据?
    oracle和sql server中,取前10条数据语法的区别
    如何将两个字段合成一个字段显示(oracle和sqlserver的区别)
    php递归注意事项
    PHP实现执行定时任务
    商城怎么使用ajax?
    添加新权限管理
    PHP判断一个JSON对象是否含有某一个属性的方法
    centos 中查找文件、目录、内容
    phpStorm中如何不让其自动添加封闭大括号?
  • 原文地址:https://www.cnblogs.com/zgq123456/p/10063742.html
Copyright © 2011-2022 走看看