臨近放假,相信我們每天都在群聊里或者朋友圈看到一些幫忙搶火車票的信息。
作為一個在廣東出生長大上小中大學的仔,我搶得最多的只是外賣紅包,火車票倒是從沒搶過。
看到朋友們搶回家的車票這么辛(bei)苦(can),結合圈里一些前輩的指點,抱着學習的心態用Python做了一個簡單的自動化搶票程序,搶到票之后通過綁定的郵箱(比如QQ)發通知。下面分享主要內容:
先自報家門:
版本號 Python 3.6.5
編譯器 PyCharm PRO 2018.1
瀏覽器 Google Chrome 71.0.3
首先,我們用到一個Splinter庫:
相信做自動化測試、自動化爬蟲的朋友都知道Selenium工具,它可以把人為驅動行為轉化為機器執行,Splinter的葯效跟它是一樣的。我們可以進去cmd后用 pip install splinter
這個命令來安裝。
然后
,開始使勁地碼:
1. 定義自動購票的類(初始化屬性)
class Buy_Tickets(object):
# 定義實例屬性,初始化
def __init__(self, username, passwd, order, passengers, dtime, starts, ends):
self.username = username
self.passwd = passwd
self.order = order # 車次,0代表所有車次
self.passengers = passengers # 乘客名
self.starts = starts # 起始地和終點
self.ends = ends
self.dtime = dtime # 日期
self.login_url = 'https://kyfw.12306.cn/otn/login/init'
self.initMy_url = 'https://kyfw.12306.cn/otn/view/index.html'
self.ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init'
self.driver_name = 'chrome'
self.executable_path = 'C:\python\chromedriver.exe'
2. 實現登錄功能
def login(self):
self.driver.visit(self.login_url)
self.driver.fill('loginUserDTO.user_name', self.username)
# sleep(1)
self.driver.fill('userDTO.password', self.passwd)
# sleep(1)
print('請輸入驗證碼...')
while True:
if self.driver.url != self.initMy_url:
sleep(1)
else:
break
3. 實現購票功能
def start_buy(self):
self.driver = Browser(driver_name=self.driver_name, executable_path=self.executable_path)
# 窗口大小的操作
self.driver.driver.set_window_size(1200, 700)
self.login()
self.driver.visit(self.ticket_url)
try:
print('開始購票...')
# 加載查詢信息
self.driver.cookies.add({"_jc_save_fromStation": self.starts})
self.driver.cookies.add({"_jc_save_toStation": self.ends})
self.driver.cookies.add({"_jc_save_fromDate": self.dtime})
self.driver.reload()
count = 0
if self.order != 0:
while self.driver.url == self.ticket_url:
self.driver.find_by_text('查詢').click()
count += 1
print('第%d次點擊查詢...' % count)
try:
self.driver.find_by_text('預訂')[self.order - 1].click()
sleep(1.5)
except Exception as e:
print(e)
print('預訂失敗...')
continue
4. 郵箱通知付款
def sendMail(self, mail_title, mail_content):
my_sender = 'xxx@qq.com' # 發件人郵箱賬號
my_user = 'xxxx@qq.com' # 收件人郵箱賬號
try:
'''發送郵件'''
msg = MIMEText(mail_content, "plain", 'utf-8') # 發送郵件內容
msg["Subject"] = Header(mail_title, 'utf-8') # 發送郵件主題/標題
msg["From"] = formataddr(['Bruce pk', my_sender]) # 郵件發送方
msg["To"] = formataddr(['brucepk', my_user]) # 郵件接收方
s = smtplib.SMTP("smtp.qq.com", 25) # 郵箱的傳輸協議,端口默認25
s.login(my_sender, 'xxxxx') # 登錄郵箱,這里的第二個參數為qq郵箱授權碼,不要填你的登錄密碼
s.sendmail(my_sender, [my_user, ], msg.as_string()) # 發送方,接收方,發送消息
s.quit() # 退出郵箱
print("搶票通知郵件發送成功!")
except Exception:
print("郵件發送失敗~~")
還有,網絡不好或者12306的服務器不穩定的時候,就會卡住,針對這種情況,系統會重復查詢:
else:
while self.driver.url == self.ticket_url:
self.driver.find_by_text('查詢').click()
count += 1
print('第%d次點擊查詢...' % count)
try:
for i in self.driver.find_by_text('預訂'):
i.click()
sleep(1)
except Exception as e:
print(e)
print('預訂失敗...')
continue
print('開始預訂...')
sleep(1)
print('開始選擇用戶...')
for p in self.passengers:
self.driver.find_by_text(p).last.click()
sleep(0.5)
if p[-1] == ')':
self.driver.find_by_id('dialog_xsertcj_ok').click()
sleep(3)
print('提交訂單...')
self.driver.find_by_id('submitOrder_id').click()
sleep(5)
print('確認選座...')
self.driver.find_by_id('qr_submit_id').click()
print('預訂成功...')
sleep(5)
self.sendMail(mail_title, mail_content)
except Exception as e:
print(e)
最后 ,祝大家都能順利搶到票回家過年。