临近放假,相信我们每天都在群聊里或者朋友圈看到一些帮忙抢火车票的信息。看到朋友们抢回家的车票这么辛(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)