Python實現全自動購買火車票!搶票回家過年咯

本文的文字及圖片來源於網絡,僅供學習、交流使用,不具備任何商業用途,若有問題請及時聯繫咱們以做處理

這個是實現結果,由於一天只能取消三次,因此最後一步點擊確認被我註釋了
1.首先實現使用selenium登錄12306

 這裏實現了使用selenium登錄12306,實現全自動登錄12306連接
2.根據上面實現登錄後,實現購買火車票還需兩步

這裏只進行了二等座的查詢和購票,想要買其餘的本身也能夠進行修改 1.進行車票的查詢 這裏面須要注意的是在輸入目的地和起始地時須要先click一下文本框browser.find_element_by_id(‘fromStationText’).click() 否則輸入的地址無效 還有將日期的只讀屬性去掉

def search_railway_ticket(fromstation,tostation,train_date):
    # 火車票頁面查詢url
    search_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc'
    # 轉到查詢車次頁面
    browser.get(search_url)
    time.sleep(2)
    #輸入出發地
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'fromStationText'))
    )
    #先點擊一下
    browser.find_element_by_id('fromStationText').click()
    browser.find_element_by_id('fromStationText').send_keys(fromstation)
    browser.find_element_by_id('fromStationText').send_keys(Keys.ENTER)
    time.sleep(1)
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'toStationText'))
    )
    #輸入目的地
    browser.find_element_by_id('toStationText').click()
    browser.find_element_by_id('toStationText').send_keys(tostation)
    browser.find_element_by_id('toStationText').send_keys(Keys.ENTER)
    time.sleep(5)
    #將日期的只讀屬性去掉
    js = 'document.getElementById("train_date").removeAttribute("readonly")'
    browser.execute_script(js)
    #去掉本來的時間
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'train_date'))
    )
    browser.find_element_by_id("train_date").clear()
    #輸入出發時間
    browser.find_element_by_id('train_date').send_keys(train_date)
    # 等待查詢按鈕是否可用
    WebDriverWait(browser, 1000).until(
        EC.element_to_be_clickable((By.ID, 'query_ticket'))
    )
    searBtn = browser.find_element_by_id('query_ticket')
    searBtn.click()
    print('點擊按鈕')

2.購買火車票 在這個函數中須要注意的是最好把最後一步註釋掉 browser.find_element_by_id(‘qr_submit_id’).click() 由於一天只能取消3次訂單

def buy_ticket(fromstation,tostation,train_date,train_number,passenger):
 
    #查詢火車票
    search_railway_ticket(fromstation,tostation,train_date)
    time.sleep(5)
    #獲取每個車次的信息
    tr_list = browser.find_elements_by_xpath('.//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
    for tr in tr_list:
        #獲取車次號
        number = tr.find_element_by_class_name('number').text
        if number in  train_number:
            #獲取是否還有票
            left_ticket = tr.find_element_by_xpath('./td[4]').text
            if left_ticket =='有'or left_ticket.isdigit:
                print(f'{number}還有票')
                #點擊預訂
                orderBtn = tr.find_element_by_class_name('btn72')
                orderBtn.click()
                time.sleep(5)
                #獲取12306中乘客的信息
                passenger_list = browser.find_elements_by_xpath('//*[@id="normal_passenger_id"]/li')
                for li in passenger_list:
                    name = li.find_element_by_xpath('./label').text
                    print(name)
                    #配對12306人名
                    if name == passenger:
                        li.find_element_by_tag_name('input').click()
                #提交訂單
                submit = browser.find_element_by_id('submitOrder_id')
                submit.click()
                WebDriverWait(browser, 1000).until(
                    EC.element_to_be_clickable((By.ID, 'qr_submit_id'))
                )
                #一天只能取消3次 因此最好把最後一步註釋了
                browser.find_element_by_id('qr_submit_id').click()
                print('已經提交訂單')
                break

下面是源代碼

測試的時候能夠把#click_captcha()這個點擊驗證碼的去掉本身手動點擊,這樣就不用扣超級鷹的積分(有錢的話當我沒說),留下了貧窮的淚水。

from selenium import webdriver
from selenium.webdriver import Actionchains
import time
from PIL import Image
import requests
from hashlib import md5
from selenium.webdriver import ChromeOptions
#驗證碼識別處理
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
 
class Chaojiying_Client(object):
 
    def __init__(self, username, password, soft_id):
        self.username = username
        password =  password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }
 
    def PostPic(self, im, codetype):
        """
        im: 圖片字節
        codetype: 題目類型 參考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
        return r.json()
 
    def ReportError(self, im_id):
        """
        im_id:報錯題目的圖片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()
 
def login(username,password):
    # 填寫帳號密碼
    browser.find_element_by_id('J-userName').send_keys(username)
    browser.find_element_by_id('J-password').send_keys(password)
 
    # 獲取驗證碼
    get_captcha()
 
    # 填寫驗證碼
    click_captcha()
 
    #點擊登陸
    time.sleep(4)
    browser.find_element_by_id('J-login').click()
    time.sleep(4)
 
    #滑動驗證碼
    slider()
 
    print('成功登錄')
    time.sleep(5)
 
def slider():
    #滑動驗證碼
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.XPATH, '//*[@id="nc_1_n1z"]'))
    )
    span = browser.find_element_by_xpath('//*[@id="nc_1_n1z"]')
    # 對div_tag進行滑動操做
    action = Actionchains(browser)
    # 點擊長按指定的標籤
    action.click_and_hold(span).perform()
    action.drag_and_drop_by_offset(span, 400, 0).perform()
 
