转载--12306刷票记

article/2025/8/19 20:30:16

转载自:http://www.360doc.com/content/13/0122/17/453497_261790962.shtml


我也记不清啥时候动了写bot刷票这个念头的。原因很简单,我一直认为作为一个以代码谋生的不合格程序员,只有把生产工具用好,才能增加自己存在的价值。

首先说明一下主要开发环境:Windows 7,PHP 5.3,php_curl。

翻到了 第一条关于刷票的微博,附了图

很不低调地炫耀。

要刷票,首先自然得熟悉目标系统,所谓踩点。firefox+firebug,抓了一个标准流程的请求:登录、查票、订票。确认订单一开始没敢点,怕会有什么影响,后来去注册了几个测试号,然后尝试了确认订单的操作。流程本身不复杂,但是提交参数有点太多,一步一步来。

回到图1,登录,其实核心在验证码。

1 验证码识别
登录的验证码处理起来很简单,图在 https://dynamic.12306.cn/otsweb/passCodeAction.do?rand=lrand,提供一个示例
这个验证码结构一直没变,字体比较规则,无变形,直接就想到了tesseract,上一次用这个的时候是2010年12月初为了刷顺丰快递的订单追踪。
流程很简单:
1 下载图片;
2 转tiff(使用了ImageMagick的convert);
3 tesseract识别;
4 读取识别文件;
5 简单判断识别输出是否合法;
6 拼登录请求。

代码里留了个 decaptcha_valid()的方法,不过只判断了是不是4位数字+字母。
写完第一版代码后,清理了一些个人信息,把代码发给了@也云,不过当时毕竟比较早,他没怎么看,但是后期验证码识别这块提供了一些改进,包括:
1 replace识别输出里的空字符,因为由于字符间距不确定,tesseract偶尔会识别出空格;
2 训练tesseract,优化识别效果;
3 这次tesseract用的是v3,已经支持多种图片格式,而我还是按上次使用的经验convert jpeg 2 tiff,这次直接省去这个过程;
4 最关键的,登录验证码在登录请求提交后并不会删除上次访问验证码图片生成的session字段,也就是说,只需要识别一次验证码,后续只需要暴力提交即可

按4调整了验证码识别方法,增加了人肉输入的支持。使用system(‘out.jpg’)直接利用Windows 7 CMD的高级功能,同时发现了Win7自带的图片查看器system执行后程序可以继续往下走而不必关掉图片查看器,这样可以alt+tab切换cmd和图片查看器,确认人肉识别的输入是否正确。

上述逻辑在1月19号之前也同样适用于确认订单的验证码,那天早起发现这块儿验证码需要每次请求了,幸好之前人肉识别的改造增加了配置开关,很轻松地就完成了改动(虽然19号刷票无一成功,但是20号回家客车上刷5张票轻松到手)。

2 查票
查票的过程其实没啥特别可以说的,简单拼个请求,查票就是了。不过返回值是需要处理的,处理的依据,从页面看,就是查票结果输出里的“预订”按钮。

预订的参数就是页面输出里的getSelected()这个js调用的参数,最初的结构我从另外一条微博里找到了例子。
查票输出
正如页面上所示,结构是“车次号#历时(分钟单位)#发车时间#某个ID#始发站编号#目标站编号”,这个参数由页面解析后带入实际的预订请求。
不过后来某一天,这个参数变了,一个输出示例是“Z67#11:26#20:06#2400000Z6705#BXP#NCG#07:32#北京西#南昌#10175000003030800001404860000160895000001017503001”。同样按上边的解释,结构是“车次号#历时#发车时间#某个ID#始发站编号#目标站编号#到站时间#某个带入ypInfoDetail字段的参数”,@也云同学研究了一下最后这个字段,认定是“余票信息”的意思,对我们没有特别的意义,可无视(后续也证实了)。

这里可能有用的信息包括上述的“某个ID”。而查票的时候也需要输出里的始发站和目标站编号,这个编号可以从 这个地址里找到 。

