悲催的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. Linux或Windows上实现端口映射

    通常服务器会有许多块网卡,因此也可能会连接到不同的网络,在隔离的网络中,某些服务可能会需要进行通信,此时服务器经过配置就可以承担起了转发数据包的功能. 一.Windows下实现端口映射 1. 查询端口 ...

  2. vue-area-linkage Vue省市区三级列表联动插件使用

    官方演示地址 // v5及之后的版本 数据依赖于area_data npm i --save vue-area-linkage area-data import Vue from 'vue'; imp ...

  3. Linux常见问题汇总

    Linux问题: ifconfig查看IP地下载报错:bash: ifconfig: commandnotfound 解决方法: 先执行 export PATH="$PATH:/sbin&q ...

  4. 十四、怎么获取data-id中的值

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  5. RabbitMQ总结

    消息队列 三个业务场景:解耦.异步.削峰 带来问题 系统可用性降低:外部依赖越多,越容易挂掉. 系统复杂性提高:重复消费,消息丢失,消息传递的顺序性 一致性问题: 一.如何保证消息的可靠性传输(如何处 ...

  6. Django的模板语言

      Django模板系统 官方文档 常用语法 只需要记两种特殊符号: {{  }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 变量 {{ 变量名 }} 变量名由字母数字和下划线组成. ...

  7. 【kindle笔记】之 《明朝那些事儿》-2018-7-1

    [kindle笔记]读书记录-总 最近在读这本书.之前在微信读书里断断续续读过,读到深处还想蹦起来做笔记那种.后来种种原因断了,再没续上. 现在又开始啦.最近还在重八兄造反阶段,还很早呢,有时候晚上玩 ...

  8. swagger 指定字段不显示到文档里

    Swagger UI 隐藏指定接口类或方法 - 宁静致远 - CSDN博客https://blog.csdn.net/lqh4188/article/details/53538201 swagger ...

  9. opencv2\core\cuda.hpp(106): error C2059: 语法错误:“常量”

    在 cuda.hpp 中, virtual void free(GpuMat* mat) = 0;   -> virtual void _free(GpuMat* mat) = 0;

  10. day 7-5 生产者消费者模型

    一. 生产者和消费者模型 在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 二. 为什么要使用生产者和消费者模式 ...