在最近的兩年以來,大數據由一個概念,逐漸地落地成為我們生活中應用案例,從智能設備的數據收集到各類大型網站和應用一次又一次拋出來的各種有趣的數據報告。今天我們來聊一聊,在過年期間被人們討論得比較多的百度遷徙。百度遷徙的產品和數據的應用本身,本文不做過多的探討,大家可以自行體驗,而數據源,無須置疑來自于百度地圖以及相關引用了百度地圖的手機應用。
本文所需要探討的是其在前端,到底是如何實現的?因為探討百度的地圖和數據收集,并不對我們普通的開發工程師同學有益,咱們更想以一個工程師,尤其是全棧工程師的觀點來討論一下百度遷徙的實現。
在探討之前,我們先拋出幾個問題,這幾個問題將在文章中一步步得到解答。
1、漂亮的遷徙地圖是用什么畫的,是Flash?SVG?還是Canvas?
2、用到了什么特殊的渲染手法,可以供我們自己在產品中使用的嗎?
3、渲染出來的數據是怎么取回來的?是 JSON 嗎,還是 XML?結構是什么樣的?
4、渲染在地圖上的數據,有多大一個實時度?每分鐘一刷新?還是一小時?
5、多種地圖數據,從人口遷徙到航班、機場、車站,每一種數據又是如何組織的呢?
6、地圖底圖是用的百度地圖嗎?為什么不能縮放以及其他操作?
好,那我們現在就開始來分析吧。
第一部分、技術與數據準備
這一次分析我們分別使用了 Charles 和 Chrome 的開發者工具,Charles 作為iPad 的代理,接收到遷移的所有代碼文件,存在文件夾下。而Chrome 開發者工具,則做一些簡單的實驗和查看在 Web 下與Mobile 下的不同,然后將所有下載到的代碼文件,導入 Netbeans 中,進行代碼的瀏覽和相關格式化。
首先 Charles 幫了我們大忙,一下子就截獲到了很多關鍵信息。如下圖:

從上圖,我們可以看到如下幾點:
百度遷徙,使用的是 jQuery 1.7.1 做為基礎框架庫。看來版本有一段時間沒有更新了。
針對 PC 瀏覽器和智能設備瀏覽器,主 JS mainIndex 使用了不一樣的版本。
使用了兩個 JS 庫,一個從名字上看也知道,是用于zip 格式操作的,一個是用于畫圖的。
剛才還懷疑為什么要用 jszip,從數據中找到了答案,因為從數據器端取回來的數據,就是壓縮包。而且壓縮包中取回的數據是有一定時間標識的。
對于 planeLocation 應該是機場的位置,做了預置,這也是一份不錯的數據資料。
那下面我們展開分析,在Netbeans 中,我們簡單將代碼格式化,通過詳細的分析來繼續解開我們的疑惑。首先通過Charles 的Save All 保存在文件夾中。

然后將相關的 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 編碼轉換成為我們能閱讀的中文,這個數據對我們就非常有意思了吧,如果你要取得類似的數據,就可以直接拿來用啦。

圖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分鐘生成前一個小時的數據。

而航班數據,則是10分鐘生成一次。都在前一個10分鐘生成。

從這里可以回答我們前面提出的問題,數據不是實時地,從服務器端取回來渲染的,是文件數據,是存儲在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私房菜