过年了家人们,抢到票没有
抢不到,很多人都会选择去某程抢加速包
但是!
该省省,该花花。骑着单车去酒吧!
先放源码,扫码关注公众号,回复源码,即可获取链接
不需要链接的兄弟们,可以直接看下面的思路
无套路,真心换真心
抢票思路
众所周知,接口层面从去年起就不行了
但是,我们用魔法打败魔法,我们就老老实实的走UI界面
流程图如图
我们定义了一个名为 BrushTicket 的类,该类用于实现自动购买12306火车票的功能。以下是该类的主要方法和属性:
init 方法:这是类的初始化方法,用于设置类的各种属性。这些属性包括12306的用户名和密码、乘车人姓名、出发站和终点站、乘车日期、车次编号、座位类型等。
user_name 和 password 属性:这两个属性用于存储12306的用户名和密码。
passengers 属性:这个属性用于存储乘车人的姓名。
from_station 和 to_station 属性:这两个属性用于存储出发站和终点站。
from_time 属性:这个属性用于存储乘车日期。
number 属性:这个属性用于存储车次编号。
seat_type 属性:这个属性用于存储座位类型。
框架选型
本次采用了splinter 框架,而不是才有selenuim框架,
选择 Splinter 框架而不是 Selenium 有以下几个原因:
- 更简单的 API:Splinter 提供了更简单直观的 API,使得编写和阅读测试代码变得更为方便。Splinter 的设计也更注重实用性,- 直接针对开发人员和测试人员的日常需求。
- 易于学习和使用:Splinter 的学习曲线较浅,相对于 Selenium,它更简洁,无论是从安装还是从编写代码的角度来看,都较为容易上手。
- 高级功能:虽然 Splinter 使用起来简单,但它也支持高级功能,如交互式 shell(您可以在编写测试时使用它进行调试)。
- 多浏览器支持:Splinter 和 Selenium 一样,都支持多浏览器。但是 Splinter 使用起来简单,而且更方便地在不同的浏览器之间切换。
- 开源社区:Splinter 有活跃的开源社区,如果遇到问题,可以从社区获得支持和帮助。
其实selenuim和splinter差不多,语法也及其相似
如图
Written in Splinter:
from splinter import Browser
browser = Browser('chrome')
browser.visit('http://cowabunga.tubular.awesome')
element = browser.find_by_css('.username')
element.fill('Michaelangelo')
Written in Selenium:
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('http://cowabunga.tubular.awesome')
element = driver.find_elements(by=By.CSS_SELECTOR, value='.username')
element.send_keys('Michaelangelo')
Splinter 的 API 提供了一个干净的界面,但这里还有更多内容:
from splinter import Browser
browser = Browser('chrome')
browser.visit('http://cowabunga.tubular.awesome')
element = browser.find_by_css('.username')
element.fill('Michaelangelo')
Splinter 将等待元素处于安全状态才能进行交互。这可以防止在 Web 应用程序准备就绪之前发现元素的常见错误。
Splinter 支持多个 Web 自动化后端。您可以使用相同的代码进行 Web 浏览器测试,以 Selenium 作为后端,并以 zope.testbrowser 作为后端进行“无头”测试(无 GUI)。
代码模块思路
登录
登录前准备,浏览器驱动,这里选用经典的谷歌浏览器
登录功能准备
这段代码是一个名为 do_login 的方法,它是在一个类( BrushTicket)中定义的。
def do_login(self):
"""登录功能实现,手动识别验证码进行登录"""
self.driver.visit(self.login_url)
sleep(1)
self.driver.fill('loginUserDTO.user_name', self.user_name)
self.driver.fill('userDTO.password', self.password)
print('请输入验证码……')
while True:
if self.driver.url != self.init_my_url:
sleep(1)
else:
break
买票功能
def start_brush(self):
"""买票功能实现"""
self.driver = Browser(driver_name=self.driver_name, executable_path=self.executable_path)
# 浏览器窗口的大小
self.driver.driver.set_window_size(900, 700)
self.do_login()
self.driver.visit(self.ticket_url)
try:
print('开始刷票……')
# 加载车票查询信息
self.driver.cookies.add({"_jc_save_fromStation": self.from_station})
self.driver.cookies.add({"_jc_save_toStation": self.to_station})
self.driver.cookies.add({"_jc_save_fromDate": self.from_time})
self.driver.reload()
count = 0
#未完待续
预订成功,发送短信
def send_sms(self, mobile, sms_info):
"""发送飞书通知短信,webhook地址需要自己去飞书申请"""
url = "https://open.feishu.cn/open-apis/bot/v2/hook/206c6464-8ec0-41d9-a8c2-79875e44ac18"
headers = {"Content-Type": "application/json"}
data = {
"msg_type": "text",
"content": {
"text": "预订成功"
}
}
response = requests.post(url, headers=headers, data=json.dumps(data))
params = parse.urlencode(
{'account': account, 'password': pass_word, 'content': sms_info, 'mobile': mobile, 'format': 'json'}
)
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
conn = httplib2.HTTPConnectionWithTimeout(host, port=80, timeout=30)
conn.request("POST", sms_send_uri, params, headers)
response = conn.getresponse()
response_str = response.read()
conn.close()
return response_str
抢票流程
def start_ticket_brushing():
# 终点站
to_input = input('请输入终点站,只需要输入首字母就行(例如北京“bj”):')
while to_input not in city_list.keys():
to_input = input('终点站不能为空或不支持当前终点站(如有需要,请联系管理员!),请重新输入:')
to_station = city_list[to_input]
# 车次编号
number = input('请输入车次号(例如“G110”):')
while number == '':
number = input('车次号不能为空,请重新输入:')
# 座位类型
seat_type = input('请输入座位类型(例如“软卧”):')
while seat_type == '':
seat_type = input('座位类型不能为空,请重新输入:')
# 抢票成功,通知该手机号码
receiver_mobile = input('请预留一个手机号码,方便抢到票后进行通知(例如:18888888888):')
mobile_pattern = re.compile(r'^1{1}\d{10}$')
while receiver_mobile == '' or re.findall(mobile_pattern, receiver_mobile) == []:
receiver_mobile = input('预留手机号码不能为空或者格式不正确,请重新输入:')
receiver_email = input('请预留一个邮箱,方便抢到票后进行通知(例如:test@163.com):')
总结
思路就介绍到这里,主要是利用splinter框架,模拟浏览器,自动刷新抢预订票,然后发送飞书通知,提醒付款,欢迎大家一起来讨论,并且提出更好的想法。