又是一年,立刻就要回家過年了,尚未買到票的小夥伴們是否已經像熱鍋上的螞蟻了無腦的開始找黃牛了? css
俗話說的好,求人不如求本身,搶票這玩意,其實我以爲我也能夠~ html
來來來,直接入正題吧! 這裏有兩種方案,一種是基於Selenium2的自動化框架控制瀏覽器實現,另外一種方案則是基於Python自身的爬蟲package如request,urllib等來實現,本文實現第一種方案,第二種方案也在摸索中。chrome
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
複製代碼
買票必要信息,好比乘車人,來往車站,車次類型等等bash
# 乘客姓名
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 = 'xxxxxxxxx@163.com'
複製代碼
注意:城市字典是將城市簡寫和城市代碼之間聯繫起來。若是沒有你想要到城市,能夠在打開12306的查票頁面,而後打開瀏覽器的開發者模式,輸入對應的城市,而後查看請求信息。服務器
登陸咱們須要手動登陸,掃碼或者輸入帳號均可以。登陸後記錄session,供後面搶票使用cookie
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
複製代碼
核心功能實現,經過掃描關鍵字來確認是否有餘票,而後實現點擊頁面,進而走向下一步。session
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網站的更新大多數不能用了,我也是在前輩們的基礎上修改完成的。想要最新源碼的同窗能夠關注的我公衆號,回覆搶票源碼!框架
喜歡我寫的東西的朋友能夠關注一下個人公衆號,上面有個人學習資源以及一些其餘福利。:Devops部落