热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

12306自动刷票下单-查票下单

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

前言

上篇写了12306登录,隔了快一个月了,才准备动手写下单篇,真的要非常感谢博客园的 Asimple朋友,如果不是看到你的留言,我几乎都忘了要写下篇了,这一点在简书上就不好,都没人看/(ㄒoㄒ)/~~,刚开始写博客,真的需要大家的鼓励,看的人多了自然有动力写更多的,所以这一篇要给那些看过我上篇的同学们,尤其是这位Asimple同学,就是为你而写,没错就是这个原因。因为你让我知道了有人在看,而且用心的在看。发了这么多感慨,其实我不是这么爱感慨的人(✿◡‿◡),直入主题吧。

还得说一下这次我用的是Firefox浏览器,在上篇中说了Chrome浏览器的一个问题,在抓取的请求过多的情况下,前面的请求就可能看不到请求信息,最后搞得我不得不搞了个虚拟机,装了xp,用Fiddler去查看请求信息,后来就换了Firefox,最新版的Firefox没有Firebug可用,但是自带的开发者工具足够用了。当然Chrome我也没卸载,因为Chrome上有个很赞的功能,在元素界面查找元素的时候可以用css和xpath,可不是右键copy里面的css和xpath哦

在这个查找框里你就可以写自己的css和xpath,看实时效果,这个真是太棒了,不用装额外的插件。Firefox上暂时还没有发现这个功能,也不知道有没有类似的插件,如果有人知道的话,麻烦回复一下,先谢过了。鼠标左键还坏了,只能把右键设置一下暂时用着,一波三折呀!这次真的要进入主题了。

卧了一个槽,忽略我上面说的吧,要写博客了,有一个请求Firefox竟然不给显示了,还是虚拟机吧


后记

后记为什么要加载前言后面,而不是在文章最后,我怕你不看。在这次分析中我基本没有添加什么代码,因为基本上每一个请求就是定义一个字典、一个url,然后发送请求,获取数据,然后继续下一个。另一方面就是我并没有做代码优化和整理。我们都应该知道对于没有反爬措施的网站,基本上看两个小时的爬虫教程就能写的出来,对于有反爬的网站,最难得地方是分析阶段,而不是发送请求。最后一点就是做这个也是一时兴起,积累一下经验,最主要是开始写一写博客。同时给像我一样初学爬虫的朋友一个例子、一个思路。


查票


车票预订界面的url:https://kyfw.12306.cn/otn/leftTicket/init,选好票以后点击查询

多了一下两个请求,第一个请求我没用,没有任何影响,我们就不用去管它,直接看第二个请求
https://kyfw.12306.cn/otn/leftTicket/query?leftTicketDTO.train_date=2017-12-25&leftTicketDTO.from_station=BJP&leftTicketDTO.to_station=SHH&purpose_codes=ADULT

看一下参数和返回数据,太乱了,稍微仔细看一下,预订、有、G5,好像还是有些有用信息的,可以按|拆分一下看看

看到了车次G101,8、9是开车时间和到达时间,10是历时,商务座特等座9张余票,32行显示9,一等二等座都是有票,对应30、31,就不能具体确定了,暂时先不管,至少我们确定了这个请求是查询出我们需要的车票信息了,那么再看一下请求参数,第一个是时间很容易理解,第四个好像是票的类型,成人票,翻译一下单词就知道了,反正每次都一样,不用管了,中间两个出发站、目的地,不过这些字母是啥意思,应该是站名对应的编码,在这个请求之前肯定是有对应关系的,

https://kyfw.12306.cn/otn/resources/js/framework/station_name.js?station_version=1.9034
一个js的请求@bjb|北京北|VAP|beijingbei|bjb|0,拆分以后可以看到站名和编号

def query_ticket_info(date, info):
js_info = json.loads(info)
if js_info.get("status") != True:
print("查询余票失败")
return

result = js_info.get("data").get("result")
for i in result:
lst = i.split('|')
if lst[11] != "Y": #主要是判断是否开票了,见下图情况
continue
item = {
"预定号":lst[0], #预定号
"train_no":lst[2],
"车次":lst[3], #车次
"始发站":get_station_name_from_code(lst[4]), #始发站
"终点站":get_station_name_from_code(lst[5]), #终点站
"起始站":get_station_name_from_code(lst[6]), #起始站
"目标站":get_station_name_from_code(lst[7]), #目标站
"出发时间":"{} {}".format(date, lst[8]), #出发时间
"到达时间":get_end_time(date, lst[8], lst[9], lst[10]), #到达时间
"历时":lst[10], #历时
"train_location":lst[15],
"高级动卧":lst[21], #高级动卧
"软卧":lst[23], #软卧
"软座":lst[24], #软座
"特等座":lst[25], #特等座
"无座":lst[26], #无座
"硬卧":lst[28], #硬卧
"硬座":lst[29], #硬座
"二等座":lst[30], #二等座
"一等座":lst[31], #一等座
"商务座":lst[32], #商务座
"动卧":lst[33], #动卧
}
yield item

