使用python从包含给定字符串的FTP服务器下载文件

时间:2016-08-14 14:53:59

标签: python ftp file-processing

我试图从ftp服务器下载大量共享一个公共字符串(' DEM')的大量文件。这些文件嵌套在多个目录中。例如,' Adair> DEM *'和'亚当斯> DEM *'

FTP服务器位于此处:ftp://ftp.igsb.uiowa.edu/gis_library/counties/,不需要用户名和密码。 所以,我想浏览每个县并下载包含字符串的文件' DEM'

我已经在堆栈和python的文档中阅读了很多问题,但无法弄清楚如何使用ftplib.FTP()进入网站而没有用户名和密码(这不是必需的),以及我无法弄清楚如何在ftplib或urllib中grep或使用glob.glob。

提前感谢您的帮助

3 个答案:

答案 0 :(得分:3)

好的,似乎有效。如果尝试下载目录或扫描文件,可能会出现问题。异常处理可以方便地捕获错误的文件类型并跳过。

由于您在远程文件系统上,

glob.glob无法正常工作,但您可以使用fnmatch来匹配名称

以下是代码:它下载TEMP目录中与*DEM*匹配的所有文件,按目录排序。

import ftplib,sys,fnmatch,os

output_root = os.getenv("TEMP")

fc = ftplib.FTP("ftp.igsb.uiowa.edu")
fc.login()
fc.cwd("/gis_library/counties")

root_dirs = fc.nlst()
for l in root_dirs:
    sys.stderr.write(l + " ...\n")
    #print(fc.size(l))
    dir_files = fc.nlst(l)
    local_dir = os.path.join(output_root,l)
    if not os.path.exists(local_dir):
        os.mkdir(local_dir)

    for f in dir_files:
        if fnmatch.fnmatch(f,"*DEM*"):   # cannot use glob.glob
            sys.stderr.write("downloading "+l+"/"+f+" ...\n")
            local_filename = os.path.join(local_dir,f)
            fh = open(local_filename, 'wb')
            fc.retrbinary('RETR '+ l + "/" + f, fh.write)

fc.close()

答案 1 :(得分:0)

具有本地模式匹配的answer by @Jean是遵循FTP标准的正确便携式解决方案。

尽管与most FTP servers do support non-standard wildcard use with file listing commands一样,您几乎总是可以使用更简单,主要是更有效的解决方案,例如:

files = ftp.nlst("*DEM*")
for f in files:
    with open(f, 'wb') as fh:
        ftp.retrbinary('RETR ' + f, fh.write)

答案 2 :(得分:0)

您可以使用 fsspecFTPFileSystem 方便地在 FTP 服务器上进行通配:

import fsspec.implementations.ftp
ftpfs = fsspec.implementations.ftp.FTPFileSystem("ftp.ncdc.noaa.gov")
files = ftpfs.glob("/pub/data/swdi/stormevents/csvfiles/*1985*")
print(files)
contents = ftpfs.cat(files[0])
print(contents[:100])

结果:

['/pub/data/swdi/stormevents/csvfiles/StormEvents_details-ftp_v1.0_d1985_c20160223.csv.gz', '/pub/data/swdi/stormevents/csvfiles/StormEvents_fatalities-ftp_v1.0_d1985_c20160223.csv.gz', '/pub/data/swdi/stormevents/csvfiles/StormEvents_locations-ftp_v1.0_d1985_c20160223.csv.gz']
b'\x1f\x8b\x08\x08\xcb\xd8\xccV\x00\x03StormEvents_details-ftp_v1.0_d1985_c20160223.csv\x00\xd4\xfd[\x93\x1c;r\xe7\x8b\xbe\x9fOA\xe3\xd39f\xb1h\x81[\\\xf8\x16U\x95\xac\xca\xc5\xacL*3\x8b\xd5\xd4\x8bL\xd2\xb4\x9d'

嵌套搜索也有效,例如 nested_files = ftpfs.glob("/pub/data/swdi/stormevents/**1985*"),但速度可能很慢。