基于Python2.7實(shí)現(xiàn)的2017年春運(yùn)搶票腳本

文章首發(fā):我的博客

又到一年一度春運(yùn)大會(huì)巴帮,2017年春運(yùn)搶火車(chē)票還是那么難间雀,各大互聯(lián)網(wǎng)公司都推出搶票服務(wù),只要加錢(qián)給服務(wù)費(fèi)就可以增加搶到票的幾率涵亏,有些代售火車(chē)票點(diǎn)宰睡,說(shuō)給100元服務(wù)費(fèi),可以幫搶到气筋,看來(lái)這水很深安鹉凇!

下面我們利用自己學(xué)的技術(shù)來(lái)自動(dòng)搶票宠默,本次腳本基于Python2.7+selenium來(lái)實(shí)現(xiàn)

首先介紹一下selenium的使用

selenium操作chrome瀏覽器需要有ChromeDriver驅(qū)動(dòng)來(lái)協(xié)助麸恍。
什么是ChromeDriver?
ChromeDriver是Chromium team開(kāi)發(fā)維護(hù)的,它是實(shí)現(xiàn)WebDriver有線(xiàn)協(xié)議的一個(gè)單獨(dú)的服務(wù)抹沪。ChromeDriver通過(guò)chrome的自動(dòng)代理框架控制瀏覽器刻肄,ChromeDriver只與12.0.712.0以上版本的chrome瀏覽器兼容。
那么要想selenium成功的操作chrome瀏覽器需要經(jīng)歷如下步驟:

  • 1融欧、下載ChromeDriver驅(qū)動(dòng)包(下載地址: http://chromedriver.storage.googleapis.com/index.htmlpath=2.7/
    注意閱讀note.txt下載與自己所使用瀏覽器一致版本的驅(qū)動(dòng)包敏弃。
  • 2、指定ChromeDriver所在位置和設(shè)置環(huán)境變量
    1)把ChromeDriver.exe放到Chrome瀏覽器的安裝位置application的目錄下
    2)通過(guò)配置ChromeDriver.exe位置到path環(huán)境變量實(shí)現(xiàn)噪馏。

實(shí)現(xiàn)思路

1.流程分析
  • 首先我們要登錄12306網(wǎng)站麦到,登錄的時(shí)候遇到很蛋疼的圖片驗(yàn)證碼,然后選擇出發(fā)地點(diǎn)和目的地點(diǎn)欠肾,接著選擇時(shí)間瓶颠,選擇車(chē)次類(lèi)型,然后查詢(xún)刺桃,再選擇班次購(gòu)票粹淋,選擇乘車(chē)人,提交訂單瑟慈,再次選擇蛋疼的圖片驗(yàn)證碼桃移。最后才會(huì)幫我們鎖住座位。** 按照這樣的流程手動(dòng)點(diǎn)擊走下來(lái)封豪,估計(jì)票都沒(méi)有了??**
2.預(yù)期實(shí)現(xiàn)目標(biāo)
  • 整個(gè)流程全自動(dòng)谴轮,實(shí)現(xiàn)自動(dòng)登錄炒瘟,自動(dòng)查詢(xún)吹埠,自動(dòng)訂票,自動(dòng)提交訂單** (暫時(shí)不實(shí)現(xiàn)自動(dòng)點(diǎn)擊驗(yàn)證碼疮装,驗(yàn)證碼成功幾率比較低缘琅,所以暫時(shí)不集成進(jìn)去,可以參考破解12306驗(yàn)證碼)**
3.實(shí)現(xiàn)代碼
  • 搶票代碼
# -*- coding: utf-8 -*-
'''2017年春運(yùn)火車(chē)票搶票
火車(chē)票預(yù)訂時(shí)間對(duì)照:
1月25日(廿八) 12月27日
1月26日(廿九) 12月28日
1月27日(除夕) 12月29日
2月1日(初四)1月3日
2月2日(初五)1月4日
2月3日(初六)1月5日
2月4日(初七)1月6日
'''

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait  # available since 2.4.0
from selenium.webdriver.support import expected_conditions as EC  # available since 2.26.0
import time

value_fromstation = '%u6DF1%u5733%u5317%2CIOQ'  # 始發(fā)站(深圳北)
value_tostation = '%u4E91%u6D6E%u4E1C%2CIXQ'  # 終點(diǎn)站(云浮東)
value_date = '2017-01-25'  # 出發(fā)時(shí)間


