python 地图包_Google地图下载

Google地图下载

谷歌地图是在线地图,然而有些时候我们需要将其下载到本地进行相关操作和使用,截图再拼接固然很好,但是不精确和效率低,本程序将下载指定区域地图到本地。此文将回顾并记录其中下载历程,进行分享。

谷歌地图访问受限,因此地图信息采集集中在八九地图(内有谷歌地图API接口,可查看谷歌地图)

通过审查元素(F12)发现谷歌加载的地图瓦片,一个个瓦片拼接成整个地图。

而且这些瓦片的链接非常规律

https://mt1.google.cn/maps/vt?lyrs=s%40781&hl=zh-CN&gl=CN&x=107915&y=49662&z=17

上述链接是午门东凤翅楼卫星照片,观察可知坐标x=107915, y= 49662,其中的z指的是地图层级,z=17,这是第17层(1-20,越大越清晰)

通过坐标的简单变换和图显示出来的瓦片图分析我们可以看出,这个谷歌地图的坐标轴的指向。它的x轴是像东增西减的,它的外轴是南增北减的。

有了坐标之后,通过对单张瓦片地图的爬取,我们就可以得到我们想要范围内的所有瓦片图。然后进行拼接,就可以得到我们想要范围内的整张地图。

上述就是此程序的基本逻辑和原理。

我用的是urllib进行爬取,因为它一条指令就可以对图片进行爬取和存储,非常方便。

首先提取的是左上角的瓦片的坐标,然后进行相应的迭代循环,从而取得整个想要的范围内的瓦片。每个瓦片图都用其坐标进行命名以便拼接。

爬了一次之后,就遇到了一个大问题,它将我的ip封掉了,我无法查看谷歌地图了(好像两天才会解封)。查了一些资料之后,发现我们需要将我们的爬虫伪装一下,加一个headers。然后里面是一个user agent的一个字典。然后又发现了一个叫fake user agent的一个库,这个库里有很多各式各样的可以模拟各种浏览器的user agent,加入这个之后就畅行无阻了,不会产生相应的问题了。

from fake_useragent import UserAgent

def weizhuanggetmap(x,y):

fakeagent = UserAgent().random

headers = {"User-Agent":fakeagent}

url = "https://mt0.google.cn/maps/vt?lyrs=s%40781&hl=zh-CN&gl=CN&x="+str(x)+"&"+"y="+str(y)+"&z="+cengji

local = mapspath + "\\" + str(x) + str(y) + ".jpg"

opener = urllib.request.build_opener()

opener.addheaders = [('User-agent', fakeagent)]

urllib.request.install_opener(opener)

urllib.request.urlretrieve(url,local)

还有一个问题就是我们范围设置的问题,比如说我们想。爬一个东西宽十公里,南北长20千米的一个图,我们需要 多少块,南北爬多少块都是需要计算的。我只爬了16层级的谷歌地图,因此我将以16层级的谷歌地图为例说明。

一块谷歌地图瓦片的像素是256x256像素。

在北纬50°的伦敦,我们通过比例尺计算出它是350米乘350米的一块。

在北纬40°的北京,我们通过比例尺计算出它是450米乘450米的一块。

在北纬34°的洛杉矶,我们通过比例尺计算出它是484米乘484米的一块。

单块儿瓦片所覆盖的米数不同,也就直接导致了相同公里数它所需的瓦片数不一样。在程序内直接进行下映的计算机即可。

程序内还使用了os库来检验文件的下载情况,看看它是否存在。有极少数情况下,有一两张瓦片会下载失败。还有些情况下会因为中途停止。而我们不知道下到了哪里,所以说引入了os库,我们可以接着上面已经下载的继续下载。

全部下载完成之后,我们即将进行图像的拼接,这里使用的是Python的pillow的库。

首先创建同样像素大小的照片作为背景,然后逐个迭代引入我们的瓦片进行粘贴。

但是由于电脑的运行内存限制,超过1万张便会卡顿。**甚至无法运行。于是,超过1万张的我们将对其进行分行粘贴,以多少行为一组进行粘贴,最后再将粘贴好的几张大的卫星图再进行拼接。

有时候地图范围会进入海域,而有谷歌地图的一些深海并没有相应层级的。这时网页是404Error报错,所以这时候需要引入urllib.error,然后进行识别这个错误。识别出这个错误之后进行替换,我们用一张线蓝色的近似于大海颜色的照片进行替换,将这个瓦片进行补全。

import urllib.error

except urllib.error.HTTPError: #关于大海

print("第"+str(i)+"行,第"+str(a)+"张"+"是一片海")

sea = Image.new("RGB",(256,256),(68,88,137)) #创建一张蓝色照片替代

local = mapspath + "\\" + str(x) + str(y) + ".jpg"

sea.save(local,"jpeg")

sea.close()

print("替换完成")

但是还有一个思路是这时候先空过去等到拼接的时候。设置一个海蓝色背景为底,然后拼接的时候用一个try except打不开就直接跳过留下蓝色背景。

关于大图片报错问题

PIL.Image.DecompressionBombError: Image size (778633216 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack.

这是库里面的源码

def _decompression_bomb_check(size):

if MAX_IMAGE_PIXELS is None:

return

pixels = size[0] * size[1]

if pixels > 2 * MAX_IMAGE_PIXELS:

raise DecompressionBombError(

"Image size (%d pixels) exceeds limit of %d pixels, "

"could be decompression bomb DOS attack." % (pixels, 2 * MAX_IMAGE_PIXELS)

)

if pixels > MAX_IMAGE_PIXELS:

warnings.warn(

"Image size (%d pixels) exceeds limit of %d pixels, "

"could be decompression bomb DOS attack." % (pixels, MAX_IMAGE_PIXELS),

DecompressionBombWarning,

)

可见一旦图片大于一倍或者两倍MAX_IMAGE_PIXELS就会报错,说这可能是DOS攻击。但是我们只是单纯的想打开这张图片,于是我们可以在开头修改这个参数。

Image.MAX_IMAGE_PIXELS = None

这样就不会产生报错,程序得以运行。

样例:

伦敦

链接:https://pan.baidu.com/s/1nkpWU__Jdycgt29nOM0Q5w

提取码:t5jg

阿尔布开克

链接:https://pan.baidu.com/s/1mHgZFECCumSXn7NmIqwm8Q

提取码:43bb

洛杉矶

链接:https://pan.baidu.com/s/13cjoTBsFYEhXZ9EYnr6-iA

提取码:4h5w

源码及样例

链接:https://pan.baidu.com/s/1bGTUjKkGlTUTHTltPbMHxg

提取码:c99l

原文链接:https://blog.csdn.net/victory0431/article/details/107498935

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值