又是一年,馬上就要回家過年了,還沒有買到票的小夥伴們是否已經像熱鍋上的螞蟻了無腦的開始找黃牛了?
俗話說的好,求人不如求自己,搶票這玩意,其實我覺得我也可以~
來來來,直接入正題吧!這裡有兩種方案,一種是基於Selenium2的自動化框架控制瀏覽器實現,另一種方案則是基於Python自身的爬蟲package如request,urllib等來實現,本文實現第一種方案,第二種方案也在摸索中。
實現過程
一、新版12306官網主要頁面網址
https://kyfw.12306.cn/otn/resources/login.htmlhttps://kyfw.12306.cn/otn/view/index.htmlhttps://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc複製程式碼
二、瀏覽器驅動資訊
這裡使用的是chrome瀏覽器
在此處下載https://sites.google.com/a/chromium.org/chromedriver/downloads複製程式碼
三、初始化必要資訊
買票必要資訊,比如乘車人,來往車站,車次型別等等
# 乘客姓名passengers_input = 'xxx'passengers = passengers_input.split(",")#乘車日期,格式為2019-01-10from_time = '2019-01-31'# 城市cookie字典city_list = {
'sz':'%u6DF1%u5733%2CSZQ', #深圳 'zz':'%u90D1%u5DDE%2CZZF', #鄭州 'gz':'%u5E7F%u5DDE%2CGZQ', #廣州
}# 出發站from_station = '%u5E7F%u5DDE%2CGZQ'# 終點站to_station = '%u90D1%u5DDE%2CZZF'# 車次編號numbers = ['Z90','Z190','Z14','Z168','Z98','T124','T370']# 座位型別seat_type = '硬臥'#通知郵件receiver_email = 'xxxxxxxxx@163.com'複製程式碼
注意:城市字典是將城市簡寫和城市程式碼之間聯絡起來。如果沒有你想要到城市,可以在開啟12306的查票頁面,然後開啟瀏覽器的開發者模式,輸入對應的城市,然後檢視請求資訊。
四、登入功能實現
登入我們需要手動登入,掃碼或者輸入賬號都可以。登入後記錄session,供後面搶票使用
def do_login(self): """登入功能實現,手動識別驗證碼進行登入""" self.driver.visit(self.login_url) sleep(1) # 選擇登陸方式登陸 print('請掃碼登陸或者賬號登陸……') while True: if self.driver.url != self.init_my_url: sleep(1) else: break複製程式碼
五、搶票功能實現
核心功能實現,通過掃描關鍵字來確認是否有餘票,然後實現點選頁面,進而走向下一步。
current_tr = self.driver.find_by_xpath('//tr[@datatran="' + number + '"]/preceding-sibling::tr[1]')if current_tr: if current_tr.find_by_tag('td')[self.seat_type_index].text == '--': print('無此座位型別出售,已結束當前刷票,請重新開啟!') sys.exit(1) else: # 有票,嘗試預訂 print('刷到票了(餘票數:' + str(current_tr.find_by_tag('td')[self.seat_type_index].text) + '),開始嘗試預訂……') current_tr.find_by_css('td.no-br>
a')[0].click() sleep(1) key_value = 1 for p in self.passengers: # 選擇使用者 print('開始選擇使用者……') self.driver.find_by_text(p).last.click() # 選擇座位型別 print('開始選擇席別……') if self.seat_type_value != 0: self.driver.find_by_xpath( "//select[@id='seatType_" + str(key_value) + "']/option[@value='" + str( self.seat_type_value) + "']").first.click() key_value += 1 sleep(0.2) if p[-1] == ')': self.driver.find_by_id('dialog_xsertcj_ok').click() print('正在提交訂單……') self.driver.find_by_id('submitOrder_id').click() sleep(2) print('正在確認訂單……') self.driver.find_by_id('qr_submit_id').click()複製程式碼
六、搶票成功後郵件通知自己
一個很簡單的功能,不過卻是必要的,避免自己錯過!
def send_mail(self, receiver_address, content): """傳送郵件通知""" # 連線郵箱伺服器資訊 host = 'xxxx.163.com' port = 25 sender = 'xxxxxx@163.com' # 你的發件郵箱號碼 pwd = 'xxxxx' # 第三方授權登入嗎,不是登入密碼!! # 發件資訊 receiver = receiver_address body = '<
h2>
溫馨提醒:<
/h2>
<
p>
' + content + '<
/p>
' msg = MIMEText(body, 'html', _charset="utf-8") msg['subject'] = '搶票成功通知!' msg['from'] = sender msg['to'] = receiver s = smtplib.SMTP(host, port) # 開始登陸郵箱,併傳送郵件 s.login(sender, pwd) s.sendmail(sender, receiver, msg.as_string())複製程式碼
過程演示
- 執行程式碼
- 登入12306網站
- 搶票成功
- 等待支付
- 郵件通知
總結:
總的來說是成功的,但還不是完全自動化的。不過相比手動搶票還是快很多的。其實網上這種程式碼很多,只不過因為12306網站的更新大多數不能用了,我也是在前輩們的基礎上修改完成的。想要最新原始碼的同學可以關注的我公眾號,回覆搶票原始碼!
喜歡我寫的東西的朋友可以關注一下我的公眾號,上面有我的學習資源以及一些其他福利。:Devops部落