参考我的项目: https://github.com/CHENJIAMIAN/CesiumLoadGoogleEarth
怎么知道怎么做的
SASPlanet 是一个免费程序,旨在查看和下载由Google Earth,Google Maps,Bing Maps,DigitalGlobe,Kosmosnimki,Yandex.Maps等服务提供的高分辨率卫星图像和常规地图。雅虎地图,VirtualEarth,Gurtam,OpenStreetMap,eAtlas,iPhone地图,General Staff地图和其他服务,但与这些服务不同的是,您下载的所有地图都将保留在计算机上,即使没有Internet连接也可以查看它们。除卫星地图外,还可以使用政治地图,景观地图,组合地图以及月球和火星地图。 通过选择特定区域(可能是非矩形)以及在地图周围移动的过程来执行地图加载。地图会经常更新-该程序仅允许您下载最新的地图。
网络协议说明
~~~~~~~~~~~~~~~~~~~~~~~~~~
Google Earth使用简单的HTTP,但是它拥有自己的auth和简单加密。
最常见的URL包括:
/geauth-处理身份验证
/dbRoot.v5-包含用于解密所有数据的密钥的文件+一些XML
/flatfile?f1-XXX-i.YYY-加密的JPEG图像(仅在
auth 之后可用)。XXX是Google格式的图像的(x,y,级别),而YYY
是包含图像
/flatfile?q2-XXX -加密和zlib压缩的元数据(仅在auth后可用)。XXX是Google格式的块(x,y,level)。
其中包含诸如图像和地形数据的可用性以及从中获取数据的节点号之类的信息。
/flatfile?f1c-XXX-t.YYY-大概是未知格式的加密和zlib压缩的地形数据(仅在auth之后可用)。XXX
是Google格式的(x,y,level),而YYY是包含数据的节点。
/flatfile?f1c-XXX-d.YYY.ZZZ-未知(也许是矢量数据)
要访问数据,需要执行以下操作:
1)进行身份验证。流程包括对/geauth的两个POST请求。什么数据传输是目前未知(从数据复制粘贴
的实际谷歌地球连接的只是作品的tcpdump)。第二个POST请求包含会话ID-80字节的字符串(请参阅gefetch_auth.c)。
使用此字符串作为cookie(请参阅gefetch_http.c)使我们可以访问/flatfile url。
2)获取/dbRoot.v5,其中包含解密密钥。该文件是即使没有身份验证也可用。有关解密算法,请参阅gefetch_crypt.c。
经过这两个步骤,一个将可以访问/flatfile url,并且能够解密检索到的数据。
解密后即可使用JPEG。其他数据也使用zlib压缩,并带有8个字节的标头。
先搞定身份验证
先用NGINX代理解决跨域问题
server {
listen 8089;
location / {
proxy_pass http://localhost:8080;
}
location /googlemap/ {
proxy_pass http://kh.google.com/;
}
location /googlemapAuth {
proxy_pass https://kh.google.com/geauth?ct=pro/;
}
}
下文google_map_post_auth_body是用fiddler抓包获取的二进制文件
async function fuckCookie() {
const res_google_map_post_auth_body = await fetch(
"http://localhost:8081/google_map_post_auth_body"
);
const google_map_post_auth_body_blob = await res_google_map_post_auth_body.blob();
const res_body = await fetch("/googlemapAuth", {
body: google_map_post_auth_body_blob,
headers: {},
method: "POST",
});
const arrayBuffer = (window._arrayBuffer = await res_body
.clone()
.arrayBuffer());
let str_arrayBuffer = "";
// console.log("长度", arrayBuffer.byteLength);
switch (arrayBuffer.byteLength) {
case 112:
str_arrayBuffer = String.fromCharCode.apply(
null,
new Uint8Array(arrayBuffer.slice(8, 88)) //截取长度是未经验证的
);
break;
case 124:
str_arrayBuffer = String.fromCharCode.apply(
null,
new Uint8Array(arrayBuffer.slice(8, 100))
);
break;
case 136:
str_arrayBuffer = String.fromCharCode.apply(
null,
new Uint8Array(arrayBuffer.slice(8, 112))
);
break;
case 144:
str_arrayBuffer = String.fromCharCode.apply(
null,
new Uint8Array(arrayBuffer.slice(8, 120))
);
break;
default:
debugger;
}
// console.log(
// "完整字符串",
// String.fromCharCode.apply(null, new Uint8Array(arrayBuffer))
// );
// console.log("截出来的cookie", str_arrayBuffer);
document.cookie = `SessionId="${str_arrayBuffer}"; path=/;`;
// console.log("document.cookie ", document.cookie);
}
fuckCookie();
setInterval(fuckCookie, 1000 * 60 * 10);
再利用Cesium去获取加载数据
var geeMetadata = new Cesium.GoogleEarthEnterpriseMetadata(
new Cesium.Resource({
url: "/googlemap",
})
);
var viewer = new Cesium.Viewer("cesiumContainer", {
imageryProvider: new Cesium.GoogleEarthEnterpriseImageryProvider({
metadata: geeMetadata,
}),
terrainProvider: new Cesium.GoogleEarthEnterpriseTerrainProvider({
metadata: geeMetadata,
}),
baseLayerPicker: false,
});
到现在都没获取到历史影像, 要做到这一点, 需要 (放弃了,太难啦):
1.获取当前范围有哪些日期可用 (用于制作历史时间滑动条)
2.修改Cesium源码, 根据选中的时间去获取历史影像(根据参考2, 构造url即可)
示例url: https://khmdb.google.com/flatfile?db=tm&f1-02000123-i.19-fa99b
最后附上url中 16进制日期 转成 字符串 的方法
//url 的 -fa99b 代表哪一天
var binarystr=(parseInt('fab9f',16).toString(2))
var yearbin = binarystr.slice(0,11) //11 5 4
var monthbin = binarystr.slice(11,15) //11 5 4
var daybin= binarystr.slice(15) //11 5 4
var year = parseInt(yearbin,2)
var month = parseInt(monthbin,2)
var day = parseInt(daybin,2)
console.log(year,month,day)//2004 25 11