悲催的12306,彻底沦为各路抢票软件的服务提供方。元旦伊始,纯粹12306官网及APP抢票,愈一周的时间,仅到手一张凌晨3:55回家的站票。为远离脑残,无奈选择抢票软件,预购年后返沪车票。BTW,研究一下抢票脚本的实现思路,参考:(https://juejin.im/post/5b116504f265da6e0636cbc2 - Python3.6实现12306火车票自动抢票)。

  在原作者之上,对执行代码做了以下处理:

  1. 删除短信/邮件通知功能
  2. 删除控制台输入功能
  3. 新增登陆cookie的刷新
  4. 新增多车次抢票
  5. 新增多座位类型抢票

  注:使用 splinter.browser 在调用时,注意将 chrome驱动路径(chromedriver.exe所在)配置在环境变量 -  path 下。

代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*- from splinter.browser import Browser
from time import sleep
import sys class BrushTicket(object):
"""买票类及实现方法"""
def __init__(self, passengers, from_time, from_station, to_station, number_seat):
"""定义实例属性,初始化"""
# 乘客姓名
self.passengers = passengers
# 起始站和终点站
self.from_station = from_station
self.to_station = to_station
# 乘车日期
self.from_time = from_time
# 车次 - 座位 dict
num_seat_dic = {}
for num_seat in number_seat:
use = num_seat.split(':')
num = use[0]
seats = use[1]
seats_use = seats.split(',')
seat_str = ''
for seat in seats_use:
# 座位类型所在td位置
if seat == '商务座特等座':
seat_type_index = 1
seat_type_value = 9
elif seat == '一等座':
seat_type_index = 2
seat_type_value = 'M'
elif seat == '二等座':
seat_type_index = 3
seat_type_value = 0
elif seat == '高级软卧':
seat_type_index = 4
seat_type_value = 6
elif seat == '软卧':
seat_type_index = 5
seat_type_value = 4
elif seat == '动卧':
seat_type_index = 6
seat_type_value = 'F'
elif seat == '硬卧':
seat_type_index = 7
seat_type_value = 3
elif seat == '软座':
seat_type_index = 8
seat_type_value = 2
elif seat == '硬座':
seat_type_index = 9
seat_type_value = 1
elif seat == '无座':
seat_type_index = 10
seat_type_value = 1
elif seat == '其他':
seat_type_index = 11
seat_type_value = 1
else:
seat_type_index = 7
seat_type_value = 3
seat_str += (str(seat_type_index) + '-' + str(seat_type_value) + ',')
num_seat_dic[num] = seat_str
self.num_seat_dic = num_seat_dic
# 新版12306官网主要页面网址
self.login_url = 'https://kyfw.12306.cn/otn/resources/login.html'
self.init_my_url = 'https://kyfw.12306.cn/otn/view/index.html'
self.ticket_url = 'https://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc'
# 浏览器驱动信息,驱动下载页:https://sites.google.com/a/chromium.org/chromedriver/downloads
self.driver_name = 'chrome'
self.driver = Browser("chrome")
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
def start_brush(self):
"""买票功能实现"""
# 浏览器窗口最大化
self.driver.driver.maximize_window()
# 登陆
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
while self.driver.url == self.ticket_url:
self.driver.find_by_text('查询').click()
sleep(1)
count += 1
print('第%d次点击查询……' % count)
if count % 50 == 0:
self.driver.find_by_id('login_user').click()
sleep(1)
self.driver.visit(self.ticket_url)
sleep(1)
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()
if self.driver.url == self.ticket_url:
continue
try:
# 多车次处理
for bander in self.num_seat_dic.keys():
current_tr = self.driver.find_by_xpath('//tr[@datatran="' + bander + '"]/preceding-sibling::tr[1]')
if current_tr:
# 多座次处理
seat_value = self.num_seat_dic[bander]
seat_split = seat_value.split(',')
for seat in seat_split:
if seat:
seat_type = seat.split('-')
seat_type_index = int(seat_type[0])
seat_type_value = int(seat_type[1])
if current_tr.find_by_tag('td')[seat_type_index].text == '--':
print(bander + ' 还未出售')
sleep(1)
elif current_tr.find_by_tag('td')[seat_type_index].text == '无':
print(bander + ' 无票,继续尝试……')
sleep(1)
else:
# 有票,尝试预订
print(bander + ' 刷到票了(余票数:' + str(
current_tr.find_by_tag('td')[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 seat_type_value != 0:
self.driver.find_by_xpath(
"//select[@id='seatType_" + str(key_value) + "']/option[@value='" + str(
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)
# 查看放回结果是否正常
submit_false_info = self.driver.find_by_id('orderResultInfo_id')[0].text
if submit_false_info != '':
print(submit_false_info)
self.driver.find_by_id('qr_closeTranforDialog_id').click()
sleep(0.2)
self.driver.find_by_id('preStep_id').click()
sleep(0.3)
continue
print('正在确认订单……')
self.driver.find_by_id('qr_submit_id').click()
print('预订成功,请及时前往支付……')
else:
print('不存在当前车次【%s】,已结束当前刷票,请重新开启!' % self.number)
sys.exit(1)
except Exception as error_info:
print(error_info)
except Exception as error_info:
print(error_info)
if __name__ == '__main__':
# nya
passengers=['***'] # 用户名
from_time='2019-02-01' # 出发日期
from_station='%u4E0A%u6D77%2CSHH' # 起始站点 - 来自12306 余票查询 请求 - cookie (此处 - 上海)
to_station='%u6C11%u6743%2CMQF' # 结束站点 (此处 - 民权)
number_seat=['K4054:硬座,无座','K4168:硬座,无座'] # 车次:座位类型
# 开始抢票
ticket = BrushTicket(passengers, from_time, from_station, to_station, number_seat)
ticket.start_brush()

python3.7之12306抢票脚本实现的更多相关文章

  1. Python 实现的 12306抢票脚本

    Python12306抢票脚本 本脚本使用一个类来实现所有代码,大体上分为以下几个模块及其步骤:- 初始化对象属性(在抢票前进行的属性初始化,包括初始化浏览器模拟对象,个人信息等).- 建立模拟浏览器 ...

  2. Python操作12306抢票脚本

    有一段时间没有使用Python了,前几天经朋友提起一篇关于用Python实现抢火车票的文章,百度了实现抢火车票的技术细节,网上却有不少资料,也不是新鲜的东西.在了解了一些技术手段,阅读了一些大神的博文 ...

  3. 12306抢票带来的启示:看我如何用Go实现百万QPS的秒杀系统

    本文为开源实验性工程:“github.com/GuoZhaoran/spikeSystem”的配套文章,原作者:“绘你一世倾城”,现为:猎豹移动php开发工程师,感谢原作者的技术分享. 1.引言 Go ...

  4. 12306 抢票系列之只要搞定RAIL_DEVICEID的来源,从此抢票不再掉线(上)

    郑重声明: 本文仅供学习使用,禁止用于非法用途,否则后果自负,如有侵权,烦请告知删除,谢谢合作! 开篇明义 本文针对自主开发的抢票脚本在抢票过程中常常遇到的请求无效等问题,简单分析了 12306 网站 ...

  5. 四、基于HTTPS协议的12306抢票软件设计与实现--水平DNS并发查询分享

    一.基于HTTPS协议的12306抢票软件设计与实现--实现效果 二.基于HTTPS协议的12306抢票软件设计与实现--相关接口以及数据格式 三.基于HTTPS协议的12306抢票软件设计与实现-- ...

  6. 12306抢票算法居然被曝光了!!!居然是redis实现的

    导读 相信大家应该都有抢火车票的经验,每年年底,这都是一场盛宴.然而你有没有想过抢火车票这个算法是怎么实现的呢? 应该没有吧,咱们今天就来一一探讨.其实并没有你想的那么难 bitmap与位运算 red ...

  7. 12306 抢票项目霸榜 GitHub,标星即将破万

    十一将至,你买到回家的火车票了吗?如果没有,你可以试着打开 GitHub,在搜索栏键入 12306 的关键词,我相信你会发现一个新大陆.没错,这里有 1572 个抢票项目.它们大多用 Python.J ...

  8. python写12306抢票

    #!/usr/bin/env python # -*- coding: utf-8 -*- ''' 利用splinter写的一个手动过验证及自动抢票的例子, 大家可以自己扩展或者弄错窗体.web端. ...

  9. 马后炮之12306抢票工具(四)--抢票Demo,2014年1月9日终结版

    时隔一年多,终于朋友的忽悠下吧抢票Demo的最后一步完善了,与2014年1月9日成功生成车票. Demo仅经过自己测试,并未在高峰期进行测试,代码质量很差,因为赶工,套用去年模板并未使用设计模式. 代 ...

随机推荐

  1. Raspberry Zero 上实现平滑视频图传

    在某些应用场合我们可能需要通过一个设备通过WIFI将图像传到其它的机器进行显示或者图形分析,那怎么可以低成本地实现呢?其实很简单,我们只需要一块 Raspberry Zero W 和一个RPI 摄像头 ...

  2. 蛙蛙推荐: TensorFlow Hello World 之平面拟合

    tensorflow 已经发布了 2.0 alpha 版本,所以是时候学一波 tf 了.官方教程有个平面拟合的类似Hello World的例子,但没什么解释,新手理解起来比较困难. 所以本文对这个案例 ...

  3. dcoker搭建wordpress

    下载wordpress镜像 docker pull wordpress 创建wordpress容器 docker run -d --name wordpress --link mysql:mysql ...

  4. 1060E Sergey and Subway(思维题,dfs)

    题意:给出一颗树,现在,给哪些距离为2的点对,加上一条边,问所有点对的距离和 题解:如果没有加入新的边,距离和就会等于每条边的贡献,由于是树,我们用点来代表点上面的边,对于每条边,它的贡献将是(子树大 ...

  5. Comet OJ 热身赛(E题)(处理+最短路算法)

    dijkstra 已经提交 已经通过 42.86% Total Submission:189 Total Accepted:81 题目描述 Eagle Jump公司正在开发一款新的游戏.泷本一二三作为 ...

  6. PS调出唯美冷色情侣婚纱写真照

    一.打开PS原片,原片是一张JPG格式的片子 色温较高整个画面较红离对着上面的我们标准的韩式色调我们来进行调节吧 ,我就不打太多文字解释一些基本常规了 二.韩式婚纱内景喜欢加点烟雾.其实我本人是不太喜 ...

  7. Python之操作MySQL数据库

      一.操作步骤 1.导入pymysql模块 2.建立连接(ip.用户名.密码.数据库名.端口号.字符集.(自动提交参数)) 3.建立游标 4.执行sql语句 (4.需要提交的提交) 5.关闭游标 6 ...

  8. 【kindle笔记】之 《恶意》-2018-4-20

    [kindle笔记]读书记录-总 在答辩和考试和各种大作业的重压以及两天后全校停电的巨大挤压中,一口气读完了恶意这本书. 这本书是我读的东野圭吾的第二本书.第一本是心心念念的<解忧杂货店> ...

  9. mysql cpu 100% 满 优化方案

    解决MySQL CPU占用100%的经验总结 - karl_han的专栏 - CSDN博客 https://blog.csdn.net/karl_han/article/details/5630782 ...

  10. 敏捷与CMM的恩怨

    模式不同,一种是灵活,一种是严肃.