Google地图下载
Google地圖下載
谷歌地圖是在線地圖,然而有些時候我們需要將其下載到本地進行相關(guān)操作和使用,截圖再拼接固然很好,但是不精確和效率低,本程序?qū)⑾螺d指定區(qū)域地圖到本地。此文將回顧并記錄其中下載歷程,進行分享。
谷歌地圖訪問受限,因此地圖信息采集集中在八九地圖(內(nèi)有谷歌地圖API接口,可查看谷歌地圖)
通過審查元素(F12)發(fā)現(xiàn)谷歌加載的地圖瓦片,一個個瓦片拼接成整個地圖。
而且這些瓦片的鏈接非常規(guī)律
https://mt1.google.cn/maps/vt?lyrs=s%40781&hl=zh-CN&gl=CN&x=107915&y=49662&z=17
上述鏈接是午門東鳳翅樓衛(wèi)星照片,觀察可知坐標(biāo)x=107915, y= 49662,其中的z指的是地圖層級,z=17,這是第17層(1-20,越大越清晰)
通過坐標(biāo)的簡單變換和圖顯示出來的瓦片圖分析我們可以看出,這個谷歌地圖的坐標(biāo)軸的指向。它的x軸是像東增西減的,它的外軸是南增北減的。
有了坐標(biāo)之后,通過對單張瓦片地圖的爬取,我們就可以得到我們想要范圍內(nèi)的所有瓦片圖。然后進行拼接,就可以得到我們想要范圍內(nèi)的整張地圖。
上述就是此程序的基本邏輯和原理。
我用的是urllib進行爬取,因為它一條指令就可以對圖片進行爬取和存儲,非常方便。
首先提取的是左上角的瓦片的坐標(biāo),然后進行相應(yīng)的迭代循環(huán),從而取得整個想要的范圍內(nèi)的瓦片。每個瓦片圖都用其坐標(biāo)進行命名以便拼接。
爬了一次之后,就遇到了一個大問題,它將我的ip封掉了,我無法查看谷歌地圖了(好像兩天才會解封)。查了一些資料之后,發(fā)現(xiàn)我們需要將我們的爬蟲偽裝一下,加一個headers。然后里面是一個user agent的一個字典。然后又發(fā)現(xiàn)了一個叫fake user agent的一個庫,這個庫里有很多各式各樣的可以模擬各種瀏覽器的user agent,加入這個之后就暢行無阻了,不會產(chǎn)生相應(yīng)的問題了。
from fake_useragent import UserAgent def weizhuanggetmap(x,y):fakeagent = UserAgent().randomheaders = {"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="+cengjilocal = 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)還有一個問題就是我們范圍設(shè)置的問題,比如說我們想。爬一個東西寬十公里,南北長20千米的一個圖,我們需要 多少塊,南北爬多少塊都是需要計算的。我只爬了16層級的谷歌地圖,因此我將以16層級的谷歌地圖為例說明。
一塊谷歌地圖瓦片的像素是256x256像素。
在北緯50°的倫敦,我們通過比例尺計算出它是350米乘350米的一塊。
在北緯40°的北京,我們通過比例尺計算出它是450米乘450米的一塊。
在北緯34°的洛杉磯,我們通過比例尺計算出它是484米乘484米的一塊。
單塊兒瓦片所覆蓋的米數(shù)不同,也就直接導(dǎo)致了相同公里數(shù)它所需的瓦片數(shù)不一樣。在程序內(nèi)直接進行下映的計算機即可。
程序內(nèi)還使用了os庫來檢驗文件的下載情況,看看它是否存在。有極少數(shù)情況下,有一兩張瓦片會下載失敗。還有些情況下會因為中途停止。而我們不知道下到了哪里,所以說引入了os庫,我們可以接著上面已經(jīng)下載的繼續(xù)下載。
全部下載完成之后,我們即將進行圖像的拼接,這里使用的是Python的pillow的庫。
首先創(chuàng)建同樣像素大小的照片作為背景,然后逐個迭代引入我們的瓦片進行粘貼。
但是由于電腦的運行內(nèi)存限制,超過1萬張便會卡頓。**甚至無法運行。于是,超過1萬張的我們將對其進行分行粘貼,以多少行為一組進行粘貼,最后再將粘貼好的幾張大的衛(wèi)星圖再進行拼接。
有時候地圖范圍會進入海域,而有谷歌地圖的一些深海并沒有相應(yīng)層級的。這時網(wǎng)頁是404Error報錯,所以這時候需要引入urllib.error,然后進行識別這個錯誤。識別出這個錯誤之后進行替換,我們用一張線藍色的近似于大海顏色的照片進行替換,將這個瓦片進行補全。
import urllib.error except urllib.error.HTTPError: #關(guān)于大海print("第"+str(i)+"行,第"+str(a)+"張"+"是一片海")sea = Image.new("RGB",(256,256),(68,88,137)) #創(chuàng)建一張藍色照片替代local = mapspath + "\\" + str(x) + str(y) + ".jpg"sea.save(local,"jpeg")sea.close()print("替換完成")但是還有一個思路是這時候先空過去等到拼接的時候。設(shè)置一個海藍色背景為底,然后拼接的時候用一個try except打不開就直接跳過留下藍色背景。
關(guān)于大圖片報錯問題
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:returnpixels = 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攻擊。但是我們只是單純的想打開這張圖片,于是我們可以在開頭修改這個參數(shù)。
Image.MAX_IMAGE_PIXELS = None這樣就不會產(chǎn)生報錯,程序得以運行。
樣例:
倫敦
鏈接: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
總結(jié)
以上是生活随笔為你收集整理的Google地图下载的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Markup解析xml字符串
- 下一篇: 恢复谷歌翻译的究极方法