🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
在最近的两年以来,大数据由一个概念,逐渐地落地成为我们生活中应用案例,从智能设备的数据收集到各类大型网站和应用一次又一次抛出来的各种有趣的数据报告。今天我们来聊一聊,在过年期间被人们讨论得比较多的百度迁徙。百度迁徙的产品和数据的应用本身,本文不做过多的探讨,大家可以自行体验,而数据源,无须置疑来自于百度地图以及相关引用了百度地图的手机应用。 本文所需要探讨的是其在前端,到底是如何实现的?因为探讨百度的地图和数据收集,并不对我们普通的开发工程师同学有益,咱们更想以一个工程师,尤其是全栈工程师的观点来讨论一下百度迁徙的实现。 在探讨之前,我们先抛出几个问题,这几个问题将在文章中一步步得到解答。 1、漂亮的迁徙地图是用什么画的,是Flash?SVG?还是Canvas? 2、用到了什么特殊的渲染手法,可以供我们自己在产品中使用的吗? 3、渲染出来的数据是怎么取回来的?是 JSON 吗,还是 XML?结构是什么样的? 4、渲染在地图上的数据,有多大一个实时度?每分钟一刷新?还是一小时? 5、多种地图数据,从人口迁徙到航班、机场、车站,每一种数据又是如何组织的呢? 6、地图底图是用的百度地图吗?为什么不能缩放以及其他操作? 好,那我们现在就开始来分析吧。 第一部分、技术与数据准备 这一次分析我们分别使用了 Charles 和 Chrome 的开发者工具,Charles 作为iPad 的代理,接收到迁移的所有代码文件,存在文件夹下。而Chrome 开发者工具,则做一些简单的实验和查看在 Web 下与Mobile 下的不同,然后将所有下载到的代码文件,导入 Netbeans 中,进行代码的浏览和相关格式化。 首先 Charles 帮了我们大忙,一下子就截获到了很多关键信息。如下图: ![](https://box.kancloud.cn/2016-02-29_56d3fe7b28de9.png) 从上图,我们可以看到如下几点: 百度迁徙,使用的是 jQuery 1.7.1 做为基础框架库。看来版本有一段时间没有更新了。 针对 PC 浏览器和智能设备浏览器,主 JS mainIndex 使用了不一样的版本。 使用了两个 JS 库,一个从名字上看也知道,是用于zip 格式操作的,一个是用于画图的。 刚才还怀疑为什么要用 jszip,从数据中找到了答案,因为从数据器端取回来的数据,就是压缩包。而且压缩包中取回的数据是有一定时间标识的。 对于 planeLocation 应该是机场的位置,做了预置,这也是一份不错的数据资料。 那下面我们展开分析,在Netbeans 中,我们简单将代码格式化,通过详细的分析来继续解开我们的疑惑。首先通过Charles 的Save All 保存在文件夹中。 ![](https://box.kancloud.cn/2016-02-29_56d3fe7b55a49.png) 然后将相关的 JS 文件进行处理,第一步是将压缩过的minify 过的文件还原。在 Netbeans 中,使用Ctrl+Shift+F ,就可以格式化代码,代码就不会挤在一块了。而像兴趣点文件 mobileLocation.min.js 中,有大量的 Unicode 代码,我们也可以通过 Java 工具还原。比如: native2ascii -reverse bcscdn.baidu.com/baidu-qianxi/chuxing/Scripts/POI/moblieLocation.min.js > bcscdn.baidu.com/baidu-qianxi/chuxing/Scripts/POI/moblieLocation.js 这个命令可以将 Unicode 编码转换成为我们能阅读的中文,这个数据对我们就非常有意思了吧,如果你要取得类似的数据,就可以直接拿来用啦。 ![](https://box.kancloud.cn/2016-02-29_56d3fe7b7961b.png) 图3、机场 Location 转换成为中文 第二部分:数据格式分析 那下载回来的数据文件是啥样的呢? 通过 unzip 发现,并不能解压,用Mac 系统自带的解压工具,则陷入了 cpgz 循环。 bash-3.2# unzip 20150221_1300_Mobile.zip Archive: 20150221_1300_Mobile.zip skipping: 20150221_1300_china_mobile.json need PK compat. v4.5 (can do v2.1) skipping: 20150221_1300_city_mobile.json need PK compat. v4.5 (can do v2.1) 那么到底是什么格式呢? 经过 Google ,原来要用 7zip 才能解压。于是乎: brew install p7zip 安装完成了之后, 就可以顺利解压了。 bash-3.2# 7za x 20150221_1300_Mobile.zip 7-Zip (A) [64] 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18 p7zip Version 9.20 (locale=utf8,Utf16=on,HugeFiles=on,2 CPUs) Processing archive: 20150221_1300_Mobile.zip Extracting 20150221_1300_china_mobile.json Extracting 20150221_1300_city_mobile.json Everything is Ok Files: 2 Size: 545572 Compressed: 46734 来看看数据,果真是得到了 JSON,可以写一段简单的PHP脚本就来看看这些数据。 $content = file_get_contents($argv[1]); print_r(json_decode($content)); 简单看几段,第一段是进入迁徙首页所看到的数据。 bash-3.2# php /code/test/newyear/parseJSON.php migration/20150221_1300_china.json |head -30 stdClass Object ( [topCityIn] => Array ( [0] => stdClass Object ( [name] => 重庆_重庆 [num] => 4160 [singleNum] => 4160 [per] => 0.0359 [floatFlag] => 0 ) [1] => stdClass Object ( [name] => 北京_北京 [num] => 3879 [singleNum] => 3879 [per] => 0.0335 [floatFlag] => 0 ) 这个数据里,有各个城市的迁入和迁出人口量以及百分比。 第二段是单个城市的数据,分为流入和流出两个方向,示例如下: 迁入数据: [北京_北京] => stdClass Object ( [topLineIn] => Array ( [0] => stdClass Object ( [name] => 天津_天津 [num] => 1092 [singleNum] => 1092 [per] => 0.2784 [floatFlag] => 0 ) [1] => stdClass Object ( [name] => 河北_保定 [num] => 917 [singleNum] => 917 [per] => 0.2337 [floatFlag] => 0 ) 迁出数据: [topLineOut] => Array ( [0] => stdClass Object ( [name] => 河北_保定 [num] => 1443 [singleNum] => 1443 [per] => 0.1669 [floatFlag] => 0 ) [1] => stdClass Object ( [name] => 天津_天津 [num] => 1337 [singleNum] => 1337 [per] => 0.1547 [floatFlag] => 0 ) [2] => stdClass Object ( [name] => 河南_周口 [num] => 143 [singleNum] => 143 [per] => 0.0165 [floatFlag] => 0 ) 这些数据反映到图上也比较直观。per 就是百分比,SingleNum 就是量。可以看到,我进入北京城市的数据之后,左边地图和右边列表的数据就是这么来的。 图 4、左边地图数据 图 5、 右边列表数据。 第三个数据是航班数据 stdClass Object ( [allPlane] => Array ( [0] => stdClass Object ( [name] => 3U8162 [LatLng] => Array ( [0] => 113.171027 [1] => 23.676085 ) [rotate] => 28 [islate] => [departure_city] => 广州 [destination_city] => 哈尔滨 [departure_airport] => 白云机场 [destination_airport] => 太平机场 [timpspan] => 13:18 ~ 17:38 ) [1] => stdClass Object ( [name] => 3U8305 [LatLng] => Array ( [0] => 122.204541 [1] => 32.570041 ) [rotate] => 157 [islate] => 1 [departure_city] => 哈尔滨 [destination_city] => 上海 [departure_airport] => 太平机场 [destination_airport] => 浦东机场 [timpspan] => 11:16 ~ 14:26 ) 在这份数据中,看到任意一架飞架,在当前这个时间的经纬度,出发城市,机场,到达城市,机场,是否晚点,以及大致的出发和到达时间。如果要做航班应用,这个数据也是不可或缺的。 第四个是航班数据,在plane 目录下存的是各个机场的热度。 stdClass Object ( [topPoi] => Array ( [0] => stdClass Object ( [name] => 北京_首都机场 [provincename] => 北京 [cityname] => 北京 [num] => 5880 [per] => 0.118 [floatFlag] => -1 ) [1] => stdClass Object ( [name] => 深圳_宝安机场 [provincename] => 广东 [cityname] => 深圳 [num] => 4290 [per] => 0.086 [floatFlag] => 1 ) 第5个车站的数据,跟机场数据差不多,不再介绍。 通过以上的数据,可以看到如下几点:所有的数据实质上是JSON,但是由于数据量较大,大多少呢? 20150221_1300.zip 文件共74K,解压之后的 JSON 文件 20150221_1300_china.json 283K, 20150221_1300_city.json 530K。90% 的压缩率。解压缩使用的是JSZipUtils,这是一个开源项目,能解压zip 文件,使用也很简单 // loading a zip fileJSZipUtils.getBinaryContent("path/to/file.zip", function (err, data) { if(err) { throw err; // or handle the error } var zip = new JSZip(data);}); 主页地址为:http://stuk.github.io/jszip-utils ,Github 地址为:https://github.com/Stuk/jszip-utils 从数据的文件名和测试可以发现,在渲染地图所用的数据是每隔一段时间固定生成的,人口、机场、车站等的数据是一小时生成一次。大约是在每个小时的前20分钟生成前一个小时的数据。 ![](https://box.kancloud.cn/2016-02-29_56d3fe7b9cb04.png) 而航班数据,则是10分钟生成一次。都在前一个10分钟生成。 ![](https://box.kancloud.cn/2016-02-29_56d3fe7bc0934.jpg) 从这里可以回答我们前面提出的问题,数据不是实时地,从服务器端取回来渲染的,是文件数据,是存储在CDN上的文件数据,这个是一个计算的结果而已。这是一种值得学习的处理办法,有很多的数据,其实看的是趋势和统计,迁徙就是如此。我们没有必要实时地计算得到数据。用户也不敏感,就像唱吧的打败了多少人,360助手的打败了多少人,绝不可能是实时的结果,也是统计,甚至都不是统计,而只是一个范围概念。这是值得我们学习的地方。 总结一下:百度迁徙所用的数据,是结果数据,并且我们可以依据上面的格式取得全部的数据,这些数据积累下来一段时间,可以做一些有意思的分析,经如可以分析出哪个航空公司、哪个航班路线的准点靠谱程度比较高。是非常有价值的。 今天有关数据说明,就讲到这里,明天我们将继续分享其在地图上的实现和绘制。