Python版实现12306抢票功能,真的能帮你抢到春运回家的票吗?

Posted 我先测了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python版实现12306抢票功能,真的能帮你抢到春运回家的票吗?相关的知识,希望对你有一定的参考价值。

背景

每逢佳节倍思亲,年关将近,思乡的情绪是不是愈发强烈了,筒子们是不是又要准备开始抢票了,还是在找黄牛吗?但是,今年在考虑是否能抢到票以外,还需要考虑是否能回得去,没错,因为疫情,需要全国人民同心协力抗疫,咱不能给祖国妈妈添麻烦,只希望皆大欢喜吧!

黄牛

它凭什么,厉害得能’脱泥而出’抢到票,它是12306的内部人员?还是他家的亲戚?而且还那么牛逼哄哄的要价,春节要加价100元/张,让原本已经200元的票价就上涨70%,有什么办法解决这一现象吗?有些也是通过买人家工具的VIP功能(据说是按年续费的比较划算),还有其他交通app的vip加价功能,嗯,作者是没成功过!还几乎跟黄牛一个价,还不如给黄牛省心。

自动抢票脚本

作为半个程序员的作者,有点’水土’不服,也尝试过自己写脚本来解决,但是有一年直接被那个图片验证码给打败,也就不了了之了,而在前不久又看到了别人特别推崇的抢票脚本,在github开源了,一看吓一跳,star那么高比作者的35星强的不是一个量级,最后作者也耐不住好奇心拿来一试深浅。

克隆代码到本地

git clone https://github.com/testerSunshine/12306

首先阅读README.md配置好python运行环境,该有的功能呢先不要偷工减料,按要求完成。

修改配置文件:TickerConfig

  • 自动打码,设置为2
AUTO_CODE_TYPE = 2 # 听他的吧,否则就是执行不下去了,即使是2也不影响;
  • 没必要发送邮箱,设置False
EMAIL_CONF = 
    "IS_MAIL": False,
    "email": "",
    "notice_email_list": "",
    "username": "",
    "password": "",
    "host": "smtp.qq.com",

  • 不配置selenium环境,设置COOKIE_TYPE=3
# 如果COOKIE_TYPE=3, 则需配置RAIL_EXPIRATION、RAIL_DEVICEID的值
RAIL_EXPIRATION = ""
RAIL_DEVICEID = ""
    • 值去哪里找?浏览器访问:https://www.12306.cn;打开F12–cookies右侧栏就能找到了⬇⬇⬇

  • 关注微信提醒:SERVER_CHAN_CONF,可有可无
# 前往 http://sc.ftqq.com/3.version 扫码绑定获取 SECRET
SERVER_CHAN_CONF = 
    "is_server_chan": True,
    "secret": "SCT76378TuaIlPCkz8OkWcUJwvlJoAe7Q"

  • 其他配置项保持默认,只替换乘车日期、预售时间、乘车人、班次信息即可。

开始运行:python run.py r

如果开启代理,先将ip加到proxy_list执行:python run.py c

  • 哦豁,执行结果出票失败了,这是不可能的,帐号本地测试能登录提交订单,不应该存在失败;
  • 那么只能找源码调试了:inter/SubmitOrderRequest文件.submitOrderRequest类.sendSubmitOrderRequest方法
def sendSubmitOrderRequest(self):
    """
    提交车次
    预定的请求参数,注意参数顺序
    注意这里为了防止secretStr被urllib.parse过度编码,在这里进行一次解码
    否则调用HttpTester类的post方法将会将secretStr编码成为无效码,造成提交预定请求失败
    :param secretStr: 提交车次加密
    :return:
    """
    submit_station_url = self.session.urls["submit_station_url"]
    submitResult = self.session.httpClint.send(submit_station_url, self.data_apr())
    # print(submitResult) # 调试
    if 'data' in submitResult and submitResult['data']:
        if submitResult['data'] == "N":
            coi = checkOrderInfo(self.session, self.train_no, self.set_type, self.passengerTicketStrList,
                                 self.oldPassengerStr,
                                 self.train_date, self.ticke_peoples)
            coi.sendCheckOrderInfo()
        else:
            print (u'出票失败')
    elif 'messages' in submitResult and submitResult['messages']:
        raise ticketIsExitsException(submitResult['messages'][0])

分析源码

提交订单请求的时候,在第二个if条件时直接跳过,走到else就over了,根本就没检查订单,所以作者在外层print(submitResult)看看这个结果的data是啥?

  • ?excuse me,竟然是“0”,不是“N”
'validateMessagesShowId': '_validatorMessage', 'status': True, 'httpstatus': 200, 'data': '0', 'messages': [], 'validateMessages': 
  • 怀疑:帐号肯定能正常查询余票并下单成功的,不可能存在购买不了,所以猜测是12306返回参数改变了,让脚本没有走订票逻辑(毕竟是两年前的代码),所以改源码,让第二个if等于"0",记得是字符串哦。
if submitResult['data'] == "0": # 原来的右边条件是:"N"
  • 再次执行,结果如下,订票成功!

  • 于是赶紧跑去12306的app查验,果然有未支付的订单,真是太厉害了。

拭目以待

本地运行代码调试成功,只待明日查看结果,是否会订票成功,不然还是摆脱不了找黄牛的命运!!!

只希望疫情得以控制,否则就算是有票,根据严重情况,都有可能把线路都停运了。

以上是关于Python版实现12306抢票功能,真的能帮你抢到春运回家的票吗?的主要内容,如果未能解决你的问题,请参考以下文章

12306 分流抢票 纯净绿色版

春运一票难求,那12306是用什么开发的呢?

python3.7之12306抢票脚本实现

Python操作12306抢票脚本

春运火车票今日开售, python让你抢票快人一步

利用Python攻破12306的最后一道防线