笔者在实验室某个GIS项目中必须需要一定数据级的地图数据。在百般无奈下,笔者开始从Google Map爬数据。从Google Map上采集一定量的数据有作实验。
从Google Map爬数据的原理
Google Map所采用的是Mercator坐标系。何为Mercator坐标系?读者可以详见{链接}。在Google Map也是以金字塔模型的方式来组织切图文件的。至于,它的后端处理或者存储方式或者文件命名方式是怎么样,笔者不得而知。笔者只能从URL等方面进行分析,大概确定其地图文件的组织方式。在金字塔模型中,地图分成若干层,每一层数据的分辨率为上层的4倍(横向与纵向各2倍)。同时,每一层数据的分辨是极其巨大,而且成指数形式增加。如果一下子,将一层的数据作为一个文件返回给用户,无论从网络的传输能力、CPU处理能力还是内存的存储能力而言都是无法做到的。而且用户所观看的只是地图的某一层的某一块区域。因而,一般都会将地图数据进行切图,即进行切分,将地图数据切成分辨率相等的若干块。因而,我们可以得知,每一层数据集的文件数为上层的4倍。
笔者使用GoogleChrome来查看Google Map的Resources,图如下:
我们可以清楚地看到,在Google Map的地图文件并不是一次加载一整张,而是分成若干块,每一块的分辨为256*256。同时,我们也得到了每一块地图的地址,例如http://mt0.google.com/lyrs=m@176000000&hl=zh-CN&src=app&x=1&y=1&z=1&s=Ga.png。其中x、y是决定文件左上角坐标的参数,z为决定文件层次的参数。通过向Google Map服务器请求,我们可以得到第0层具有1块。从而第level层,具有2^level*2^level块,即x、y的取值范围为[0,2^level-1]。第level层每一块数据的横向经度差为360/2^level,纵向纬度差为180/2^level。
x=0&y=0&z=0 |
![]() |
x=0&y=0&z=1
|
x=1&y=0&z=1 |
![]() |
![]() |
x=0&y=1&z=1 | x=1&y=1&z=1 |
![]() |
![]() |
我们可以得知,x=xx,y=yy,z=zz的这块数据,所在的图层为zz层,该图层中每块数据的经度差为360/2^zz,纬度差为180/2^zz,左上角的经纬度为(360/2^zz*xx-180, 180/2^zz*yy-90)。同样,我们也可从一个数据块的左上角经纬度反推出这个文件在zz层的x与y。这也就是我们从Google Map爬数据的原理。
从Google Map爬数据有何难点?
1. 在国内由于政治等原因,连接Google服务器会有所中断。
2. Google的Web服务器,或者Google防火墙,会对某一台客户端的请求进行统计。如果一段时间内,请求数超过一定的值,此后的请求会直接被忽略。据说,当一天中,来自某一个IP的请求数超过7000个时,此后的请求后直接被忽略。
3. 单线程操作的效率太低,多线程情况下,效率会有很大提升。
4. Google服务器会对每个请求检查,判断是否来自浏览器还是来自爬虫。
5. 对于已下载的文件无须下载,即爬虫必须拥有“断点续传”的功能。不能由于网络的中断或者人为的中断,而导致之前的进度丢失。
对于这些难点有何解决方案
1. 对于第1点难点,我们可以使用国外的服务器作为我们的代理。这样,我们通过国外的服务器来请求Google Map。而对