3 订票 && 提交订单
订票使用了查票的输出参数,提交url是 https://dynamic.12306.cn/otsweb/order/querySingleAction.do?method=submutOrderRequest。明显有个Typo,而且这里名字是“提交订单”。不管那么多,说技术细节。

这个使用查票参数构造了一个POST请求,如果提交成功,服务器端会发一个302,重定向到一个新的页面 https://dynamic.12306.cn/otsweb/order/confirmPassengerAction.do?method=init。

流程很简单,curl实现只需要开 CURLOPT_FOLLOWLOCATION 即可。但是这个地方卡了我很久,直到12月初的某天才查出来为什么每次提交在这里总是出现 HTTP 500,虽然还是不知道原因,但是补上了几个http头,一切ok了(具体看代码)。

订票输出的页面,会有formtoken,参数名是 org.apache.struts.taglib.html.TOKEN。有点Web编程经验就应该能知道是干啥的。不多说,参数请求必须带上,所以正则匹配,无技术含量。
确认订单页只是拼参数,补上验证码识别就ok,无技术含量。

第一个细节,这个页面是填身份证的页面,入口有两个,订票 和 确认订单失败(后期确认订单失败不再直接回到该页面,不过验证码错误的应该还是会回来),所以确认订单的错误处理是可以考虑增加的。这个一开始代码就加上了,不过后来@也云改的lite版把这个流程改为 提交订单 + 确认订单,两步走,确认失败直接重订票。

第二个细节,验证码URL不一样了,https://dynamic.12306.cn/otsweb/passCodeAction.do?rand=randp,不过输出还是一样的。

第三个细节,最关键的,某个晚上睡前突然意识到的问题。回到form token上,我们可以观察到这个系统很多地方都会有form token,包括但不限于确认订单、支付订单、撤销订单等等。但是我意识到一个问题,提交订单这个过程可能会很慢,慢到一个不能忍的状态,尤其是高峰期。而,用户中心的表单里,也有form token,而且参数名完全一样,那么,这两个token会是同一个session字段吗?
接下来做的事情是改造form token的获取方法,改从用户中心的页面匹配,仅作测试。测试结果很乐观,从用户中心匹配到的token能作为确认订单token,而且这个请求自然会比从提交订单拿到的页面匹配要快,于是匹配token的方法可以优化了。(但是16号早上,订单系统似乎出问题了,各种慢,未支付订单页面刷不出来,支付订单也失败了,3张票扣了我1.3k RMB,没出票,极度想粗口!!!)

说到第三细节,如果你顺着读下来,可能会觉得有疑问:不是有很多参数要从页面匹配吗?如果不去拿提交订单后的页面,匹配变量,怎么确认订单?
答案是:你所需要的参数从你拿到查票输出的时候就已经足够了。你所需要的车次相关的信息,查票的输出已经能满足所有字段的需求;你所需要的订票人信息,以及所需坐席,你自己是已经知道了的。而,经过观察,查票输出里除了余票信息字段会变,其他的都不变!!!所以,你只需要在确定要刷票的前一天晚上,做一下准备工作,查查你要刷票的车次的信息,第二天拿着刷票便是了!!!
具体不多说,看代码便知。

到此,基本能说的都说了。

后边还有一些其他的细节优化。
支付
最初的支付表单是在一个独立的页面上,从未完成订单里选择订单,点支付,弹出的一个新页面匹配几个参数再submit,输出页面只有一个简单的form,body onload的时候触发了submit操作。也就是说,只需要拿下这个页面完成支付即可,这个最早@也云实验成功了,后来我有几次支付也用这个方法完成。过了几天,支付的表单在未完成订单点支付后的页面里直接写死了,于是新的lite版bot直接匹配了页面表单,存了个独立页面。
完后,弹出IE,支付。
本来想做招行的手机支付自动化的,后来实在懒了,自己订票的需求满足了,没心做这种优化。