def login_proc(username, password):
    # 打開(kāi)登錄頁(yè)面
    sel = webdriver.Chrome('C:\Program Files (x86)\Google\Chrome\Application\chromedriver.exe')
    # sel=webdriver.Firefox()
    sel.implicitly_wait(30)
    login_url = 'https://kyfw.12306.cn/otn/login/init'
    sel.get(login_url)
    # sign in the username
    try:
        user_input = sel.find_element_by_id("username")
        user_input.clear()
        user_input.send_keys(username)
        print 'user-id write success!'
    except:
        print 'user-id write error!'
    # sign in the pasword
    try:
        pwd_input = sel.find_element_by_id("password")
        pwd_input.clear()
        pwd_input.send_keys(password)
        print 'pw write success!'
    except:
        print 'pw write error!'

    # Check for Login success
    while True:
        curpage_url = sel.current_url
        if curpage_url != login_url:
            if curpage_url[:-1] != login_url:  # choose wrong verify_pic
                print 'Login finished!'
                break
        else:
            time.sleep(5)
            print u'------------>等待用戶(hù)圖片驗(yàn)證'
    return sel


def search_proc(sel, train_type='', timer=False):
    print u'--------->選擇車(chē)次類(lèi)型', train_type
    # 定時(shí)搶票時(shí)間點(diǎn)
    if timer == True:
        while True:
            current_time = time.localtime()
            if ((current_time.tm_hour == 14) and (current_time.tm_min >= 25) and (
                        current_time.tm_sec >= 00)):
                print u'開(kāi)始刷票...'
                break
            else:
                time.sleep(5)
                if current_time.tm_sec % 30 == 0:
                    print time.strftime('%H:%M:%S', current_time)

    # 打開(kāi)訂票網(wǎng)頁(yè)
    book_url = 'https://kyfw.12306.cn/otn/leftTicket/init'
    sel.get(book_url)
    # 始發(fā)站
    # sel.find_element_by_id('fromStationText').click()
    # from_station = sel.find_element_by_xpath('//*[@id="ul_list1"]/li[32]') # 深圳
    # from_station.click()
    sel.add_cookie({"name": "_jc_save_fromStation", "value": value_fromstation})
    # 終點(diǎn)站
    # sel.find_element_by_id('toStationText').click()
    # sel.find_element_by_id('nav_list3').click()#點(diǎn)擊事件
    # tation = sel.find_element_by_xpath('//*[@id="ul_list1"]/li[9]') # 廣州
    # to_station.click()
    sel.add_cookie({"name": "_jc_save_toStation", "value": value_tostation})
    # 出發(fā)日期
    # date_sel = sel.find_element_by_id('train_date')
    # js = "document.getElementById('train_date').removeAttribute('readonly')" # del train_date readonly property
    # sel.execute_script(js)
    # date_sel.clear()
    # date_sel.send_keys(leave_date)
    sel.add_cookie({"name": "_jc_save_fromDate", "value": value_date})
    sel.refresh()
    # 車(chē)次類(lèi)型選擇
    train_type_dict = {'T': '//input[@name="cc_type" and @value="T"]',  # 特快
                       'G': '//input[@name="cc_type" and @value="G"]',  # 高鐵
                       'D': '//input[@name="cc_type" and @value="D"]',  # 動(dòng)車(chē)
                       'Z': '//input[@name="cc_type" and @value="Z"]'}  # 直達(dá)
    if train_type == 'T' or train_type == 'G' or train_type == 'D' or train_type == 'Z':
        sel.find_element_by_xpath(train_type_dict[train_type]).click()
    else:
        print u"車(chē)次類(lèi)型異忱疲或未選擇!(train_type=%s)" % train_type


def book_proc(sel, refresh_interval=0):
    # 等待狀態(tài)查詢(xún)
    query_times = 0
    time_begin = time.time()
    while True:
        # 循環(huán)查詢(xún)
        time.sleep(refresh_interval)
        # 開(kāi)始查詢(xún) @id="ZE_6c000D281201"
        search_btn = WebDriverWait(sel, 10).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="query_ticket"]')))
        search_btn.click()
        # 掃描查詢(xún)結(jié)果
        try:
            # T17
            tic_tb_item = WebDriverWait(sel, 20).until(
                EC.presence_of_element_located((By.XPATH, '//*[@id="ZE_6i000G291204"]')))
            # G381
            # tic_tb_item = WebDriverWait(sel,20).until(EC.presence_of_element_located((By.XPATH, '//*[@id="ZE_240000G38107"]')))
            tic_ava_num = tic_tb_item.text
        except:  # 應(yīng)對(duì)查詢(xún)按鈕一次點(diǎn)擊后,網(wǎng)站未返回查詢(xún)結(jié)果
            search_btn.click()
            # T17
            tic_tb_item = WebDriverWait(sel, 5).until(
                EC.presence_of_element_located((By.XPATH, '//*[@id="ZE_6i000G291204"]')))
            # G381
            # tic_tb_item = WebDriverWait(sel,20).until(EC.presence_of_element_located((By.XPATH, '//*[@id="ZE_240000G38107"]')))
            tic_ava_num = tic_tb_item.text

        if tic_ava_num == u'無(wú)' or tic_ava_num == u'*':  # 無(wú)票或未開(kāi)售
            query_times += 1
            time_cur = time.time()
            print u'第%d次查詢(xún),總計(jì)耗時(shí)%s秒' % (query_times, time_cur - time_begin)
            continue
        else:
            # 訂票 @id="ticket_6c000D281201"
            sel.find_element_by_xpath('//*[@id="6i000G291204_IOQ_IXQ"]/td[13]/a').click()  # T17
            # sel.find_element_by_xpath('//*[@id="ticket_240000G38107"]/td[13]/a').click()  # G381
            break
    # 判斷頁(yè)面跳是否轉(zhuǎn)至乘客選擇頁(yè)面
    cust_sel_url = 'https://kyfw.12306.cn/otn/leftTicket/init'
    while True:
        if (sel.current_url == cust_sel_url):
            print u'頁(yè)面跳轉(zhuǎn)成功!'
            break
        else:
            print u'等待頁(yè)面跳轉(zhuǎn)...'
    # 乘車(chē)人選擇
    while True:
        try:
            # sel.find_element_by_xpath('//*[@id="normalPassenger_0"]').click()
            sel.find_element_by_xpath('//*[@id="normalPassenger_1"]').click()
            break
        except:
            print u'等待常用聯(lián)系人列表...'

    # 席別選擇
    # 提交訂票
    sel.find_element_by_xpath('//*[@id="submitOrder_id"]').click()
    # 確認(rèn)訂票信息
    while True:
        try:
            sel.switch_to.frame(sel.find_element_by_xpath('//*[@id="body_id"]/iframe[2]'))
            print
            sel.find_element_by_xpath('//*[@id="qr_submit_id"]').click()
            print 'Pass!'
            break
        except:
            print u'請(qǐng)手動(dòng)通過(guò)圖片驗(yàn)證碼'
            time.sleep(5)
            break
    return 'yeah'


