Python:从 FTP 服务器下载文件

Posted

技术标签:

【中文标题】Python:从 FTP 服务器下载文件【英文标题】:Python: download a file from an FTP server 【发布时间】:2012-07-30 21:04:59 【问题描述】:

我正在尝试下载一些公共数据文件。我截屏以获取文件的链接,它们看起来都像这样:

ftp://ftp.cdc.gov/pub/Health_Statistics/NCHS/nhanes/2001-2002/L28POC_B.xpt

我在Requests library website 上找不到任何文档。

【问题讨论】:

【参考方案1】:

requests 库不支持 ftp 链接。

要从 FTP 服务器下载文件,您可以:

import urllib 

urllib.urlretrieve('ftp://server/path/to/file', 'file')
# if you need to pass credentials:
#   urllib.urlretrieve('ftp://username:password@server/path/to/file', 'file')

或者:

import shutil
import urllib2
from contextlib import closing

with closing(urllib2.urlopen('ftp://server/path/to/file')) as r:
    with open('file', 'wb') as f:
        shutil.copyfileobj(r, f)

Python3:

import shutil
import urllib.request as request
from contextlib import closing

with closing(request.urlopen('ftp://server/path/to/file')) as r:
    with open('file', 'wb') as f:
        shutil.copyfileobj(r, f)

【讨论】:

谢谢您,但是您如何提供凭据? @SSHThis:尝试:'ftp://username:password@server/path/to/file' 或使用@Rakesh's answer。如果你不能让它工作,ask. 这里有一点 urllib 与请求信息:blog.pythonlibrary.org/2012/06/07/… @cbare:链接的意义何在。 requests 是否完全支持 ftp @LimokPalantaemon 它相当于ftp.login(user, passw) 调用,因此它没有加密(ftp 是一个非常古老的协议——安全性很低)。你可以试试 sftp (fabric/paramiko)。【参考方案2】:

你可以试试这个

import ftplib

path = 'pub/Health_Statistics/NCHS/nhanes/2001-2002/'
filename = 'L28POC_B.xpt'

ftp = ftplib.FTP("Server IP") 
ftp.login("UserName", "Password") 
ftp.cwd(path)
ftp.retrbinary("RETR " + filename, open(filename, 'wb').write)
ftp.quit()

【讨论】:

如果服务器上的文件名有一些特殊字符,例如' '、$ 等。我需要转义它们吗? 文件名可以是任意字节序列,但有少数例外,例如b'\xff'(我不知道有任何标准方法可以转义此类名称)。这是more detail (in Russian)。如果您对 ftp 文件名有特定问题,您可以提出单独的 Stack Overflow 问题 将文件名从 unicode 编码为“utf-8”对我有用。也许在不同的操作系统上会有所不同:ftp.retrbinary(u"RETR täßt.jpg".encode('utf-8'), open('local.jpg', 'wb').write) 如果返回的数据大于块大小我相信这会继续覆盖文件并只保留最后一个块。 如何指定发送到本地机器上的哪个目录?【参考方案3】:

尝试使用 python 的 wget 库。你可以找到它的文档here。

import wget
link = 'ftp://example.com/foo.txt'
wget.download(link)

【讨论】:

最简单,效果很好。您也可以在 wget.download 中使用out 参数设置文件名。 这对我有用,其他方法导致文件崩溃。 @anatoly-techtonik 我认为你是这个 pypi 模块的作者。你认为它可以安全使用吗? 警告:自 2015 年以来没有发布,并且 pypi 上的主页链接已损坏(指向 bitbucket)。作者的其他项目移到了github上,但是我没有看到这个。 github.com/techtonik【参考方案4】:

使用urllib2。更多详情,请查看example from doc.python.org:

这是教程中的一个 sn-p,可能会有所帮助

import urllib2

req = urllib2.Request('ftp://example.com')
response = urllib2.urlopen(req)
the_page = response.read()

【讨论】:

【参考方案5】:
    import os
    import ftplib
    from contextlib import closing

    with closing(ftplib.FTP()) as ftp:
        try:
            ftp.connect(host, port, 30*5) #5 mins timeout
            ftp.login(login, passwd)
            ftp.set_pasv(True)
            with open(local_filename, 'w+b') as f:
                res = ftp.retrbinary('RETR %s' % orig_filename, f.write)

                if not res.startswith('226 Transfer complete'):
                    print('Downloaded of file 0 is not compile.'.format(orig_filename))
                    os.remove(local_filename)
                    return None

            return local_filename

        except:
                print('Error during download from FTP')

【讨论】:

我有一个与此线程完全无关的问题,但与您在 github 上上传的代码有关:***.com/questions/27584233/…【参考方案6】:

正如一些人所指出的,请求不支持 FTP,但 Python 有其他库支持。如果你想继续使用 requests 库,有一个 requests-ftp 包,它为请求添加了 FTP 功能。我已经使用了这个库,它确实有效。不过,文档中充满了关于代码质量的警告。从 0.2.0 开始,文档说“这个库是在大约 4 小时的总工作时间内完成的,没有测试,并且依赖于一些丑陋的 hack”。

import requests, requests_ftp
requests_ftp.monkeypatch_session()
response = requests.get('ftp://example.com/foo.txt')

【讨论】:

这个解决方案至少在我手中有效,就像s = requests.Session() response = s.get(...(不是requests.get【参考方案7】:

urllib2.urlopen 处理 ftp 链接。

【讨论】:

对于 Python 的新手:重命名为 urllib,仍然支持 FTP。基本上看到最上面的答案了。【参考方案8】:

如果您想利用最新 Python 版本的异步功能,您可以使用aioftp(与更流行的 aiohttp 库来自同一系列的库和开发人员)。这是取自他们的client tutorial的代码示例:

client = aioftp.Client()
await client.connect("ftp.server.com")
await client.login("user", "pass")
await client.download("tmp/test.py", "foo.py", write_into=True)

【讨论】:

【参考方案9】:

urlretrieve 对我不起作用,官方document 表示它们可能会在将来的某个时候被弃用。

import shutil 
from urllib.request import URLopener
opener = URLopener()
url = 'ftp://ftp_domain/path/to/the/file'
store_path = 'path//to//your//local//storage'
with opener.open(url) as remote_file, open(store_path, 'wb') as local_file:
    shutil.copyfileobj(remote_file, local_file)

【讨论】:

以上是关于Python:从 FTP 服务器下载文件的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ftp 下载文件?

pythonftp给文件授权

Python 连接FTP服务器并实现文件夹下载实例演示,python区分ftp目录下文件和文件夹方法,ftp目录下包含中文名问题处理

Python 连接FTP服务器并实现文件夹下载实例演示,python区分ftp目录下文件和文件夹方法,ftp目录下包含中文名问题处理

python实现从FTP下载文件通过多线程同时分发到多台机器

从 FTP 服务器检查和下载多个文件