def click_captcha():
    # 獲取驗證碼須要的爲點擊位置
    chaojiying = Chaojiying_Client('本身的用戶名', '密碼', '軟件id')  # 用戶中心>>軟件ID 生成一個替換 96001
    im = open('./captcha.png', 'rb').read()  # 本地圖片文件路徑 來替換 a.jpg 有時WIN系統需要//
    location = chaojiying.PostPic(im, 9004)['pic_str']  # 1902 驗證碼類型  官方網站>>價格體系 3.4+版 print 後要加()
    print(chaojiying.PostPic(im, 9004))
    # 將位置進行分割成    [  [  ], [ ], [ ]  ]類型
    location_list = [i.split(',') for i in location.split('|')]
    for l in location_list:
        x = l[0]
        y = l[1]
        Actionchains(browser).move_to_element_with_offset(browser.find_element_by_class_name('login-pwd-code'), int(x),int(y)).click().perform()
        time.sleep(0.5)
 
def get_captcha():
    # 獲取網頁的截圖
    allscreen = browser.get_screenshot_as_file('allscreen.png')
    # 獲取captcha
    captcha = browser.find_element_by_class_name('login-pwd-code')
    # 獲取captcha的左上角位置
    location = captcha.location
    # 獲取圖片大小
    size = captcha.size
    # 裁取captcha
    rangle = (location['x'],location['y'],(location['x']+size['width']),(location['y']+size['height']))
    i = Image.open('./allscreen.png')
    captcha_img = './captcha.png'
    frame = i.crop(rangle)
    frame.save(captcha_img)
 
def buy_ticket(fromstation,tostation,train_date,train_number,passenger):
 
    #查詢火車票
    search_railway_ticket(fromstation,tostation,train_date)
    time.sleep(5)
    tr_list = browser.find_elements_by_xpath('.//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
    for tr in tr_list:
        number = tr.find_element_by_class_name('number').text
        if number in  train_number:
            left_ticket = tr.find_element_by_xpath('./td[4]').text
            if left_ticket =='有'or left_ticket.isdigit:
                print(f'{number}還有票')
                orderBtn = tr.find_element_by_class_name('btn72')
                orderBtn.click()
                time.sleep(5)
                passenger_list = browser.find_elements_by_xpath('//*[@id="normal_passenger_id"]/li')
                for li in passenger_list:
                    name = li.find_element_by_xpath('./label').text
                    if name == passenger:
                        li.find_element_by_tag_name('input').click()
                submit = browser.find_element_by_id('submitOrder_id')
                submit.click()
                WebDriverWait(browser, 1000).until(
                    EC.element_to_be_clickable((By.ID, 'qr_submit_id'))
                )
                #一天只能取消3次 因此把最後一步註釋了
                # browser.find_element_by_id('qr_submit_id').click()
                print('已經提交訂單')
                break
 
def search_railway_ticket(fromstation,tostation,train_date):
    # 火車票頁面查詢url
    search_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc'
    # 轉到查詢車次頁面
    browser.get(search_url)
    time.sleep(2)
    #輸入出發地
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'fromStationText'))
    )
    #先點擊一下
    browser.find_element_by_id('fromStationText').click()
    browser.find_element_by_id('fromStationText').send_keys(fromstation)
    browser.find_element_by_id('fromStationText').send_keys(Keys.ENTER)
    time.sleep(1)
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'toStationText'))
    )
    #輸入目的地
    browser.find_element_by_id('toStationText').click()
    browser.find_element_by_id('toStationText').send_keys(tostation)
    browser.find_element_by_id('toStationText').send_keys(Keys.ENTER)
    time.sleep(5)
    #將日期的只讀屬性去掉
    js = 'document.getElementById("train_date").removeAttribute("readonly")'
    browser.execute_script(js)
    #去掉本來的時間
    WebDriverWait(browser, 1000).until(
        EC.presence_of_element_located((By.ID, 'train_date'))
    )
    browser.find_element_by_id("train_date").clear()
    #輸入出發時間
    browser.find_element_by_id('train_date').send_keys(train_date)
    # 等待查詢按鈕是否可用
    WebDriverWait(browser, 1000).until(
        EC.element_to_be_clickable((By.ID, 'query_ticket'))
    )
    searBtn = browser.find_element_by_id('query_ticket')
    searBtn.click()
    print('點擊按鈕')
 
if __name__ == '__main__':
    option = ChromeOptions()  # 實例化一個ChromeOptions對象
    option.add_experimental_option('excludeSwitches', ['enable-automation'])  # 以鍵值對的形式加入參數
    option.add_experimental_option('useAutomationExtension', False)
 
    browser = webdriver.Chrome(options=option)
    # 獲取響應
    browser.get('https://kyfw.12306.cn/otn/resources/login.html')
    script = 'Object.defineProperty(navigator,"webdriver",{get:()=>undefined,});'
    browser.execute_script(script)
    browser.maximize_window()
    time.sleep(1)
 
    # 點擊帳號登錄
    browser.find_element_by_class_name('login-hd-account').click()
    #登錄12306的帳號密碼
    login('用戶名','密碼')
    time.sleep(4)
    #例buy_ticket('南昌','撫州北','2020-12-15','D2241','xx')
    buy_ticket('起始地','目的地','出發日期','車次','姓名')

想要獲取更多Python學習資料能夠加
QQ:2955637827私聊
或加Q羣630390733
你們一塊兒來學習討論吧!
php

相關文章
相關標籤/搜索