Python + Splinter 12306搶票

臨近春節和期末放假,很多小夥伴也開始關注起來了12306的放票與搶票,學習python之餘,敲一個小的demo,如果能幫到人成功搶到票,那便是最好不過的了。這個小的腳本完成過程中,做了很多的調試,力求滿足所有人的條件。但是沒有在關鍵搶票環時間點拿出來使用過,所以如果有人能試用下,記得留言給我反饋,感謝!
  其實這個腳本就是模擬的鼠標點擊與鍵盤輸入而已,原理很簡單,但是卻從輸入到點擊都提升了很多檔次,尤其是輸入。還有就是在搶票開始前幾分鐘就可以打開腳本,他會一直檢測你需要的車次與刷新界面,直到官方開放搶票接口的那一刻,都在不停檢測。

實現步驟

  1. 配置python + splinter環境,本人本次使用的是python2.7 + splinter0.7.7,splinter直接pip install即可。
  2. 瀏覽器 +WebDriver。建議Chrome + ChromeDriver。由於我本機Chrome位置移動最後未能識別到,索性就使用了splinter默認的瀏覽器Firefox + FirefoxDriver 。
  3. Chrome瀏覽器可自行下載,附上[瀏覽器驅動ChromeDriver]。(http://npm.taobao.org/mirrors/chromedriver/ “瀏覽器驅動ChromeDriver”)鏈接。
  4. 瀏覽器驅動下載下來是一個.exe執行文件,將其放在你本機python環境的目錄下,也就是跟python.exe同一目錄。要是找不到你的python環境,可以去環境變量中尋找。

注意點

  1. Chrome 與驅動ChromeDriver 應該兼容,與splinter也應該兼容。我這裏均使用的最新版本,打開上面的ChromeDriver網址,找到LATEST_RELEASE,下載並打開,會顯示最新的ChromeDriver是哪個版本,然後下載最新版中的chromedriver_win32.zip,Mac跟Linux當然對應其他的驅動.zip包)。
  2. 如果安裝完畢後會報錯,可能的原因有:版本不對不兼容;python環境不對,anaconda多環境的要注意下;驅動安裝位置不對;瀏覽器的問題,試試重裝最新版等。

半自動搶票代碼實現

具體的實現邏輯比較簡單,是splinter的基礎練手內容,畢竟是初學者,在這裏我就給大家講一下我實現的搶票代碼的使用方式,運行過後大家也可以試着改成自己想要的樣子。

  1. 上述環境等操作完成。
  2. 根據自己的情況修改代碼中的賬號密碼等數值,(雖然是python的初學者,但是沒有將其寫成一個接口,深感羞愧)。
  3. 運行代碼,唯一需要做的就是選擇登錄程序中的驗證碼,點擊登錄。如果自身瀏覽器比較慢的話,可能在個人界面卡一下,我並沒有在代碼上優化這一點,所以有的時候可能需要你手動點擊一下車票預訂(在後期可以試着寫一下對驗證碼的識別,不過應該是比較難的,畢竟360在這上面花了那麼多功夫,到時候再看)。
  4. 實現的功能有:查詢,預定,是否學生票,爲朋友預定,他們是否學生票。最後自行選座位之後,點擊最後一個提交按鈕。
    5.爲什麼是說半自動搶票呢?不是在於最後一步的自己選座位(我給選也不太好),而是在於要自己去找對應車站的cookie信息,比如重慶——濰坊,重慶的cookie是 %u91CD%u5E86%2CCQW ,濰坊的cookie是 %u6F4D%u574A%2CWFK 。怎麼找呢?步驟如下:
  • Chrome打開12306官網的查詢餘票界面
  • 選中出發點,或者目的地,按下F12,找到Application,點擊Cookies看到的name/value就是對應的站點cookie信息。如圖,框後對應的value就是對應的cookie。

詳細代碼

# -*- coding: utf-8 -*-
from splinter.browser import Browser
from time import sleep

