发表于 2022-11-15 11:36

申请会员ID: xiaopacai2

1、申 请 I D:xiaopacai2
2、个人邮箱:464757237@qq.com
3、原创技术文章:利用python结合selenium编写12306自动化抢票程序

代码简介:

[*]selenium结合谷歌驱动登陆12306火车票订购网站,其中验证等待手动输入
[*]获取输入的出发地-目的地信息并查询车票
[*]pandas保存返回的车次以及座位信息
[*]选择乘车人以及车次,座次,如果有票,提交订单
[*]如果没有,每5s刷新一次车次信息,直到抢到对应的车票



代码如下:

# -*- coding: utf-8 -*-
"""
Created on Sun Jan 30 19:45:18 2022

@author: Yuan
"""

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
import pandas as pd
import time

class get_tickets(object):

    def __init__(self):
      self.login_url = 'https://kyfw.12306.cn/otn/resources/login.html'
      self.init_url = 'https://kyfw.12306.cn/otn/view/index.html'
      self.search_url = 'https://kyfw.12306.cn/otn/leftTicket/init'
      self.driver = webdriver.Chrome()
      self.options = webdriver.ChromeOptions()
      self.script = 'Object.defineProperty(navigator,"webdriver",{get:()=>undefined,});'
      self.data_frame = pd.DataFrame(columns = ['车次','站点','时间','历时','商务座','一等座','二等座','高级软卧','一等软卧','动卧','硬卧','软座','硬座','无座','其他'])
      # 更换头部
      self.user_agent = (
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36'
    )
         
    def _login(self):
      self.driver.maximize_window()
      self.options.add_argument('user-agent=%s'%self.user_agent)
      self.driver.get(self.login_url)
      self.driver.execute_script(self.script)

      WebDriverWait(self.driver , 1000).until(
                EC.url_to_be(self.init_url)
                )
      print('登陆成功!!')
      
    def _wait_input(self):
      self.from_station = input('出发地:')
      self.to_station = input('目的地:')
      #标准时间格式:yyyy-mm-dd
      self.depart_time = input('出发日(注意格式:yyyy-mm-dd):')
      #self.passengers = input('乘客姓名(如果有多个用,隔开)').split(',')
      #self.trains = input('输入列车车次(有多个用,隔开):').split(',')
      
    def _get_pos(self , seat_type):
      pos = None
      for row_num,rows in self.data_frame.iterrows():
            ifself.target_train.upper() in rows.upper() and rows != '无' and rows != '候补' and rows != '--':
                print('当前是否有票:',rows)
                pos =str(2 * (row_num + 1) - 1)
      return pos
   
    def _get_data(self):
      #清空数据
      self.data_frame.drop(self.data_frame.index,inplace=True)
      #获取可预订数据
      td1 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td/div/div[@class="train"]/div')
      td2 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td/div/div[@class="cdz"]')
      td3 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td/div/div[@class="cds"]')
      td4 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td/div/div[@class="ls"]')
      td5 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      td6 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      td7 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      td8 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      td9 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      td10 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      td11 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      td12 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      td13 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      td14 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      td15 = self.driver.find_elements_by_xpath('//tbody[@id="queryLeftTable"]/tr/td')
      for td1,td2,td3,td4,td5,td6,td7,td8,td9,td10,td11,td12,td13,td14,td15in zip(td1,td2,td3,td4,td5,td6,td7,td8,td9,td10,td11,td12,td13,td14,td15):
                list_tr =
                index_size = self.data_frame.index.size
                self.data_frame.loc = list_tr
      pd.set_option('display.max_columns', None) #设置显示的最大列数参数
      pd.set_option('display.max_rows', None) #设置显示的最大的行数参数
      pd.set_option('display.width',100) #设置显示的宽度
      
    #查询网页元素是否存在
    def isElementExist(self, value_type , element):
      flag=True
      browser=self.driver
      try:
            if value_type == 'id':
                browser.find_element_by_id(element)
            elif value_type == 'xpath':
                browser.find_element_by_xpath(element)
            return flag
      except:
            flag=False
            return flag
         
    def _clickWarningWindow(self):
         if self.isElementExist('id','qd_closeDefaultWarningWindowDialog_id' ):
                  self.driver.find_element_by_id('qd_closeDefaultWarningWindowDialog_id').click()
      
    def _order_tickets(self):
      self.driver.get(self.search_url)
      self._clickWarningWindow()
      

      #等待出发地输入正确
      WebDriverWait(self.driver , 1000).until(
                EC.text_to_be_present_in_element_value((By.ID , 'fromStationText') , self.from_station)
                )
      #等待目的地输入正确
      WebDriverWait(self.driver , 1000).until(
                EC.text_to_be_present_in_element_value((By.ID , 'toStationText') , self.to_station)
                )
      #等待出发日期正确
      WebDriverWait(self.driver , 1000).until(
                EC.text_to_be_present_in_element_value((By.ID , 'train_date') , self.depart_time)
                )
      #等待查询按钮是否能够呗点击
      WebDriverWait(self.driver , 1000).until(
                EC.element_to_be_clickable(('id' , 'query_ticket'))
                )
      searchBtn = self.driver.find_element_by_id('query_ticket')
      searchBtn.click()
      #print('====正在打印车次信息====')
      time.sleep(5)
      self._get_data()
      print(self.data_frame)
      self.target_train = input('请输入需要选择的车次:')
      seat_type = input('请输入需要选择的作为类别:')
      
      #print(self._get_pos(seat_type))
      #self.driver.refresh()
      #如果没有找到车次,循环获取订单页面
      while self._get_pos(seat_type) isNone:
            WebDriverWait(self.driver , 1000).until(
                EC.element_to_be_clickable(('id' , 'query_ticket'))
                )
            searchBtn = self.driver.find_element_by_id('query_ticket')
            searchBtn.click()
            self._clickWarningWindow()
            time.sleep(10)
            self._get_data()
      print(self.data_frame)
         #点击对应车次预定按钮
      self.driver.find_element_by_xpath('//tbody[@id="queryLeftTable"]/tr[' + self._get_pos(seat_type) +']/td/a[@class="btn72"]').click()
      #车次时间较近
      self._clickWarningWindow()
         
      #等待页面跳转到订单界面
      time.sleep(5)
      #输入乘车人
      Passenger = input('请输入乘车人姓名,如有多个按逗号隔开:').split(',')
      li_list = self.driver.find_elements_by_xpath('//*[@id="normal_passenger_id"]/li')
      for index , value in enumerate(li_list):
            if value.text in Passenger:
                self.driver.find_element_by_xpath('//*[@id="normal_passenger_id"]/li['+ str(index + 1) +']/label').click()
                self._clickWarningWindow()
      #提交订单
      self.driver.find_element_by_id('submitOrder_id').click()
      time.sleep(5)
      #选择座位位置//*[@id="1F"]
      ''' 鼠标悬停
      element = self.driver.find_element_by_xpath('//*[@id="'+ seat_num.upper() +'"]')
      ActionChains(self.driver).move_to_element(element).perform()
      '''
      seat_list = input('请输入需要选择的座位号:').split(',')
      if seat_list != []:
            for seat_num in seat_list:
                print(seat_num.upper())
                element = self.driver.find_element_by_xpath('//*[@id="'+ seat_num.upper() +'"]')
                self.driver.execute_script("arguments.click", element)
      
      #self.driver.find_element_by_id('qr_submit_id').click()
      
    def run(self):
      self._wait_input()
      self._login()
      self._order_tickets()
      
if __name__ == '__main__':
    spider = get_tickets()
    spider.run()
    #spider.driver.quit()

Hmily 发表于 2022-11-15 11:42

抱歉,未能达到申请要求,申请不通过,可以关注论坛官方微信(吾爱破解论坛),等待开放注册通知。
页: [1]
查看完整版本: 申请会员ID: xiaopacai2