if __name__ == '__main__':
    # 變量定義
    leave_date = '2016-12-23'
    train_type = 'G'
    refresh_interval = 0.1
    timer = False

    sel = login_proc('****************', '***********')
    search_proc(sel, train_type, timer)
    book_proc(sel, refresh_interval)
  • 全局配置
#-*- coding: utf-8 -*-
# 對(duì)抗12306多次查詢(xún)后,會(huì)出現(xiàn)服務(wù)器繁忙問(wèn)題

from auto_book import login_proc,search_proc,book_proc
import configparser

config=configparser.ConfigParser()
config.read('user.cfg')

result = 'gogogo'
username=config.get('user','username')
password=config.get('user','password')
begin_time = '15:35:00'
refresh_interval = 0.1
timer=False
type='G'

for i in range(1,5):
    if result == 'gogogo':
        try:
            sel = login_proc(username,password)
            search_proc(sel,type,timer)
            book_proc(sel,refresh_interval)
        except:
            continue
    else:
        print result
        break

  • 配置登錄個(gè)人信息
[user]
username = yourname(輸入你的賬號(hào))
password = yourpassword(輸入你的密碼)
4.使用
  • 下載ChromeDrive并放到正確位置和配置好環(huán)境變量
  • 安裝selenium模塊
    pip install selenium
  • uesr.cfg文件配置個(gè)人信息
  • auto_book.py修改乘車(chē)始點(diǎn)站刷袍、終點(diǎn)站,乘車(chē)時(shí)間
  • wrapper.py設(shè)置車(chē)次類(lèi)型和是否定時(shí)搶票
  • 最后運(yùn)行python wrapper.py

** 項(xiàng)目地址**

** 更多文章請(qǐng)關(guān)注我的blog:https://karmalove.github.io/ **

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末樊展,一起剝皮案震驚了整個(gè)濱河市呻纹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌专缠,老刑警劉巖雷酪,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異涝婉,居然都是意外死亡哥力,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吩跋,“玉大人寞射,你說(shuō)我怎么就攤上這事⌒颗ィ” “怎么了桥温?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)轧粟。 經(jīng)常有香客問(wèn)我策治,道長(zhǎng),這世上最難降的妖魔是什么兰吟? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任通惫,我火速辦了婚禮,結(jié)果婚禮上混蔼,老公的妹妹穿的比我還像新娘履腋。我一直安慰自己,他們只是感情好惭嚣,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布遵湖。 她就那樣靜靜地躺著,像睡著了一般晚吞。 火紅的嫁衣襯著肌膚如雪延旧。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天槽地,我揣著相機(jī)與錄音迁沫,去河邊找鬼。 笑死捌蚊,一個(gè)胖子當(dāng)著我的面吹牛集畅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缅糟,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼挺智,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了窗宦?” 一聲冷哼從身側(cè)響起赦颇,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赴涵,沒(méi)想到半個(gè)月后媒怯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡句占,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年沪摄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡杨拐,死狀恐怖祈餐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情哄陶,我是刑警寧澤帆阳,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站屋吨,受9級(jí)特大地震影響蜒谤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜至扰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一鳍徽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧敢课,春花似錦阶祭、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至圾结,卻和暖如春瑰剃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筝野。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工晌姚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人遗座。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓舀凛,卻偏偏與公主長(zhǎng)得像俊扳,于是被迫代替她去往敵國(guó)和親途蒋。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容