Pythonはbing地図を取得して自分のTMSサービスを発表する(二)大量の瓦のアクセス問題を解決する

5433 ワード

ピラミッド構造の瓦の数はどのくらいですか
現在インターネットでよく使われているWebMecatorを例に挙げると
  • 第1層:256*256映像タイル4枚(JPGやPNGなど)
  • 第2層:42
  • 第3層:43
  • は、例えば、第1層から第18層までの瓦の総数(等比数列加算)91625968980個、約916億個を順次類推する.記憶空間推定は100 T近くである.

  • 瓦がファイルシステムに直接格納される欠点
  • ファイルシステムファイル数、サイズの制限
  • 容易な移行、バックアップ
  • ソリューション
    この問題は本質的に大量の小データの管理であり、多くのインターネット大手工場には比較的成熟した方案があり、具体的な状況に応じて選択調整すればよい.
    スタンドアロンストレージ
    sqliteを使用して複数のsqliteに格納され、sqliteファイル名は一意性を保証し、(row,column,level)に1つ1つ対応します.
  • (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の家小欄を参照
    記事の末尾にソースコードのダウンロードがあり、このコラムに興味があれば、注目してみてください.