智慧城市项目中经常会涉及到离线部署的问题,底图就是不得不解决的一个问题点了。
此前写过的底图爬虫适用于全球底图的爬取,但实际上很多时候做的只是一个范围的,不需要那么大的数据量,因此写了一个根据
经纬度范围爬取的脚本。mapbox底图需要自己申请token
import math
import os
import urllib.request
#起始经纬度
startCoor=[119.2,35.2]
#终止经纬度
endCoor=[121.1,37.2]
#下载目录
rootDir=r"D:\cs"
res={
0:156543.033928023,
1:78271.5169640117,
2:39135.7584820059,
3:19567.8792410029,
4:9783.93962050147,
5:4891.96981025073,
6:2445.98490512537,
7:1222.99245256268,
8:611.496226281342,
9:305.748113140671,
10:152.874056570335,
11:76.4370282851677,
12:38.2185141425838,
13:19.1092570712919,
14:9.55462853564596,
15:4.77731426782298,
16:2.38865713391149,
17:1.19432856695575,
18:0.597164283477873
}
tileSize=256
originX = -20037508.342789244
originY = 20037508.342789244
#经纬度投影到平面坐标
def millerToXY(lon, lat):
x=6378137*math.pi*lon/180
y=6378137*math.log(math.tan(math.pi/360*(lat+90)))
return (x,y)
start=millerToXY(startCoor[0],startCoor[1])
end=millerToXY(endCoor[0],endCoor[1])
#下载图片
def download_img(img_url, path,imgname):
request = urllib.request.Request(img_url)
try:
response = urllib.request.urlopen(request)
filename = path+"\\"+imgname
if (response.getcode() == 200):
with open(filename, "wb") as f:
f.write(response.read()) # 将内容写入图片
return filename
except:
return "failed"
#计算行列号
def calXY(x,y,level):
reso=res[level]
sx=(x-originX)/(reso*tileSize)
xy=(y-originY)/(reso*tileSize)
return (sx,xy)
#print(sx,xy)
#1-5级别全部爬取
for level in range(1, 6):
num = int(math.pow(2, level))
for x in range(num):
for y in range(num):
url="https://a.tiles.mapbox.com/v4/mapbox.dark/"+ str(level) + "/" + str(x) + "/" + str(y) + ".png"+"?access_token=token"
#根目录
isExists = os.path.exists(rootDir)
if not isExists:
os.mkdir(rootDir)
# 第一级目录
pathOne = rootDir + "\\" + str(level)
isExists = os.path.exists(pathOne)
if not isExists:
os.mkdir(pathOne)
# 第二级目录
path = rootDir + "\\" + str(level) + "\\" + str(x)
isExists = os.path.exists(path)
if not isExists:
os.mkdir(path)
download_img(url, path, str(y) + ".png")
#爬取经纬度范围内的
for level in range(6,11):
print(level)
ss = calXY(start[0], start[1], level)
ee = calXY(end[0], end[1], level)
x0 = math.floor(ss[0])
if (math.fabs(math.floor(ss[1])) > math.fabs(math.floor(ee[1]))):
y0 = math.floor(math.fabs(ee[1]))
else:
y0 = math.floor(math.fabs(ss[1]))
#每级边缘多爬取一张
num = math.ceil(ee[0] - x0) + 1
for x in range(x0,x0+num):
for y in range(y0,y0+num):
url="https://a.tiles.mapbox.com/v4/mapbox.dark/"+ str(level) + "/" + str(x) + "/" + str(y) + ".png"+"?access_token=token"
#根目录
isExists = os.path.exists(rootDir)
if not isExists:
os.mkdir(rootDir)
# 第一级目录
pathOne = rootDir + "\\" + str(level)
isExists = os.path.exists(pathOne)
if not isExists:
os.mkdir(pathOne)
# 第二级目录
path = rootDir + "\\" + str(level) + "\\" + str(x)
isExists = os.path.exists(path)
if not isExists:
os.mkdir(path)
download_img(url, path, str(y) + ".png")