这个函数需要解释一下,主要是这些站点信息是怎么找到的,说一下思路
- 当我们打开车票预订界面的时候,是这样的,下面是空的

- 点击查询后

- 由此我们知道车票信息是通过js动态添加的(maybe),那么我们就查找动态创建出来的元素,随便在上面找一个元素特征,比如我找这个

当然你可以随便找一个,前提是不是动态创建的,然后在我们的js和document请求中去查找这个值,最后我找到了https://kyfw.12306.cn/otn/resources/merged/queryLeftTicket_end_UAM_js.js?scriptVersion=1.9053

我找这个是干什么呢?我们上面的请求得到了余票信息,是json格式的,那么肯定是通过js把它添加到界面上,我们要知道哪一个信息是添加到硬座上,哪一个是添加到硬卧上,就像我代码里写的那样,把所有的票种都找出来
- 通过分析js

然后把大部分我们需要的参数都对应出来,这样就看到像我上面写的函数那样,取出我们需要的信息
- 其实有一种更简单的方式,就是你查询了余票信息以后,会看到余票几张几张,然后去对应的信息参数中去找,比如

我们就知道了32对应的是商务座特等,多查询一些站点就会把所有对应索引都找出来


预订

点击预订后看一下请求,记住我上一遍说过的,一般是看xhr和document请求,
https://kyfw.12306.cn/otn/login/checkUser
看起来很简单,参数也只有一个_json_att,值为空
重头戏来了https://kyfw.12306.cn/otn/leftTicket/submitOrderRequest
看请求参数secretStr,其他的请求几次发现没啥变化,重点就在这个secretStr上了,太乱了,咦,我上面好像说过这三个字,对他们有关系。怎么去理解呢,这里是发了一个post请求,而这个secretStr是作为参数发送给服务器的,那么它必定是在我们本地产生的,在这个请求之前应该能找到。看一下特征:+wOQuwrBzvR6e…。是不是能发现查票那个请求里返回的数据第一个%2BwOQuwrBzvR6e,相似度很高啊,肯定是进行了编码或解码。Fiddler这点很好

点击查票请求的第一条数据,右键->Send to TextWizare…

哇哦,So Beautiful,这下就相等了,是使用了urldecode,这里支持很多种编码解码方式,非常方便,真相已经出来了,secretStr是我们上面输出的第0行字符串的urldecode解码值,python3中是parse.unquote。
train_date:订哪一天的票,back_train_date:今天的时间,还有出发站和目的地。


推荐阅读
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • 2021年最详细的Android屏幕适配方案汇总
    1Android屏幕适配的度量单位和相关概念建议在阅读本文章之前,可以先阅读快乐李同学写的文章《Android屏幕适配的度量单位和相关概念》,这篇文章 ... [详细]
  • 启动浏览器、设置profile&加载插件
    一、Driver下载地址:http:docs.seleniumhq.orgdownload二、启动firefox浏览器(不需要下载驱动,原生支持)1、firefox安装在默认路径下 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • poj1182 食物链(并查集经典题)
    食物链TimeLimit:1000MSMemoryLimit:10000KTotalSubmissions:124632Accepted:38129Description动物王 ... [详细]
  • fiddler_Fiddler的原理和基本介绍
    一,Fiddler的工作原理   1,Fiddler是位于客户端和服务器端的HTTP ... [详细]
  • 高仿CSDN社区树形图 .
    一直感觉CSDN社区的树形结构特别的人性化,直观化。最近做系统的时候需要用到这个树形结构,于是模仿CSDN的树形结构做了一个自己的树形结构, ... [详细]
  • IsapiCache组件 - 自动为网站生成…
    sapiCache是一款自动为网站生成静态页面的IIS组件(ISAPI筛选器),静态页面可以有效的加快网站访问速度,大大减轻服务器负担。工作原理是组件把服务器返回给客户端的网页源码保存起来,生成静态文 ... [详细]
  • 一、选择器性能优化建议1.总是从#id选择器来继承这是jQuery选择器的一条黄金法则。jQuery选择一个元素最快的方法就是用ID来选择了。1$(#content).hide() ... [详细]
  • 有哪些PHP调试技巧?
    有哪些PHP调试技巧?:回复内容:我目前遇到的最让我称赞的debug方式是:xdebug的xdebug_start_trace();*业务代码*xdebug_stop_trace( ... [详细]
author-avatar
波Z-
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有