# 以下是你需要根據自己情況修改的數值
# 可以提前試一下,免得到時候因爲自己的輸入或者網絡太慢/瀏覽器太慢出現問題
# 搶到搶不到很大程度上依賴於機器和網絡的好壞
my_name = "孫良龍(學生)"               # 你要搶票的人的名字,注意格式。當然名字要提前在12306上存檔的。
myfriends_name1 = "XXX(學生)"          # 如果同時也給朋友搶的話,可以修改這一欄,沒有的話不要修改,修改會報錯
myfriends_name2 = "XXX(學生)"          # 如果同時也給朋友搶的話,可以修改這一欄,沒有的話不要修改,修改會報錯
myfriends_name3 = "XXX(學生)"          # 如果同時也給朋友搶的話,可以修改這一欄,沒有的話不要修改,修改會報錯
ticket_type = "普通票"                 # 你是要買學生票還是普通票
friend_ticket_type1 = "學生票"                 # 你的朋友1是要買學生票還是普通票
friend_ticket_type2 = "學生票"                 # 你的朋友2是要買學生票還是普通票
friend_ticket_type3 = "學生票"                 # 你的朋友3是要買學生票還是普通票
my_username = "[email protected]"  # 換成你的用戶名
my_password = "sun651066702"  # 換成你的密碼
my_time = "2018-02-06"  # 選擇要搶票的日期,就算12306上面不可選也可以填 注意格式一定要與示例相同
train_num = 5        # 選擇車次,按照在12306上面的次序,比如上海—太原的Z196,train_num爲6,起始爲0
train_from = "%u7AE0%u4E18%2CZTK"      # 選擇你的始發站,這是示例重慶
train_to = "%u6F4D%u574A%2CWFK"        # 選擇你的終點站,這是示例濰坊
# 起始地址的cookies值要自己去找,尋找你的始終站的方法:http://www.sunlianglong.cn/index.php/2018/01/07/python01/




# 12306
login_url = "https://kyfw.12306.cn/otn/login/init"
my_url = "https://kyfw.12306.cn/otn/index/initMy12306"
ticket_url = "https://kyfw.12306.cn/otn/leftTicket/init"
buy = "https://kyfw.12306.cn/otn/confirmPassenger/initDc"
driver = Browser()
driver.visit(login_url)
# username password
driver.fill("loginUserDTO.user_name", my_username)
driver.fill("userDTO.password", my_password)
print(u"等待驗證碼,自行輸入...")

while True:
    if driver.url != my_url:
        sleep(1)
    else:
        break

driver.find_by_text(u"車票預訂").first.click()

while True:
    if driver.url != ticket_url:
        sleep(1)
    else:
        break

# To determine if a single interface has been entered
flag = 0
while flag == 0:
    # 填寫出發點目的地
    driver.cookies.add({u"_jc_save_fromStation": train_from})
    driver.cookies.add({"_jc_save_fromDate": my_time})
    driver.cookies.add({u"_jc_save_toStation": train_to})
    # loading
    driver.reload()
    order = 1
    if order != 0:
        while True:
            driver.find_by_text(u"查詢").click()
            try:
                noDate2 = driver.find_by_id("qd_closeDefaultWarningWindowDialog_id")
                if noDate2 == []:
                    wait = driver.find_by_text(u"預訂")[train_num]
                    if wait == []:
                        break
                    else:
                        wait.click()
                    # To determine whether a successful reservation
                    if driver.url != buy:
                        order = order-1
                else:
                    break
            except Exception as e:
                print u"還沒開始預訂"
                continue
            if order == 0:
                flag = 1
                break

print flag
if True:
    # Choose yourself
    driver.find_by_text(my_name).click()
    stu_toast = driver.find_by_id("dialog_xsertcj_ok")
    if stu_toast != [] :
        if ticket_type == "學生票":
            stu_toast.click()
        else:
            driver.find_by_id("dialog_xsertcj_cancel").click()
    # Choose friend 1
    if myfriends_name1 != "XXX(學生)":
        driver.find_by_text(myfriends_name1).click()
        stu_toast1 = driver.find_by_id("dialog_xsertcj_ok")
        if stu_toast1 != []:
            if friend_ticket_type1 == "學生票":
                stu_toast1.click()
            else:
                driver.find_by_id("dialog_xsertcj_cancel").click()

    # Choose friend 2
    if myfriends_name2 != "XXX(學生)":
        driver.find_by_text(myfriends_name2).click()
        stu_toast2 = driver.find_by_id("dialog_xsertcj_ok")
        if stu_toast2 != []:
            if friend_ticket_type2 == "學生票":
                stu_toast2.click()
            else:
                driver.find_by_id("dialog_xsertcj_cancel").click()

    # Choose friend 3
    if myfriends_name3 != "XXX(學生)":
        driver.find_by_text(myfriends_name3).click()
        stu_toast3 = driver.find_by_id("dialog_xsertcj_ok")
        if stu_toast3 != []:
            if friend_ticket_type3 == "學生票":
                stu_toast3.click()
            else:
                driver.find_by_id("dialog_xsertcj_cancel").click()

while True:
    driver.find_by_text(u"提交訂單").click()
    if driver.url != buy:
        break

print "success!"


發佈了35 篇原創文章 · 獲贊 44 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章