Python 自动化抢票脚本实战:基于 Selenium 的 12306 购票流程
前言
在春运等高峰期,手动抢票往往面临页面拥堵、验证码复杂等问题。利用 Python 结合 Selenium 自动化框架,可以模拟人工操作,提高查询和提交订单的效率。本文将详细介绍如何构建一个基于 Selenium 的 12306 抢票脚本,涵盖环境搭建、登录处理、余票监控及订单提交等核心环节。
环境准备
1. 依赖安装
确保已安装 Python 3.6+ 版本。需要安装以下库:
pip install selenium webdriver-manager
webdriver-manager 用于自动管理 ChromeDriver 版本,避免手动下载驱动文件的麻烦。
2. 浏览器配置
推荐使用 Google Chrome 浏览器。需确保浏览器版本与下载的 ChromeDriver 版本匹配。
核心逻辑实现
1. 车站编码获取
12306 系统使用特定的城市编码(如 %u6DF1%u5733%2CSZQ)。若需添加新城市,可打开 12306 官网查票页面,通过浏览器开发者工具查看网络请求中的参数。
2. 登录机制
出于安全考虑,12306 强制要求扫码或账号密码登录。脚本启动后需暂停等待用户手动完成登录验证,随后保存 Session 供后续请求复用。
3. 余票监控
通过定时轮询指定车次和日期的接口,解析页面元素判断余票状态。当检测到目标席别有余票时,触发预订流程。
4. 订单提交
自动填充乘车人信息,选择席别,并提交订单。此过程需处理可能的验证码或滑块验证。
5. 邮件通知
集成 SMTP 服务,在抢票成功后发送通知邮件,防止错过支付时间。
代码实现
以下是整合后的核心类结构示例:
import time
import smtplib
from email.mime.text import MIMEText
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
class TrainTicketBot:
def __init__(self):
# 初始化浏览器
self.driver = webdriver.Chrome(ChromeDriverManager().install())
self.wait = WebDriverWait(self.driver, 10)
# 配置信息
self.passengers = ['张三', '李四']
self.from_station = '%u5E7F%u5DDE%2CGZQ' # 广州
self.to_station = '%u90D1%u5DDE%2CZZF' # 郑州
self.train_numbers = ['Z90', 'Z190']
self.seat_type = '硬卧'
self.email_receiver = '[email protected]'
self.login_url = 'https://kyfw.12306.cn/otn/login/init'
self.init_my_url = 'https://kyfw.12306.cn/otn/index/initMy12306'
def do_login(self):
"""手动登录并等待 Session 建立"""
print('请扫码登陆或者账号登陆……')
self.driver.get(self.login_url)
while True:
if self.init_my_url in self.driver.current_url:
break
time.sleep(1)
print('登录成功')
def check_ticket(self):
"""检查余票"""
# 此处省略具体 URL 构造细节,实际需根据 12306 接口文档调整
# 模拟查找表格行
try:
# 注意:12306 页面结构频繁变动,XPath 需根据实际情况调整
rows = self.driver.find_elements(By.XPATH, '//tr[@datatran]')
for row in rows:
# 简单逻辑演示
pass
except Exception as e:
print(f'查询出错:{e}')
def submit_order(self):
"""提交订单"""
print('开始尝试预订……')
# 模拟点击预订按钮
# self.driver.find_element(By.CSS_SELECTOR, 'td.no-br>a').click()
# 选择乘客
# 选择席别
# 提交订单
print('订单提交中...')
def send_mail(self, receiver_address, content):
"""发送邮件通知"""
host = 'smtp.163.com'
port = 25
sender = '[email protected]'
pwd = 'your_auth_code'
receiver = receiver_address
body = f'<h3>温馨提醒</h3><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())
s.quit()
def run(self):
self.do_login()
# 主循环逻辑
while True:
self.check_ticket()
# 这里应加入具体的余票判断逻辑
time.sleep(5)
if __name__ == '__main__':
bot = TrainTicketBot()
bot.run()
注意事项与法律风险
- 反爬机制:12306 拥有较强的反爬虫策略,包括 IP 限制、验证码识别等。高频请求可能导致 IP 被封禁。建议设置合理的轮询间隔(如 5-10 秒)。
- 验证码处理:登录或下单时可能弹出图形验证码,目前自动化脚本通常需人工介入处理。
- 合规性:本脚本仅供学习 Python 自动化技术使用。请勿用于恶意攻击服务器或破坏正常购票秩序。遵守相关法律法规。
总结
通过 Selenium 模拟浏览器操作,可以实现基础的 12306 购票辅助功能。相比纯 API 调用,这种方式更稳定且易于调试。但需注意网站更新带来的兼容性维护成本。在实际应用中,建议结合多线程或分布式部署以提高效率。