登录
登录是件苦力活,经常就人满了,频率高了IP也会被封。所以登录成功一次得好好珍惜。
做法是: CURLOPT_COOKIEFILE + CURLOPT_COOKIEJAR。
脚本执行结束后,手工改 cookie jar文件,把expiration时间改长点。
但是由于经常性在登录完成后ctrl+c,没法触发__destruct()的调用,按@也云的建议,改成了登录完成后触发一次curl close操作并改expiration,执行结束后的继续保留。

源码
/bot.php
/config/test.php

执行参数 php bot.php 0 test 2>err.txt
只保证win下可用,soff改过一个mac下可用的版本,没找他要。
test 是 config/ 下的 test.php
0 是 test.php 里的tickets_info字段的索引,其实叫train_info更合适

然后为了骚扰自己,加了个vbs文件,内容很简单,取名messagebox.vbs,这段内容感谢@linxinsnow

' Message box Script
Set objArgs = WScript.Arguments
For I = 0 to objArgs.Count - 1
msgbox objArgs(I)
Next

写在最后
虽然我经常在微博XY,但是一直没公开源码。最终可用的代码也只有也云和soff拿到了。
一直不开源或者不发布的原因很简单,我不希望我的代码成为别人系统“有压力”的理由。我也看到了几个网上放出来的刷票工具或者js解决方案,但是,越多人知道这个,就意味着越多人会用你的“刀”“杀”铁道部。
或许我想的有点多。

感谢也云同学对本年度刷票的支持。感谢soff提供的验证码识别优化方案,虽然效果还不如我们的。



http://chatgpt.dhexx.cn/article/P2Qfuc4Y.shtml

相关文章

12306自动刷票下单-查票下单(二)

前言 上篇写了12306登录,隔了快一个月了,才准备动手写下单篇,真的要非常感谢博客园的 Asimple朋友,如果不是看到你的留言,我几乎都忘了要写下篇了,这一点在简书上就不好,都没人看/(ㄒoㄒ)/~~&a…

快过年了,Python实现12306查票以及自动购票....

马上就要过年了,听说还有人买不到票? 不要慌,今天咱们来用Python做一个自动查票抢票的脚本,24小时抢票,谁抢的过你! python实现12306自动抢票查票 准备工作爬虫思路 准备工作 环境 Python 3.8Pycharm 插…

12306智能刷票,订票

乐在分享 python版本支持 2.7.10 - 2.7.15 依赖库 依赖若快 若快注册地址:http://www.ruokuai.com/client/index?6726 推荐用若快,打码兔平台已经关闭项目依赖包 requirements.txt安装方法 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r…

12306自动刷票下单-下单

12306自动刷票下单-登录 12306自动刷票下单-查票预定 下单 进入下单界面了 https://kyfw.12306.cn/otn/confirmPassenger/initDc 还有一个请求https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs 仔细看一下返回值,是我们常用联系人的信息&…

12306自动刷票下单-下单(三)

12306自动刷票下单-登录篇(一)12306自动刷票下单-查票预定(二) 下单 进入下单界面了 https://kyfw.12306.cn/otn/confirmPassenger/initDc 还有一个请求https://kyfw.12306.cn/otn/confirmPassenger/getPassengerDTOs 仔细看一下…

新手写的一个12306刷票工具

本来是去年打算写的一个12306的刷票工具,但是一直拖着没完成。过完年才搞好。其实也不算写好,只是感觉都过完年了这个东西都没多大意义,在说各大网站上都有这个功能。但就当记录一下吧。 刚开始写的时候困扰我的其实不是买票的流程&#xff0…

【使用教程】面向回家编程-12306智能刷票,订票

代码链接:https://github.com/testerSunshine/12306 实名感谢:testerSunshine 春运一票难求,很多朋友都听说了GitHub上的12306抢票神器,但苦于没有计算机编程基础或在使用过程中遇到暂时无法解决的问题导致抢票失败。特撰写本博…

12306自动刷票下单-登录篇(一)

12306网站推出图片验证码以后,对于抢票软件就提出了更高的要求,本篇并不涉及自动识别验证码登录(主要是博主能力所限),提供一个途径-打码平台,这个几乎是可以破解所有验证码了,本篇主要是分享一…

