您的位置:首页 > 编程语言 > Go语言

Google Map Tile 下载脚本

2010-04-30 12:54 211 查看
http://bbs.esrichina-bj.cn/ESRI/viewthread.php?tid=65904 (我没有用过,有环境的朋友可以试试)

早就写了,一直都有问题没好意思放出来,自己最近这段时间着迷于python编程,但进步缓慢,昨晚看《可爱的python》,得到启发,还是拿出来让大家一起帮忙修改完善。
毛病很多,比如:线程,不太会用,下载进度计数上面有问题;又如:不能暂停下载后接着下载。
总之希望大家多多交流,把这个小工具修改完善。
dmc.py源代码:

代码

#coding=utf-8

#Filename:dmc.py

import cmath,urllib,os,math,random,sys,time,threading

class Cdt:

def __str__(self):

return '{x = %s,y = %s}'%(self.x,self.y)

def createName(num,type):

#'''创建文件夹/文件名称'''

temp = '00000000'+str(hex(int(num)))[2:]

return type + temp[::-1][0:8][::-1]

def getPixelFromCdt(x,y,z):

#'''根据经纬度坐标以及缩放等级获取像素坐标'''

pixel = Cdt()

sinLatitude = cmath.sin(y * cmath.pi / 180)

pixel.x = ((x + 180) / 360) * 256 * (2**z)

temp = cmath.log((1+sinLatitude)/(1-sinLatitude))

pixel.y = abs((0.5 - temp / (4 * cmath.pi))*256*(2**z))

return pixel

def getTileFromPixel(pixel):

#'''根据像素坐标获取切片'''

tile = Cdt()

tile.x = math.floor(pixel.x / 256)

tile.y = math.floor(pixel.y / 256)

return tile

def getTileFromCdt(x,y,z):

#'''根据经纬度坐标以及缩放等级获取切片'''

return getTileFromPixel(getPixelFromCdt(x,y,z))

def downloadTile(remoteFile,localFile):

#'''下载远程文件到本地'''

urllib.urlretrieve(remoteFile,localFile)

def createDir(dirPath):

#'''创建文件夹'''

if not os.path.exists(dirPath):

os.makedirs(dirPath)

def createRemoteUrl(x,y,z):

#'''创建远程tile地址'''

port = str(random.randint(0,3))

x = str(x)

y = str(y)

z = str(z)

return 'http://mt'+port+'.google.cn/vt/v=w2.115&hl=zh-CN&gl=cn&x='+x+'&s=&y='+y+'&z='+z

def createLocalFile(x,y,z,lvRange,cacheDir):

#'''创建缓存本地路径'''

#计算<等级目录>名称

i = int(z) - lvRange[0]

l = ''

if i < 10:

l = 'L0' + str(i)

elif i >= 10 and i <= lvRange[len(lvRange) - 1]:

l = 'L' + str(i)

#计算<行目录>和<(列)图片>名称

r = createName(y,'R')

c = createName(x,'C')

#拼装本地路径

return cacheDir + os.sep + l + os.sep + r + os.sep + c + '.png'

def createCacheDir(rowName,lv,row,xRange):

#'''创建缓存目录'''

createDir(rowName)#创建行文件夹

for col in xRange:

#localTile = rowName + os.sep + createName(col,'C') + '.png'

tempTask.append('%s,%s,%s'%(lv,row,col))

def createLvCache(extent,lv,dir):

#'''创建某一等级下一行cache'''

startTile = getTileFromCdt(extent[0],extent[1],lv)

endTile = getTileFromCdt(extent[2],extent[3],lv)

xRange = range(int(startTile.x),int(endTile.x))

yRange = range(int(startTile.y),int(endTile.y))

for row in yRange:

rowName = dir + os.sep + createName(row,'R')

createCacheDir(rowName,lv,row,xRange)

def createCacheStruc(extent,lvRange,cacheDir):

#'''创建缓存目录结构及计算tile'''

global tempTask

tempTask=[]#存储cache下载列表

count = 0

print '创建Cache目录及计算tile数目...'

for lv in lvRange:

lvName = 'L0' + str(count)#lvName:等级文件夹名

createDir(cacheDir +os.sep + lvName)#创建lv等级的文件夹,例如:lv01,lv02...

