又是一年,馬上就要回家過年了,還沒有買到票的小夥伴們是否已經像熱鍋上的螞蟻了無腦的開始找黃牛了?
俗話說的好,求人不如求自己,搶票這玩意,其實我覺得我也可以~
來來來,直接入正題吧!
這裏有兩種方案,一種是基於Selenium2的自動化框架控制瀏覽器實現,另一種方案則是基於Python自身的爬蟲package如request,urllib等來實現,本文實現第一種方案,第二種方案也在摸索中。
實現過程
一、新版12306官網主要頁面網址
https://kyfw.12306.cn/otn/resources/login.html
https://kyfw.12306.cn/otn/view/index.html
https://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-10
from_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 = '[email protected]'
注意:城市字典是將城市簡寫和城市代碼之間聯繫起來。如果沒有你想要到城市,可以在打開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 = '[email protected]' # 你的發件郵箱號碼
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網站的更新大多數不能用了,我也是在前輩們的基礎上修改完成的。想要最新源碼的同學可以關注的我公衆號,回覆搶票源碼!