文章首發(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/ **