createLvCache(extent,lv,cacheDir +os.sep + lvName)#创建完等级文件夹后,添加该等级的行文件夹,例如:R000001a0

count += 1

def loadErrorFile(url):

'''

加载错误任务

'''

os.rename(url,url+'bak')

f = open(url+'bak')

return f.readlines()

def loadTask(task,threadNum):

global failureTask

failureTask = []

tasksize = len(task)

threadTask = tasksize//int(threadNum)       #取整除 返回商的整数部分

print '待下载Tile总计:%s,下载线程数:%s'%(tasksize,sys.argv[5])

for i in range(len(task)):

#log('开启线程:%s'%i,False)

st = i * int(threadTask)

ed = st + int(threadTask) + 1

if ed > len(task) - 1:

download = Download(task[st:len(task) - 1])

download.start()

break

download = Download(task[st:ed])

download.start()

time.sleep(0.5)

class Download(threading.Thread):

sucessCount = 0

failureCount = 0

def __init__(self,tasks):

threading.Thread.__init__(self)

self.tasks = tasks

self.lock = threading.RLock()

def run(self):

#log('start download',False)

for task in self.tasks:

valueAry = task.split(",")

lv = valueAry[0]

row = valueAry[1]

col = valueAry[2]

remoteFile = createRemoteUrl(col,row,lv)

localFile = createLocalFile(col,row,lv,lvRange,cacheDir)

try:

downloadTile(remoteFile,localFile)

self.lock.acquire()

Download.sucessCount += 1

log('已经下载:%s / %s ,失败: %s / %s'%(Download.sucessCount,len(tempTask),Download.failureCount,len(failureTask)),False)

self.lock.release()

except:

logStr = '%s,%s,%s'%(lv,row,col)

f = file(cacheDir+os.sep+'error.log','a')#在日志文件中打印失败记录

f.write(logStr+'\n')

f.close()

self.lock.acquire()

Download.failureCount += 1

self.lock.release()

failureTask.append(logStr)

def log(event,b):

#'''打印消息或日志'''

try:

logStr = str(event)

if b:#在日志文件中打印消息

f = file(cacheDir+os.sep+str(time.strftime('%Y%m%d%H'))+'.log','a')

f.write(logStr+'\n')

f.close()

sys.stdout.write('\r'+logStr)#在控制台中打印消息

sys.stdout.flush()

except:

pass

if __name__ == '__main__':

extent = sys.argv[1]

maxLv = sys.argv[2]

minLv = sys.argv[3]

global extAry,lvRange,cacheDir,threadNum

ext = [float(i) for i in extent.split(' ')]

extAry = [ext[0],ext[3],ext[2],ext[1]]          #区域范围

lvRange = range(int(minLv),int(maxLv) + 1)      #等级范围

cacheDir = sys.argv[4]                          #下载目录

threadNum = sys.argv[5]                         #下载线程

if sys.argv[1] == 'loadError':

errorTask = loadErrorFile(sys.argv[2]+os.sep+'error.log')

loadTask(tempTask,sys.argv[3])

else:

createCacheStruc(extAry,lvRange,cacheDir)       #创建缓存目录结构

loadTask(tempTask,threadNum)                    #下载


我的python版本是2.5,装过ArcMap的都默认安装了这个版本。
执行以上脚本可以在同目录下新建一个批处理文件,内容如下:

python dmc.py "118.411792548134 31.5176549981089 119.43094617187 32.3386680868215" 16 10 c:\caches\jn 20

pause

复制代码
"118.411792548134 31.5176549981089 119.43094617187 32.3386680868215" 是待下载的区域范围
16 10 是下载的等级范围
c:\caches\jn 是存储目录
20 是线程数 我的python版本是2.5,装过ArcMap的都默认安装了这个版本。
执行以上脚本可以在同目录下新建一个批处理文件,内容如下:

python dmc.py "118.411792548134 31.5176549981089 119.43094617187 32.3386680868215" 16 10 c:\caches\jn 20

pause

"118.411792548134 31.5176549981089 119.43094617187 32.3386680868215" 是待下载的区域范围
16 10 是下载的等级范围
c:\caches\jn 是存储目录
20 是线程数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: