以目前互聯網經常使用的WebMecator爲例python
這個問題本質上是對海量小數據的管理,不少互聯網大廠都有比較成熟的方案,只須要根據具體狀況進行選擇調整便可。sql
採用sqlite
存儲在多個sqlite中,sqlite文件名保證了惟一性,與(row,column, level)一一對應。json
注意sqlite單文件的大小不要太大。服務器
使用HDFS等網絡化存儲方案。網絡
# -*- coding: utf-8 -*- """下載區域影像 從第一層到指定層 多線程版 存儲到sqlite中 """ import requests # python3的thread模塊 import _thread import random import time from random import random import os.path import QuadKey.quadkey as quadkey import shutil import secrets as secrets import sqlite_util as dbutil # 下載的最細層 tileZoom = 10 rootTileDir = "tiles_db" # 分的db數量,採用質數 db_num = 1511 lat_min = -90 lat_max = 90 lon_min = -180 lon_max = 180 # MS doesn't want you hardcoding the URLs to the tile server. This request asks for the Aerial # url template. Replace {quadkey} response = requests.get("https://dev.virtualearth.net/REST/V1/Imagery/Metadata/Aerial?key=%s" % (secrets.bingKey)) # 返回結果 data = response.json() print(data) # grabs the data we need from the response. # 例如:http://ecn.{subdomain}.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=7786 tileUrlTemplate = data['resourceSets'][0]['resources'][0]['imageUrl'] # 例如:['t0', 't1', 't2', 't3'] imageDomains = data['resourceSets'][0]['resources'][0]['imageUrlSubdomains'] if (os.path.exists(rootTileDir) == False): os.mkdir(rootTileDir) bingTilesDir = os.path.join(rootTileDir, "bing") if (os.path.exists(bingTilesDir) == False): os.mkdir(bingTilesDir) def get_tiles_by_pixel(tilePixel): """ 下載該點之上的瓦片 :param lat: :param lon: :return: """ """get pixel coordinates""" # tilePixel = quadkey.TileSystem.geo_to_pixel((lat, lon), tileZoom) # print(tilePixel) pixel = tilePixel geo = quadkey.TileSystem.pixel_to_geo(pixel, tileZoom) # 計算四鍵 qk = quadkey.from_geo(geo, tileZoom) # 四鍵 qkStr = str(qk) # qkArray = [] for index in range(tileZoom): qkArray.append(qkStr[0:index + 1]) print(qkArray) # 存放路徑 for qk in qkArray: # db位置 dbPath = "%s/%s.db" % (bingTilesDir, int(qk) % db_num ) print(dbPath) if (os.path.exists(dbPath) == False): # os.mkdir(dbPath) dbutil.create_db(dbPath) # 下載影像 if (dbutil.is_exists(dbPath, qk)): # already downloaded dbutil.save_images(dbPath, qk) ok = 1 else: print("下載中", end='') url = tileUrlTemplate.replace("{subdomain}", imageDomains[0]) url = url.replace("{quadkey}", qk) url = "%s&key=%s" % (url, secrets.bingKey) response = requests.get(url, stream=True) print(response) dbutil.insert(dbPath, qk, response.content) del response # 強制睡一會,防止bing服務器限制 sleepTime = random() * 3 time.sleep(sleepTime) # 左上爲原點 tilePixelMax = quadkey.TileSystem.geo_to_pixel((lat_max, lon_max), tileZoom) tilePixelMin = quadkey.TileSystem.geo_to_pixel((lat_min, lon_min), tileZoom) print(tilePixelMax) print(tilePixelMin) tile_pixel_list = [] for x in range(tilePixelMin[0], tilePixelMax[0], 256): for y in range(tilePixelMax[1], tilePixelMin[1], 246): tile_pixel_list.append((x, y)) # 取決與服務器的硬件性能 thread_pause = 30 for i in range(len(tile_pixel_list)): print("處理"+str(i)) _thread.start_new_thread(get_tiles_by_pixel,(tile_pixel_list[i],) ) if(i % thread_pause == (thread_pause-1)): print("讓正常運行的線程執行完,睡眠開始") time.sleep(5) print("睡眠結束") # _thread.start_new_thread( get_tiles_by_pixel, ( ) ) print('下載完畢')
能夠優化的點不少多線程
更多的詳情見小專欄文章:GIS之家小專欄app
文章尾部提供源代碼下載,對本專欄感興趣的話,能夠關注一波dom