Category: 票.今天

从“香港西九龙”到12306协议

从“香港西九龙”到12306协议

经过了乱七八糟的问题,质疑和风浪之后,香港西九龙终于开通在即了。 先来个小笑话: 这票二维码是和票面信息完全不符……槽点满满。 XJA-IZQ:香港西九龙——广州南 二维码上购票人姓名和票面购票人姓名不同,车次G9994是要干什么么……更别说时间日期以及票号等等等等了……车厢,座位号和证件倒是对的。 当然,也许二维码上这个日期和时间是原预定开通时间,然后原预定开通为香港西九龙——广州南,并且车次为G9994次……(完全瞎猜。如有雷同,实属巧合。不接受跨省追捕。) 回到正题: 现在这几天车迷圈儿除了香港西九龙就是香港西九龙,感觉什么都见不到。某微博(实在想不起来名字了)的香港西九龙至各地的时刻表传的圈子内(当然我也可以假设圈子外也是)基本无人不知无人不晓。 有意思的是,现在12306官网还没有把香港西九龙站上表——而APP已经这么做了。 作为kelibiao.com的站长,每次有新站上客里表的时候都必须得看一眼数据。明显,香港西九龙还没有上表,但是总是可以一探究竟的。毕竟数据需要及时更新,才能够吸引到更多用户么(说得跟用户有多少一样)。 正好有人跟我讲到香港西九龙上了APP的站名表,并且听说电报码是-XJA;同时有个叫做“边界”的“车站”,电报码为-XBA,希望我能求证。于是,我便开始了折腾一天的求证之旅。   首先,第一个想法就是进行http嗅探。作为昔日piao.today的站长,12306前端怎么工作我还是比较了解的。APP和网站很类似——APP其实就是个h5配上app的壳做成的WebAPP而已。但是我也早在那时候就知道APP的通讯也是https的。这就导致了嗅探起来比较麻烦。 当然,麻烦不代表做不了。大概有以下几种方法: 找个树莓派弄成路由器然后中间层攻击(真的懒得再碰树莓派了) 反编译app(这不是扯淡呢么,最麻烦的方法——写在这儿凑数的。两条还搞个list真的不好看) 手机层面上想办法。 嗅探么,一直在安卓上用一款叫做wicap的软件。Google Play也推送了剩下三个他家的软件——其中有一个叫做Proxymon。一看,正是我想要的:它会在手机上安装一个根证书,然后手机上的网络全走这上面一圈儿(中间层了么这不就是),然后解压。 于是,我便开始了我的折腾之旅。 第一件事儿,打开手机。发现手机0%电。小米手机这点好:插上电源0%也能开机——不像苹果必须达到一个安全值后才可以开机。 之前root过的手机不知道怎么回事儿root还给关了。幸亏早就刷了自定义的Discovery系统,很快重新root了。 打开Wicap和Proxymon,下载了12306,查询香港西九龙至随便点了一站。这样的话,APP会提交一个http请求,并且在里面显示出发到站和请求的出发日期。 很快,通过Proxymon我就读到了我需要的数据: OK,from_station=XJA,看来香港西九龙的电报码是XJA无误了。 那既然这样了,我为什么不直接顺便把整个请求链抓下来呢?Proxymon是我第一次使用,之前没有购买过,而免费版只会记录256kb的数据。准备购买完整版,却在支付的时候被Google Play拦截了,死活无法支付——从信用卡到PayPal到礼品卡都无法支付。给Google打电话用了45分钟才把问题解决好——因为我需要重新验证我的身份(安全是安全,但是真耽误事儿啊)。 很快,我得到了一堆(解密过的)数据包。dump到电脑后,发现里面所有Content-Encoding: gzip的response无法被解压——原因不得而知。试用了直接将response体存为文件用gzip解压,失败;用python找zlib库解压,失败;甚至直接用之前的代码套了个http server(dump下来的是http请求体和返回体如同上图,所以该有的header等都有)直接返回到浏览器或者给curl解压,也失败。得到的城市数据库等都无法被成功解压成response里所说的text/plain或者application/json(说白了还是text)格式,都是一大堆二进制数据。套了http server之后让浏览器自动解gzip失败后它自动把二进制数据下载了下来,大小和chunked里面描述的大小完全一样;同理,对于request请求体,很多写了Content-Type: application/json的也是一片乱码。用TridNet来分析response返回来的二进制文件也无法分析出是gzip格式。估计是12306学聪明了,把请求加密了一些。具体怎么解密,估计就不是今天能解决得了的事儿了。 此路不通,总有留爷处么(什么鬼混搭)。决定从APP入手。毕竟12306只需要从网上get一次基础数据,以后都可以用了就——这说明,他们肯定是有持久化存储的。果不其然,在文件系统的data目录里找到了12306的数据库——看到扩展名为db,第一个想法就是“这八成是SQLite吧”……把文件传到了电脑上,读取了一下——果然是SQLite! 好了,那就搜索一下就好了么…… 有意思的是,香港西九龙在12306 APP上的拼音的确为HKWestKowloon。这要是真的输拼音进去然后找不到香港西九龙该多尴尬啊…… 这是谁才能想得到这个站的拼音叫做HKWestKowloon,然后拼音缩写还是xg…… 证明一下: 同时,对id的搜索并未找到有电报码为-XBA的车站,也无法找到名为“边界”的车站。说明“边界”站未上表(比如不办理客运业务等)。根据这位提问者的说法,有TRS数据事实证明该站存在(注:TRS为中国铁路的售票系统,就是你去车站买票的时候车站售票人员用的那个软件)。他推测的本站定性为:“广深港高速线深港段的分界站,划定内地和香港铁路资产范围”。但是无论如何,我个人还是认为眼见为实的。目前来说我没有看到该站直接事实存在的证据,而该车站存在的方式也不好说(真的是个“站”是不可能了,没准就是个什么标记啥的呢。参考海岫铁路的那一堆车站,一个没见到影。跟着高德地图去了一趟所谓的析(shi2)木站,真的是什么标记都没有,周边都是玉米地)。 无论如何,任务完成了。上面提到的无法gzip解压(也许是解密)的问题以后可以再说。 今天一整天都耗在这上面了,连午饭都没吃就到了晚饭的点儿了。抛砖引玉,希望各位能够对12306的底层协议和数据结构等发展出更深刻的了解吧。

