Python实现全自动购买火车票!抢票回家过年咯

开发 后端
这里只进行了二等座的查询和购票,想要买其他的自己也可以进行修改 1.进行车票的查询 这里面需要注意的是在输入目的地和起始地时需要先click一下文本框browser.find_element_by_id(‘fromStationText’).click() 不然输入的地址无效 还有将日期的只读属性去掉。

这个是实现结果,因为一天只能取消三次,所以最后一步点击确认被我注释了。 

Python实现全自动购买火车票!抢票回家过年咯

1.首先实现使用selenium登陆12306

关于使用selenium实现12306登陆可以看我的另一篇文章 这里实现了使用selenium登陆12306,这次是基于上次的代码进行修改实现全自动购买车票的 实现全自动登陆12306链接。

2.根据上面实现登陆后,实现购买火车票还需两步

这里只进行了二等座的查询和购票,想要买其他的自己也可以进行修改 1.进行车票的查询 这里面需要注意的是在输入目的地和起始地时需要先click一下文本框browser.find_element_by_id(‘fromStationText’).click() 不然输入的地址无效 还有将日期的只读属性去掉。 

  1. def search_railway_ticket(fromstation,tostation,train_date): 
  2.     # 火车票页面查询url 
  3.     search_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc' 
  4.     # 转到查询车次页面 
  5.     browser.get(search_url) 
  6.     time.sleep(2) 
  7.     #输入出发地 
  8.     WebDriverWait(browser, 1000).until( 
  9.         EC.presence_of_element_located((By.ID, 'fromStationText')) 
  10.     ) 
  11.     #先点击一下 
  12.     browser.find_element_by_id('fromStationText').click() 
  13.     browser.find_element_by_id('fromStationText').send_keys(fromstation) 
  14.     browser.find_element_by_id('fromStationText').send_keys(Keys.ENTER) 
  15.     time.sleep(1) 
  16.     WebDriverWait(browser, 1000).until( 
  17.         EC.presence_of_element_located((By.ID, 'toStationText')) 
  18.     ) 
  19.     #输入目的地 
  20.     browser.find_element_by_id('toStationText').click() 
  21.     browser.find_element_by_id('toStationText').send_keys(tostation) 
  22.     browser.find_element_by_id('toStationText').send_keys(Keys.ENTER) 
  23.     time.sleep(5) 
  24.     #将日期的只读属性去掉 
  25.     js = 'document.getElementById("train_date").removeAttribute("readonly")' 
  26.     browser.execute_script(js) 
  27.     #去掉原本的时间 
  28.     WebDriverWait(browser, 1000).until( 
  29.         EC.presence_of_element_located((By.ID, 'train_date')) 
  30.     ) 
  31.     browser.find_element_by_id("train_date").clear() 
  32.     #输入出发时间 
  33.     browser.find_element_by_id('train_date').send_keys(train_date) 
  34.     # 等待查询按钮是否可用 
  35.     WebDriverWait(browser, 1000).until( 
  36.         EC.element_to_be_clickable((By.ID, 'query_ticket')) 
  37.     ) 
  38.     searBtn = browser.find_element_by_id('query_ticket'
  39.     searBtn.click() 
  40.     print('点击按钮'

2.购买火车票 在这个函数中需要注意的是最好把最后一步注释掉 browser.find_element_by_id(‘qr_submit_id’).click() 因为一天只能取消3次订单。 

  1. def buy_ticket(fromstation,tostation,train_date,train_number,passenger): 
  2.  
  3.     #查询火车票 
  4.     search_railway_ticket(fromstation,tostation,train_date) 
  5.     time.sleep(5) 
  6.     #获取每一个车次的信息 
  7.     tr_list = browser.find_elements_by_xpath('.//tbody[@id="queryLeftTable"]/tr[not(@datatran)]'
  8.     for tr in tr_list: 
  9.         #获取车次号 
  10.         number = tr.find_element_by_class_name('number').text 
  11.         if number in  train_number: 
  12.             #获取是否还有票 
  13.             left_ticket = tr.find_element_by_xpath('./td[4]').text 
  14.             if left_ticket =='有'or left_ticket.isdigit: 
  15.                 print(f'{number}还有票'
  16.                 #点击预订 
  17.                 orderBtn = tr.find_element_by_class_name('btn72'
  18.                 orderBtn.click() 
  19.                 time.sleep(5) 
  20.                 #获取12306中乘客的信息 
  21.                 passenger_list = browser.find_elements_by_xpath('//*[@id="normal_passenger_id"]/li'
  22.                 for li in passenger_list: 
  23.                     name = li.find_element_by_xpath('./label').text 
  24.                     print(name
  25.                     #配对12306人名 
  26.                     if name == passenger: 
  27.                         li.find_element_by_tag_name('input').click() 
  28.                 #提交订单 
  29.                 submit = browser.find_element_by_id('submitOrder_id'
  30.                 submit.click() 
  31.                 WebDriverWait(browser, 1000).until( 
  32.                     EC.element_to_be_clickable((By.ID, 'qr_submit_id')) 
  33.                 ) 
  34.                 #一天只能取消3次 所以最好把最后一步注释了 
  35.                 browser.find_element_by_id('qr_submit_id').click() 
  36.                 print('已经提交订单'
  37.                 break 

下面是源代码

测试的时候可以把#click_captcha()这个点击验证码的去掉自己手动点击,这样就不用扣超级鹰的积分(有钱的话当我没说),留下了贫穷的泪水。 

  1. from selenium import webdriver 
  2. from selenium.webdriver import Actionchains 
  3. import time 
  4. from PIL import Image 
  5. import requests 
  6. from hashlib import md5 
  7. from selenium.webdriver import ChromeOptions 
  8. #验证码识别处理 
  9. from selenium.webdriver.common.keys import Keys 
  10. from selenium.webdriver.common.by import By 
  11. from selenium.webdriver.support.wait import WebDriverWait 
  12. from selenium.webdriver.support import expected_conditions as EC 
  13.  
  14. class Chaojiying_Client(object): 
  15.  
  16.     def __init__(self, username, password, soft_id): 
  17.         self.username = username 
  18.         password =  password.encode('utf8'
  19.         self.password = md5(password).hexdigest() 
  20.         self.soft_id = soft_id 
  21.         self.base_params = { 
  22.             'user': self.username, 
  23.             'pass2': self.password
  24.             'softid': self.soft_id, 
  25.         } 
  26.         self.headers = { 
  27.             'Connection''Keep-Alive'
  28.             'User-Agent''Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)'
  29.         } 
  30.  
  31.     def PostPic(self, im, codetype): 
  32.         ""
  33.         im: 图片字节 
  34.         codetype: 题目类型 参考 http://www.chaojiying.com/price.html 
  35.         ""
  36.         params = { 
  37.             'codetype': codetype, 
  38.         } 
  39.         params.update(self.base_params) 
  40.         files = {'userfile': ('ccc.jpg', im)} 
  41.         r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers) 
  42.         return r.json() 
  43.  
  44.     def ReportError(self, im_id): 
  45.         ""
  46.         im_id:报错题目的图片ID 
  47.         ""
  48.         params = { 
  49.             'id': im_id, 
  50.         } 
  51.         params.update(self.base_params) 
  52.         r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers) 
  53.         return r.json() 
  54.  
  55. def login(username,password): 
  56.     # 填写账号密码 
  57.     browser.find_element_by_id('J-userName').send_keys(username) 
  58.     browser.find_element_by_id('J-password').send_keys(password
  59.  
  60.     # 获取验证码 
  61.     get_captcha() 
  62.  
  63.     # 填写验证码 
  64.     click_captcha() 
  65.  
  66.     #点击登录 
  67.     time.sleep(4) 
  68.     browser.find_element_by_id('J-login').click() 
  69.     time.sleep(4) 
  70.  
  71.     #滑动验证码 
  72.     slider() 
  73.  
  74.     print('成功登陆'
  75.     time.sleep(5) 
  76.  
  77. def slider(): 
  78.     #滑动验证码 
  79.     WebDriverWait(browser, 1000).until( 
  80.         EC.presence_of_element_located((By.XPATH, '//*[@id="nc_1_n1z"]')) 
  81.     ) 
  82.     span = browser.find_element_by_xpath('//*[@id="nc_1_n1z"]'
  83.     # 对div_tag进行滑动操作 
  84.     action = Actionchains(browser) 
  85.     # 点击长按指定的标签 
  86.     action.click_and_hold(span).perform() 
  87.     action.drag_and_drop_by_offset(span, 400, 0).perform() 
  88.  
  89. def click_captcha(): 
  90.     # 获取验证码需要的为点击位置 
  91.     chaojiying = Chaojiying_Client('自己的用户名''密码''软件id')  # 用户中心>>软件ID 生成一个替换 96001 
  92.     im = open('./captcha.png''rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要// 
  93.     location = chaojiying.PostPic(im, 9004)['pic_str']  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加() 
  94.     print(chaojiying.PostPic(im, 9004)) 
  95.     # 将位置进行分割成    [  [  ], [ ], [ ]  ]类型 
  96.     location_list = [i.split(','for i in location.split('|')] 
  97.     for l in location_list: 
  98.         x = l[0] 
  99.         y = l[1] 
  100.         Actionchains(browser).move_to_element_with_offset(browser.find_element_by_class_name('login-pwd-code'), int(x),int(y)).click().perform() 
  101.         time.sleep(0.5) 
  102.  
  103. def get_captcha(): 
  104.     # 获取网页的截图 
  105.     allscreen = browser.get_screenshot_as_file('allscreen.png'
  106.     # 获取captcha 
  107.     captcha = browser.find_element_by_class_name('login-pwd-code'
  108.     # 获取captcha的左上角位置 
  109.     location = captcha.location 
  110.     # 获取图片大小 
  111.     size = captcha.size 
  112.     # 裁取captcha 
  113.     rangle = (location['x'],location['y'],(location['x']+size['width']),(location['y']+size['height'])) 
  114.     i = Image.open('./allscreen.png'
  115.     captcha_img = './captcha.png' 
  116.     frame = i.crop(rangle) 
  117.     frame.save(captcha_img) 
  118.  
  119. def buy_ticket(fromstation,tostation,train_date,train_number,passenger): 
  120.  
  121.     #查询火车票 
  122.     search_railway_ticket(fromstation,tostation,train_date) 
  123.     time.sleep(5) 
  124.     tr_list = browser.find_elements_by_xpath('.//tbody[@id="queryLeftTable"]/tr[not(@datatran)]'
  125.     for tr in tr_list: 
  126.         number = tr.find_element_by_class_name('number').text 
  127.         if number in  train_number: 
  128.             left_ticket = tr.find_element_by_xpath('./td[4]').text 
  129.             if left_ticket =='有'or left_ticket.isdigit: 
  130.                 print(f'{number}还有票'
  131.                 orderBtn = tr.find_element_by_class_name('btn72'
  132.                 orderBtn.click() 
  133.                 time.sleep(5) 
  134.                 passenger_list = browser.find_elements_by_xpath('//*[@id="normal_passenger_id"]/li'
  135.                 for li in passenger_list: 
  136.                     name = li.find_element_by_xpath('./label').text 
  137.                     if name == passenger: 
  138.                         li.find_element_by_tag_name('input').click() 
  139.                 submit = browser.find_element_by_id('submitOrder_id'
  140.                 submit.click() 
  141.                 WebDriverWait(browser, 1000).until( 
  142.                     EC.element_to_be_clickable((By.ID, 'qr_submit_id')) 
  143.                 ) 
  144.                 #一天只能取消3次 所以把最后一步注释了 
  145.                 # browser.find_element_by_id('qr_submit_id').click() 
  146.                 print('已经提交订单'
  147.                 break 
  148.  
  149. def search_railway_ticket(fromstation,tostation,train_date): 
  150.     # 火车票页面查询url 
  151.     search_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc' 
  152.     # 转到查询车次页面 
  153.     browser.get(search_url) 
  154.     time.sleep(2) 
  155.     #输入出发地 
  156.     WebDriverWait(browser, 1000).until( 
  157.         EC.presence_of_element_located((By.ID, 'fromStationText')) 
  158.     ) 
  159.     #先点击一下 
  160.     browser.find_element_by_id('fromStationText').click() 
  161.     browser.find_element_by_id('fromStationText').send_keys(fromstation) 
  162.     browser.find_element_by_id('fromStationText').send_keys(Keys.ENTER) 
  163.     time.sleep(1) 
  164.     WebDriverWait(browser, 1000).until( 
  165.         EC.presence_of_element_located((By.ID, 'toStationText')) 
  166.     ) 
  167.     #输入目的地 
  168.     browser.find_element_by_id('toStationText').click() 
  169.     browser.find_element_by_id('toStationText').send_keys(tostation) 
  170.     browser.find_element_by_id('toStationText').send_keys(Keys.ENTER) 
  171.     time.sleep(5) 
  172.     #将日期的只读属性去掉 
  173.     js = 'document.getElementById("train_date").removeAttribute("readonly")' 
  174.     browser.execute_script(js) 
  175.     #去掉原本的时间 
  176.     WebDriverWait(browser, 1000).until( 
  177.         EC.presence_of_element_located((By.ID, 'train_date')) 
  178.     ) 
  179.     browser.find_element_by_id("train_date").clear() 
  180.     #输入出发时间 
  181.     browser.find_element_by_id('train_date').send_keys(train_date) 
  182.     # 等待查询按钮是否可用 
  183.     WebDriverWait(browser, 1000).until( 
  184.         EC.element_to_be_clickable((By.ID, 'query_ticket')) 
  185.     ) 
  186.     searBtn = browser.find_element_by_id('query_ticket'
  187.     searBtn.click() 
  188.     print('点击按钮'
  189.  
  190. if __name__ == '__main__'
  191.     option = ChromeOptions()  # 实例化一个ChromeOptions对象 
  192.     option.add_experimental_option('excludeSwitches', ['enable-automation'])  # 以键值对的形式加入参数 
  193.     option.add_experimental_option('useAutomationExtension'False
  194.  
  195.     browser = webdriver.Chrome(options=option
  196.     # 获取响应 
  197.     browser.get('https://kyfw.12306.cn/otn/resources/login.html'
  198.     script = 'Object.defineProperty(navigator,"webdriver",{get:()=>undefined,});' 
  199.     browser.execute_script(script) 
  200.     browser.maximize_window() 
  201.     time.sleep(1) 
  202.  
  203.     # 点击账号登陆 
  204.     browser.find_element_by_class_name('login-hd-account').click() 
  205.     #登陆12306的账号密码 
  206.     login('用户名','密码'
  207.     time.sleep(4) 
  208.     #例buy_ticket('南昌','抚州北','2020-12-15','D2241','xx'
  209.     buy_ticket('起始地','目的地','出发日期','车次','姓名'

 【编辑推荐】

 

责任编辑:未丽燕 来源: 今日头条
相关推荐

2018-12-29 16:24:58

Python12306火车票

2018-01-10 22:19:44

2013-01-07 17:34:47

火车票抢票浏览器

2018-01-02 09:56:04

Python12306火车票

2013-01-21 13:07:31

傲游云浏览器

2012-01-05 13:14:42

火车票

2013-01-23 11:24:57

360浏览器抢票

2011-01-28 15:48:11

Chrome插件Page Monito火车票

2016-08-31 13:26:24

PythonPython3工具

2018-01-05 09:33:10

Python火车票春运

2013-09-18 13:17:58

傲游云浏览器

2014-12-10 12:28:18

安卓市场

2015-02-11 19:39:16

114啦机票频道

2013-01-31 10:02:25

产品经理火车

2018-10-23 11:16:59

12306思路余票

2020-01-13 07:42:01

技术研发指标

2011-01-24 15:37:32

火车票

2023-09-26 12:08:20

开源python
点赞
收藏

51CTO技术栈公众号