Python获取 bing 地图发布自己的 TMS 服务(二)解决海量瓦片存取问题
金字塔结构的瓦片数量有多大
以目前互联网常用的WebMecator为例
- 第一层:4幅256*256影像瓦片(JPG或PNG等)
- 第二层:42
- 第三层:43
- 依次类推
比如计算第1层至第18层的瓦片总数目(等比数列求和)91625968980个,大约916亿。存储空间估算在近百T。
瓦片直接存储在文件系统中的缺点
- 文件系统对文件数量、大小的限制
- 不易迁移、备份
- 等等
解决方案
这个问题本质上是对海量小数据的管理,很多互联网大厂都有比较成熟的方案,只需要根据具体情况进行选择调整即可。
单机存储
采用sqlite
存储在多个sqlite中,sqlite文件名保证了唯一性,与(row,column, level)一一对应。
- (row,column, level)可以转为唯一数字,比如QuadKey,或者其他编码方式
- sqlite移动与管理就比较方便。
注意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('下载完毕')
可以优化的点很多
- 修改线程使用方式
- 提高查询影像是否存在的效率
- 减少建立sqlite连接的次数
源码
更多的详情见小专栏文章:GIS之家小专栏
文章尾部提供源代码下载,对本专栏感兴趣的话,可以关注一波
Python获取 bing 地图发布自己的 TMS 服务(二)解决海量瓦片存取问题的更多相关文章
- python获取bing地图发布自己的TMS服务(一)下载瓦片
部分结果 bing地图瓦片使用QuadKey作为命名方式. QuadKey简介 如何计算quadkey 在给定level下,把行号tileY和列号tileX转换为2进制,然后行列交叉存储,再转换为4进 ...
- geotrellis使用(三十一)使用geotrellis直接将GeoTiff发布为TMS服务
前言 传统上我们需要先将Tiff中存储的影像等数据先切割成瓦片,而后再对外提供服务.这样的好处是服务器响应快,典型的用空间来换时间的操作.然而这样造成的问题是空间的巨大浪费,一般情况下均需要存储1-1 ...
- geotrellis使用(三十二)大量GeoTiff文件实时发布TMS服务
前言 在上一篇文章中我讲了如何直接将Geotiff文件发布为TMS服务,在其中只讲了单幅Geotiff的操作,其实单幅这种量级的数据对Geotrellis来说就是杀鸡焉用牛刀,Geotrellis针对 ...
- 获取bing每日图片
http://global.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=en-US 其中idx表示倒数第几张图片 ...
- 使用Python获取Linux系统的各种信息
哪个Python版本? 当我提及Python,所指的就是CPython 2(准确的是2.7).我会显式提醒那些相同的代码在CPython 3 (3.3)上是不工作的,以及提供一份解释不同之处的备选代码 ...
- 获取bing图片并自动设置为电脑桌面背景(C++完整开源程序)
众所周知,bing搜索网站首页每日会更新一张图片,张张漂亮(额,也有一些不合我口味的),特别适合用来做电脑壁纸. 我们想要将bing网站背景图片设置为电脑桌面背景的通常做法是: 上网,搜索bing 找 ...
- Python爬取地图瓦片
由于要在内网开发地图项目,不能访问在线的地图服务了,就想把地图瓦片下载下来,网上找了一些下载器都是需要注册及收费的,否则下载到的图都是打水印的,如下: 因为地图瓦片就是按照层级.行.列规则组织的一张张 ...
- 【开源程序(C++)】获取bing图片并自动设置为电脑桌面背景
众所周知,bing搜索网站首页每日会更新一张图片,张张漂亮(额,也有一些不合我口味的),特别适合用来做电脑壁纸. 我们想要将bing网站背景图片设置为电脑桌面背景的通常做法是: 上网,搜索bing 找 ...
- python提取百度经验<标题,发布时间,平均流量,总流量,具体的链接>
之前想研究下怎么抓网页数据.然后就有了下面的练习了. 如有BUG.也纯属正常. 只是练习.请勿投入产品使用. #!/usr/bin/python # -*- coding: utf-8 -*- #Fi ...
随机推荐
- 基于docker搭建Jenkins+Gitlab+Harbor+Rancher架构实现CI/CD操作(续)---Harbor的安装
前期安装文档:https://www.cnblogs.com/lq-93/p/11828626.html Harbor的作用: 开发提交代码至gitlab容器中,Jenkins拉取代码构建镜像 ...
- 利用Python获取统计自己的qq群成员信息
利用python获取自己的qq群成员信息! 首先说明一下需要使用的工具以及技术:python3 + selenium selenium安装方法:pip install selenium 前提:获取自己 ...
- 创建基于OData的Web API - Knowledge Builder API, Part I:Business Scenario
在.NET Core 刚刚1.0 RC的时候,我就给OData团队创建过Issue让他们支持ASP.NET Core,然而没有任何有意义的答复. Roadmap for ASP.NET Core 1. ...
- JS简单循环遍历json数组的方法
例如数据库里面的json字符串是这样的 1 2 3 4 5 var str = '[{"name":"宗2瓜","num":"1& ...
- docker入门篇
在网上的教程中,大多数是建议利用linux来安装docker,在此我也建议大家用linux安装,为什么?请看下图 docker使用go语言开发,并且运行在linux系统下,而如果想用window运行, ...
- ArrayList和LinkedList的源码学习,理解两者在插入、删除、和查找的性能差异
List的使用 List的子类 1). ArrayList 数据结构:数组 2). Vector 数据结构:数组 3). LinkedList 数据结构:循环双向链表 ArrayList .Vecto ...
- 安卓Android碎片fragment实现静态加载
静态加载好后的界面如下,两个碎片分别位于一个活动的左边和右边: 左边和右边分别为一个碎片,这两个碎片正好将一整个活动布满.一个活动当中可以拥有多个碎片,碎片的含义就是可以在同一个UI界面下,将这个界面 ...
- Selenium+Java(六)Selenium 强制等待、显式等待、隐实等待
前言 在实际测试过程中,由于网速或性能方面的原因,打开相应的网页后或在网页上做了相应的操作,网页上的元素可能不会马上加载出来,这个时候需要在定位元素前等待一下,等元素加载出来后再进行定位,根据实际使用 ...
- urllib练习
# coding = utf-8 """ 解析https://www.kuaidaili.com/free/网站里的代理地址, 并测试是否可用 ""& ...
- c#-EntitySet<TEntity>
MSDN 解释: https://msdn.microsoft.com/zh-cn/library/bb341748.aspx 为 LINQ to SQL 应用程序中的一对多关系和一对一关系的集合方提 ...