2015-07-29 2 views
0

Мне нужно загрузить несколько zip-файлов (Digital Earth Model) в папку «C: \ DEMDownload» на моем ПК (ОС Windows) с общей базы геоданных Canada Government.Python загружает zip-файлы с общедоступного FTP-сервера

когда я запускаю мой код на линии ftp.retrbinary('RETR %s' %file, open(local_file, 'wb').write) я получаю следующее сообщение об ошибке

Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
    File "C:\Python27\lib\ftplib.py", line 414, in retrbinary 
    conn = self.transfercmd(cmd, rest) 
    File "C:\Python27\lib\ftplib.py", line 376, in transfercmd 
    return self.ntransfercmd(cmd, rest)[0] 
    File "C:\Python27\lib\ftplib.py", line 339, in ntransfercmd 
    resp = self.sendcmd(cmd) 
    File "C:\Python27\lib\ftplib.py", line 249, in sendcmd 
    return self.getresp() 
    File "C:\Python27\lib\ftplib.py", line 224, in getresp 
    raise error_perm, resp 
error_perm: 550 Failed to open file. 

секунду. Можно ли избежать писать available_days список и создать список всех почтовых файлов для загрузки

import os, ftplib 
destdir='C:\DEMDownload' 
ftp = ftplib.FTP('ftp2.cits.rncan.gc.ca') 
ftp.login('anonymous', '') 
available_days= ['001k11.zip', 
    '001k12.zip', 
    '001k13.zip', 
    '001k14.zip', 
    '001k15.zip', 
    '001l13.zip', 
    '001l14.zip', 
    '001l16.zip', 
    '001m01.zip', 
    '001m02.zip', 
    '001m03.zip', 
    '001m04.zip', 
    '001m05.zip', 
    '001m06.zip', 
    '001m07.zip', 
    '001m08.zip', 
    '001m09.zip', 
    '001m10.zip', 
    '001m11.zip', 
    '001m12.zip', 
    '001m13.zip', 
    '001m14.zip', 
    '001m15.zip', 
    '001m16.zip', 
    '001n02.zip', 
    '001n03.zip', 
    '001n04.zip', 
    '001n05.zip', 
    '001n06.zip', 
    '001n07.zip', 
    '001n10.zip', 
    '001n11.zip', 
    '001n12.zip', 
    '001n13.zip', 
    '001n14.zip', 
    '001n15.zip'] 

    hdfs = list() 
    for day in available_days : 
     file = available_days[available_days.index(day)] 
     print 'file=', file 
     local_file = os.path.join(destdir, file) 
     ftp.retrbinary('RETR %s' %file, open(local_file, 'wb').write) 
     hdfs.append(os.path.abspath(local_file)) 
     ftp.cwd('..') 
    ftp.quit() 
+0

Вы хотите, чтобы загрузить все файлы почтового индекса, доступные или определенные файлы почтового индекса? Я вижу несколько каталогов в корне. – ThinkCode

+0

Мне нужно скачать все доступные zip-файлы –

+0

Все zip-файлы в каждом каталоге 001, 002, 003, ...? – ThinkCode

ответ

2

Я был в состоянии успешно загрузить файлы почтового индекса с данного URL с этим:

# connect to ftp 
url = urlparse.urlparse("http://ftp2.cits.rncan.gc.ca/pub/geobase/official/cded/50k_dem/") 
ftp = ftplib.FTP(url.netloc) 
ftp.login() 
ftp.cwd(ftp_dirname) 

with open(filename, 'w') as fobj: 
    ftp.retrbinary('RETR %s' % basename, fobj.write) 

вы может избежать жестко закодированные имена файлов/реж пешком через FTP-каталогов подобно тому, как вы могли бы пройти через локальный каталог с некоторым творческим использованием ftplib.FTP.dir()

Полный код ниже:

url = 'http://ftp2.cits.rncan.gc.ca/pub/geobase/official/cded/50k_dem/' 
url = urlparse.urlparse(url) 

local_root = os.path.expanduser("~/ftp_download") # change this to wherever you want to download to 

def download(ftp, ftp_path, filename, check_cwd=True): 
    """ 
    Using the given ftp connection, download from ftp_path to 
    filename. 

    If check_cwd is False, assume the ftp connection is already 
    in the correct current working directory (cwd) 
    """ 
    basename = posixpath.basename(ftp_path) 
    dirname = os.path.dirname(filename) 
    if not os.path.exists(dirname): 
     os.makedirs(dirname) 
    if check_cwd: 
     ftp_dirname = posixpath.dirname(ftp_path) 
     if ftp_dirname != ftp.pwd(): 
      ftp.cwd(ftp_dirname) 

    with open(filename, 'w') as fobj: 
     ftp.retrbinary('RETR %s' % basename, fobj.write) 

def ftp_dir(ftp): 
    """ 
    Given a valid ftp connection, get a list of 2-tuples of the 
    files in the ftp current working directory, where the first 
    element is whether the file is a directory and the second 
    element is the filename. 
    """ 
    # use a callback to grab the ftp.dir() output in a list 
    dir_listing = [] 
    ftp.dir(lambda x: dir_listing.append(x)) 
    return [(line[0].upper() == 'D', line.rsplit()[-1]) for line in dir_listing] 

# connect to ftp 
ftp = ftplib.FTP(url.netloc) 
ftp.login() 

# recursively walk through the directory and download each file, depth first 
stack = [url.path] 
while stack: 
    path = stack.pop() 
    ftp.cwd(path) 

    # add all directories to the queue 
    children = ftp_dir(ftp) 
    dirs = [posixpath.join(path, child[1]) for child in children if child[0]] 
    files = [posixpath.join(path, child[1]) for child in children if not child[0]] 
    stack.extend(dirs[::-1]) # add dirs reversed so they are popped out in order 

    # download all files in the directory 
    for filepath in files: 
     download(ftp, filepath, os.path.join(local_root, filepath.split(url.path,1)[-1]), 
              check_cwd=False) 

# logout 
ftp.quit() 

Вы можете уплотнить это далее через использование одной из библиотек оберток питона фтп, такие как ftptool или ftputil

Смежные вопросы