票.今天的数据抓取

票.今天的数据抓取

好久没写博客了。 回国了,放假了,也是时候写篇博客散散心了。 作为一个抓取数据的网站,抓取数据是最重要的一个环节。 piao.today是如何做到稳定抓取数据的呢? 余票趋势和实时余票功能 他们抓取数据的难点都分别在哪里呢? 让我们来盘点一下。   首先,说说余票趋势。 余票趋势最重要的是后台抓取,不可避免地需要谈到Worker进程。 本站的抓取分任务分发者和工作者。分发者负责从数据库中查找需要抓取的区间,然后分发给抓取的工作者。 在实践过程中,男性朋友们会遇到worker进程由于控制不当系统问题而提前射x停止工作(被系统莫名kill掉)。 所以,我们需要用crontab来进行一个小脚本,每隔一段时间查看worker数量,若不足则增加worker数量到一个数值。 这些脚本的用途就是用来获取当前运行了多少worker,若不足则重新添加。 因为Python的稳定性(而且作为后台运行的程序来说,只要内存足够,不管多少worker进程都放得下),所以没啥大问题。 但是,最近将实时余票功能升级了一下,改成允许用户抓取多日(预售期)余票(比如),发现服务器经常出现502(Bad Gateway)或者504(Gateway Timeout)错误。 这说明,我的php-fpm和Nginx的设置有问题,没有考虑到大并发和长连接的问题。 如果用户中途关闭了窗口,经常一个fpm进程就会卡在那里不知所措,被水淹没。 那么会导致整个站点因为fpm数量不够而卡死。 现在分散到多个vps上——四个服务器,三个在香港一个在日本,避免了把整个站带坏。 因为这些服务器距离国内都不远,所以抓取实时余票反馈给用户会很快。 以后应该研究一下对于这种情况的根本解决措施。 最近有时间先把筛选搞了吧。 总之吧,先mark下。 等着过两天驾照下来了好好研究研究。

说说搬迁网站时候那点儿破事儿吧

说说搬迁网站时候那点儿破事儿吧

我相信网站搬家对于许多站长都是一个十分蛋疼的问题。 无论是数据库,还是网站代码,搬迁都非常令人头疼。 好了,废话不多说,我就说说我搬网站的时候有多蛋疼吧。 首先,12G的MySQL数据文件(说是MariaDB更好) 想要从一个服务器搬到另外一个服务器,还是跨洲的(香港——法国),那稳定性我就不说什么了。 sftp真心慢成狗了……香港服务器本身只有3Mbits的带宽,上传速度300KBytes每秒,那简直就是忍无可忍啊…… 结果偶然一下子发现了个好东西叫做rsync,哇塞豁然开朗啊…… 上传速度按MByte算啊,超过了物理限制有木有!   将此事问询Q神,果真不出我所料是压缩了。 管他呢,不管黑猫白猫,只要能抓老鼠就是好猫。 速度这么快,爽死了,也就是差不多两个小时左右传完了…… 之后开始忙活MariaDB安装啊,配置啊…… 发现数据库文件在,数据库有显示表存在,但是点击之后告诉我Table xxx doesn’t exist…… 这不是在逗我么,这不是在逗我! 去网上查了一下,得把原来数据库的ib*文件全都传过去。 OK,传过去之后就没事儿了。 开始跑网站抓数据。 哎我去,新问题来了:有个表仍然显示不存在。 一看,这两个文件都不在,表能存在才怪。 OK,从旧服务器上传了这两个文件。 本以为能搞定,结果发现建表的时候显示Table xxx exists! 打开表又显示Table xxx doesn’t exist! 想要DROP也提示doesn’t exist…… 你在逗我…… 好吧,把ib*都移到了一个文件夹里备份,重新上传ib*文件。 得了,MariaDB干脆无法启动。 好吧,重新把之前的复制回来。 一下子又好使了……谁知道这鬼东西到底是怎么运作的…… 但是user表和邮件提醒表失踪了……显示存在但是打开的时候又提示不存在…… 好吧,抱着仅存的希望DROP表,没想到DROP成功了! 直接从老服务器导出两个sql文件(比直接拷表文件安全方便快捷,毕竟小可以导出),传到新服务器上然后导入。 OK完成。   然后配置nginx+php……结果发现这个直接把php代码就写出来了……php没有经过解析就出来了…… 赶快确认一下连接用文件是否会有代码外泄,发现竟然没有! 之后竟然发现,php-fpm的默认设置是关闭shorttag的……我有些文件是shorttag有些不是(比如连接用文件就不是shorttag所以经过了解析)。去php的设置里面改了改,开启shorttag的解析。 彻底搞定,票.今天 成功地迁移到了法国服务器。60天预售期模式开启,祝你们玩儿的开心!

zhxq(SolveKit)下属网站2015年发展计划

zhxq(SolveKit)下属网站2015年发展计划

2015年还有不到一个月时间就要到了。 公交/火车Wiki已经快要进行到第三个年头了。 感谢各位的支持,要是没有各位的支持我张某人肯定撑不到今天。 尤其是感谢父母给我资金,感谢我可爱的琳琳给我精神上的支持。 没有你们,我没法坚持到今天。 在这里,尤其要感谢以下的车迷: SCat、Q神、最爱橙子、京西A169/壹仟、SolveKit官方群所有成员、#模拟售票官方群全体成员、北京公交吧各位公交迷、以及经由维护群所有成员。 感谢中国铁路车迷网的管理员愿意在网站首页导航栏为 票.今天 以及火车Wiki留出链接位置。 还要感谢所有公交Wiki/火车Wiki/票.今天的用户,因为你们的使用才有了我网站的成功! (友谊地久天长bgm响起)   好了,客套话就不说了。 下面让我说说大概下一年我下属网站的发展计划吧。 首先:钱钱钱!谁能给我捐点儿钱啊……啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊(不明真相的群众:啊站长你上来就谈钱不怕伤感情么?你开头就敛财这个样子真的好么?) 好吧……我来说说…… 现在火车Wiki&鞍山火车迷俱乐部的网站总共用了大概是15G空间,挂载在狗爹(godaddy)的服务器上。 票.今天的数据库占了12G,都是在网站服务器上,服务器也就是30G的空间啊……系统5个G,服务器的各种软件几个G……加上数据库12G真心hold不住啊……(虽然现在已经成功迁移到了新的2T服务器上) 最近这两天又开始购入huoche.wiki, gongjiao.wiki, piao.wiki 以及 tielu.wiki,还有zhxq.io, zxq.io以及zhxq.me作为技术博客以及技术试验平台……简直是不堪重负啊…… 要知道我只是一个没有收入的大学僧啊……大一的大学僧啊…… 吃饭现在都快成问题了就为了写网站啊…… 我有点儿太拼了啊…… 求捐助啊求捐助…… 支付宝:zhxq@zhxqweb.com 比特币:1PiQuZMSufrREFVkoh3gGsmKENKCqUbTf3 比特币二维码:    好了要钱到此为止……说点儿不伤感情的…… 首先——让我来介绍一下公交Wiki和火车Wiki的新域名! 他们是:http://gongjiao.wiki/以及http://huoche.wiki/! 没错,域名的名字就是这么任性! 什么?问我为什么不是gj.wiki或者hc.wiki? 根据http://whois.nic.wiki/查询了whois…… 看到没…… 到这个网站一看—— https://gitlab.centralnic.com/centralnic/spec5-reserved-names 下载下来,打开spec5.pdf…… 第二条提及了所有的两个字符的域名都会被禁止注册。 好吧,ICANN干的我也没办法…… 干脆就huoche.wiki以及gongjiao.wiki算了,将就用吧…… 这么好记的域名都记不住……那我可就真没办法了……   好了继续…… 另外,收入了两个其它域名——http://piao.wiki/以及http://tielu.wiki/,用来以后做更多类型的维基网站。 同时,将会上线一些铁路文化/学术类网站,让更多的人认识火车迷群体,也能让中国铁路文化得到传承。 目前火车迷躯体在往低龄化趋势发展,如何处理好文化断层是个问题。随着上面两个新网站的发展,我相信这个问题会解决的。   另外,现在已经彻底地把票.今天迁移到了法国的OVH服务器。 2T硬盘(实则1.77G),足够用个几年了。…

Read More Read More

OVH主机终于申请通过!

OVH主机终于申请通过!

天灵灵,地灵灵,观世音菩萨来显灵……(不对啊我是无神论者) OVH主机终于通过了! 附上截图一张~ 好样的! 等待人工处理服务器上线中~ 先美美地睡一觉,明天早上估计就好了~ 反正马上就要考完期末考试了,等着期末考试考完配置票.今天的新服务器也不迟~ 大家敬请拭目以待!   (当然网站可能是要关闭可能几个小时吧……不好说,毕竟12GB的数据在那儿放着呢是吧……这个吧我有必要告诉你们一点儿人生的经验,不要总想搞个大新闻……哎哎哎不对这是技术帖子啊)

为了 票.今天 购买OVH旗下主机的一些小插曲

为了 票.今天 购买OVH旗下主机的一些小插曲

票.今天上线三个月了(这句话都在多少个post里面重复过了喂!) 数据量达到12个G,一个小小的虚拟主机根本就达不到要求啊! 现在算是砸锅卖铁,铁了心准备买个好的真正的独立服务器用来存 票.今天 的数据。 那么问题来了——性价比高哪家强? 没事儿闲的google,查到了OVH——很久没有找独立主机了,现在还能想起来OVH的大名……果断点击进去。 发现他们家旗下有一个品牌比较好,价格也不错,32$每月 2T硬盘。   果断买啊果断买!买买买!! 结果下了单发现他们竟然是需要人工审核订单的!   这不是在逗我么……虽然我知道这是为了保护电子财产安全吧…… 于是乎……发送了这个过去。 The reason that I use this to send my documents is because i@zxq.io is a email that redirected to zhxqaeiou@gmail.com. To proof that, I have a screenshot. After that, are my documents. First is my government issued document – passport…

Read More Read More

票.今天的大数据

票.今天的大数据

票.今天已经上线三个月了。 这三个月积攒了不少的数据。 截至PST 2014年12月7日 15:31分时,本站已经拥有数据128649413条(为了给我这种得数几位的人方便,报一下数吧——一亿两千八百六十四万九千四百一十三条) 数据算是大数据了。 占了大概是12G左右的空间。 现在的想法就是能够继续缩减空间,然后搬迁到独立服务器上去。 什么时候能够执行该计划呢?真心不好说啊……

浅谈票.今天

浅谈票.今天

