在最近的两年以来,大数据由一个概念,逐渐地落地成为我们生活中应用案例,从智能设备的数据收集到各类大型网站和应用一次又一次抛出来的各种有趣的数据报告。今天我们来聊一聊,在过年期间被人们讨论得比较多的百度迁徙。百度迁徙的产品和数据的应用本身,本文不做过多的探讨,大家可以自行体验,而数据源,无须置疑来自于百度地图以及相关引用了百度地图的手机应用。
本文所需要探讨的是其在前端,到底是如何实现的?因为探讨百度的地图和数据收集,并不对我们普通的开发工程师同学有益,咱们更想以一个工程师,尤其是全栈工程师的观点来讨论一下百度迁徙的实现。
在探讨之前,我们先抛出几个问题,这几个问题将在文章中一步步得到解答。
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助手的打败了多少人,绝不可能是实时的结果,也是统计,甚至都不是统计,而只是一个范围概念。这是值得我们学习的地方。
总结一下:百度迁徙所用的数据,是结果数据,并且我们可以依据上面的格式取得全部的数据,这些数据积累下来一段时间,可以做一些有意思的分析,经如可以分析出哪个航空公司、哪个航班路线的准点靠谱程度比较高。是非常有价值的。
今天有关数据说明,就讲到这里,明天我们将继续分享其在地图上的实现和绘制。
- PHP技术文章
- PHP中session和cookie的区别
- php设计模式(一):简介及创建型模式
- php设计模式结构型模式
- Php设计模式(三):行为型模式
- 十款最出色的 PHP 安全开发库中文详细介绍
- 12个提问频率最高的PHP面试题
- PHP 语言需要避免的 10 大误区
- PHP 死锁问题分析
- 致PHP路上的“年轻人”
- PHP网站常见安全漏洞,及相应防范措施总结
- 各开源框架使用与设计总结(一)
- 数据库的本质、概念及其应用实践(二)
- PHP导出MySQL数据到Excel文件(fputcsv)
- PHP中14种排序算法评测
- 深入理解PHP原理之--echo的实现
- PHP性能分析相关的函数
- PHP 性能分析10则
- 10 位顶级 PHP 大师的开发原则
- 30条爆笑的程序员梗 PHP是最好的语言
- PHP底层的运行机制与原理
- PHP 性能分析与实验——性能的宏观分析
- PHP7 性能翻倍关键大揭露
- 鸟哥:写在PHP7发布之际一些话
- PHP与MySQL通讯那点事
- Php session内部执行流程的再次剖析
- 关于 PHP 中的 Class 的几点个人看法
- PHP Socket 编程过程详解
- PHP过往及现在及变革
- PHP吉祥物大象的由来
- PHP生成静态页面的方法
- 吊炸天的 PHP 7 ,你值得拥有!
- PHP开发中文件操作疑难问答
- MongoDB PHP Driver的连接处理解析
- PHP 杂谈《重构-改善既有代码的设计》之二 对象
- 在php中判断一个请求是ajax请求还是普通请求的方法
- 使用HAProxy、PHP、Redis和MySQL支撑10亿请求每周架构细节
- HTML、HTML5、XHTML、CSS、SQL、JavaScript、PHP、Web Services 是什么?
- 重构-改善既有代码的设计
- PHP场景中getshell防御思路分享
- 移动互联时代,你看看除了PHP你还会些什么
- 安卓系统上搭建本地php服务器环境
- PHP中常见的缓存技术!
- PHP里10个鲜为人知但却非常有用的函数
- 成为一名PHP专家其实并不难
- PHP 命令行?是的,您可以!
- PHP开发提高效率技巧
- PHP八大安全函数解析
- PHP实现四种基本排序算法
- PHP开发中的中文编码问题
- php.get.post
- php发送get、post请求的6种方法简明总结
- 中高级PHP开发者应该掌握哪些技术?
- 前端开发
- web前端知识体系大全
- 前端工程与性能优化(下)
- 前端工程与性能优化(上)
- 2016 年技术发展方向
- Web应用检查清单
- 如何成为一名优秀的web前端工程师
- 前端组件化开发实践
- 移动端H5页面高清多屏适配方案
- 2015前端框架何去何从
- 从前端看“百度迁徙”的技术实现(一)
- 从前端看“百度迁徙”的技术实现(二)
- 前端路上的旅行
- 大公司里怎样开发和部署前端代码?
- 5个经典的前端面试问题
- 前端工程师新手必读
- 手机淘宝前端的图片相关工作流程梳理
- 一个自动化的前端项目实现(附源码)
- 前端代码异常日志收集与监控
- 15年双11手淘前端技术总结 - H5性能最佳实践
- 深入理解javascript原型和闭包系列
- 一切都是对象
- 函数和对象的关系
- prototype原型
- 隐式原型
- instanceof
- 继承
- 原型的灵活性
- 简述【执行上下文】上
- 简述【执行上下文】下
- this
- 执行上下文栈
- 简介【作用域】
- 【作用域】和【上下文环境】
- 从【自由变量】到【作用域链】
- 闭包
- 完结
- 补充:上下文环境和作用域的关系
- Linux私房菜