12306刷票脚本

我也在刷票,不过发现12306还是发生了一些变化,在使用过程中,发现会自动退出登录。所以对脚本做了一些改动。顺便加了一些新的功能。具体如下: 防自动退出 添加刷到票后发起桌面通知 勾选某些类型的车 选择发站站点 …

c#模拟网页实现12306登陆、自动刷票、自动抢票完全篇

这一篇文章,我将从头到尾教大家使用c#模拟网页面登陆12306网站,自动刷票,选择订票人,到最后一步提交订单。研究过HTTP协议的童鞋们都知道,我们在访问网站时,是有两种方式的,POST和GET方式&#…

你距离家只差一个刷票脚本而已——12306刷票脚本升级版

马上就要回家了,票还没有。你是否用到了我去年发布的刷票脚本呢。传送门~ 我也在刷票,不过发现12306还是发生了一些变化,在使用过程中,发现会自动退出登录。所以对脚本做了一些改动。顺便加了一些新的功能。具体如下:…

搞技术的要不要学习财务知识

越是大型的集团或者企业,公司里面设立的部门就越多,也越细化,各部门之间既相互独立管理,又是相互的辅助支持,所以在工作中经常遇到这样的一个问题,就是做技术的要不要学习财务知识。这个问题其实就是把技术…

财务管理的一般常识

2019独角兽企业重金招聘Python工程师标准>>> 财务总监助理在协助财务总监做好企业理财规划与管理的时候需要首先了解以下的有关知识: —、财务和企业财务管理的概念 所谓“财务”,通俗地讲就是有关“钱财”的事务。从事一切事业都离不开钱财&…

财政系统基本知识

文章目录 一、基础数据1、单位管理修改2、部门信息 二、资产账1、卡片登记(新增资产)2、新增资产入账,也可批量入账3、卡片变动1)普通信息变动 >>>普通信息确认2)资产价值变动3)资产大类变动4&…

身为企业管理者,必须了解的财务知识

财务管理工作是企业管理工作中的核心内容,也是企业管理工作中的难点内容,对于集团企业来讲更是任务艰巨而又问题频出。然而,信息时代的来临为解决和完善企业财务管理问题提供了新思路,就集团企业而言,财务管理信息化基…

业务:财务会计业务知识

一、引言 会计是以货币为主要计量单位,对企业、事业、机关、团体及其他经济组织的经济活动进行记录、计算、控制、分析、报告,以提供财务和管理信息的工作。会计的职能主要是反映和控制经济活动过程,保证会计信息的合法、真实、准确和完整&a…

软件测试分类

一、软件测试的分类 1、按开发阶段:单元测试、集成测试、系统测试、验收测试 2、按测试实施组织:α、β、第三方 3、按测试执行方式:静态测试、动态测试 4、按是否查看代码:黑盒测试、白盒测试、灰盒测试 5、按是否手工执行划分&a…

【软件工程】软件测试报告——软件测试说明书

【备注】本说明书由华中农业大学2018级计算机科学与技术专业的刘畅、刘铠铭、张清望、卢家伟四位同学共同完成。 文章目录 1 引言1.1 编写目的1.2 背景1.3 术语和缩略词1.4 参考资料 2 测试用例设计3 测试结果及分析3.1 测试环境3.2 测试用例执行3.3 结论及建议 1 引言 1.1 编…

软件测试模型有哪些?

目录 1、瀑布模型 2、V模型 3、W模型 4、H模型 5、X模型 6、前置测试模型 1、瀑布模型 瀑布模型(Waterfall Model)是一个软件生命周期模型,开发过程是通过设计一系列阶段顺序展开的,从系统需求分析开始直到产品发布和维护&…

1.软件测试-----软件测试的基本概念

目录 一、软件测试的基本概念 1.什么是软件测试? 2.软件测试和软件开发的区别? 3.什么是需求? 4.什么是BUG? 5.如何描述一个BUG? 6.BUG的级别? 7.BUG的生命周期? 8.软件测试的生命周期&#xff1…