票.今天是个神奇的网站。 它将本身完全不透明的中国铁路票务给变得公开化起来了。 虽然还是得靠用户的力量才行,但是明显的能让更多人知道中国铁路票务到底是个什么情况。 网站大概的意思就是——从12306上每五分钟抓取一次用户请求(日期,发站,到站)的数据,存到我自己的服务器里(包含所有该日该区间车次以及所有的当时的余票数据&抓取时间),可以随时绘图出来余票数量的走势。 为什么想要写票.今天呢? 因为SCat最近忙,没有时间打理余票网…… 于是我觉得我干脆写一个功能类似但又不同的网站好了…… 顺便当做练练手。 同时,在这里感谢SCat,Q神,沈仙,各种原火车Wiki用户以及#模拟售票官方群的各位帮忙进行了测试。   下面我来说说票.今天的大概架构吧。 作为一个大一学生(写网站的时候处于高三毕业状态,还没有上大学),也就是懂一些基本的网站运营维护技术。 火车Wiki在1月份的时候改写成php,公交Wiki啥时候改写的我都给忘了……总之给我积攒了不少php经验。 手机版和电脑版几乎没有区别,唯一的区别就是界面区别;后台处理的代码几乎完全可以通用。 但是,票.今天作为一个抓数据的网站,明显需要后台值守的进程。 那么问题来了——后台值守哪家强? C太麻烦、C++同样的道理(而且我还不会C++)……其它很多语言更别说了。 最后,两个选择——坚持已经会的滚瓜烂熟的php和完全一点儿不会的Python. 想了想以前曾经做过的一些项目,php做后台进程的稳定性真心不敢恭维……想了想还是现学Python现卖吧。   Python毕竟是C族语言,还是有很多地方可以和php通用的。 之前我已经用php写好了一个完整版的抓取全国铁路余票数据的程序,用了大概一天时间改成了Python(在此之前我一点儿Python不会)。 结果发现了个大问题——全国一共有2000多个车站,2000*2000=四百万次循环……四百万次啊!!而且还有以后的数据压力有木有!!!(我知道12306上有个js有全国所有车次,分析下就能抓取到全国所有的车次了,但是数据压力啊数据压力啊……) 想了想,还是算了……还是改成了用户添加什么车就监控什么车。 很好改,十几分钟就搞定了。 为了应对大量请求,我另外买了两个服务器专门用来抓取余票数据和发送邮件(简称甲乙服务器吧)。 甲服务器每五分钟Crontab一个抓取的Client,读取用户请求然后发送到本机的Gearman Server。甲乙服务器各跑着25个值守Worker读取甲服务器请求,当Gearman有新任务立刻抓取数据。 乙服务器每五分钟Crontab一个邮件的Client,读取用户请求然后发送到本机的Gearman Server。甲乙服务器各跑着25个值守Worker读取乙服务器请求,当Gearman有新任务立刻发送邮件。 为了防止Worker进程异常退出,两个服务器每五分钟Crontab一个脚本,该脚本的作用是若发现每种Worker脚本正在运行进程数量小于25个时,自动补全回25个。对两种Worker均有效。   然后是前台的php,给用户看的,这都好办,就是时间问题;一点儿点儿写就行了。 数据库么——有以下表: 用户表 车站&电报码对应表 用户添加请求表(简称A表) 每个请求有一个表(去A表的重,简称B表)(在一个月之前是一天一张表,但是有的时候一张表上千万数据效率极低于是分表) 大概就这样了。 每次Python脚本从A表读取用户请求,然后12306抓取数据存到B表。 A表中同时存储每条请求的拥有的所有车次,网页先从A表读取信息,只有点击了查看趋势图才会从B表读取数据绘出图表(Highcharts绘制图表真心不错,怪不得那么些大网站都在用Highcharts)。 邮件处理么……也是每五分钟crontab(跟抓取的py一样),从数据库读取最新数据(直接抓的资源消耗太高)然后发送给用户。 用户在网站上可以选择关注的席位。 系统判断该车次的席位是通过在B表中随意找出一行(就说是直接找出来第一行就完了呗),每一个列代表一个席位。若列为NULL那么说明无该席位,反之同理。 感觉这个系统真心做的不错。(王婆卖瓜自卖自夸啊这是……) 现在的问题就是:一亿两千八百六十四万条记录,什么时候能有个好点儿的安家之地? 写了这么多,也该吃饭去了。学校的招牌印度咖喱鸡肉卷我来也~