python 实现FTP文件批量下载

正文

FTP协议

  • FTP(File Transfer Protocol,文件传输协议) 是TCP/IP协议组中的协议之一。FTP协议包括两个组成部分,其一为FTP服务器,其二为FTP客户端。其中FTP服务器用来存储文件,用户可以使用FTP客户端通过FTP协议访问位于FTP服务器上的资源。
  • 默认情况下FTP协议使用TCP端口中的 20和21这两个端口,其中20用于传输数据,21用于传输控制信息。

python ftplib模块

python中默认安装的ftplib模块定义了FTP类,可用来实现简单的ftp客户端,用于上传或下载ftp服务器上的文件。
ftplib模块官方文档:https://docs.python.org/3/library/ftplib.html#module-ftplib
ftplib源码:https://github.com/python/cpython/blob/3.7/Lib/ftplib.py
ftp模块常用函数和命令 

from ftplib import FTP            # 导入ftplib模块
ftp=FTP()                         # 获取ftp变量
ftp.set_debuglevel(2)             # 打开调试级别2,显示详细信息
ftp.connect("host","port")          #连接的ftp sever服务器
ftp.login("usrname","password")      # 用户登陆
print(ftp.getwelcome())            # 打印欢迎信息
ftp.cmd("xxx/xxx")                # 进入远程目录
ftp.retrbinaly("RETR filename.txt",file_handle,bufsize) # 接收服务器上文件并写入本地文件
ftp.set_debuglevel(0)             #关闭调试模式
ftp.quit()                        #退出ftp

ftp.cwd(ftppath)                 # 设置ftp当前操作的路径
ftp.dir()                         # 显示目录下所有文件信息
ftp.nlst()                        # 获取目录下的文件,返回一个list
ftp.mkd(pathname)                 # 新建远程目录
ftp.pwd()                         # 返回当前所在路径
ftp.rmd(dirname)                  # 删除远程目录
ftp.delete(filename)              # 删除远程文件
ftp.rename(fromname, toname) # 将fromname修改名称为toname。
ftp.storbinaly("STOR filename.txt",fid,bufsize)  # 上传目标文件
ftp.retrbinary("RETR filename.txt",fid,bufsize)  # 下载FTP文件

下面以一个FtpDownload.py脚本为例,实现ftp批量下载

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/4/11 17:28
# @Author  : zengsk in HoHai

import os
import sys
from ftplib import FTP

# 连接ftp服务器
def ftpConnect(ftpserver, port, usrname, password):
    ftp = FTP()
    try:
        ftp.connect(ftpserver, port)
        ftp.login(usrname, password)
    except:
        raise IOError('\n FTP connection failed, please check the code!')
    else:
        print(ftp.getwelcome()) # 打印登陆成功后的欢迎信息
        print('\n+------- ftp connection successful!!! --------+')
        return ftp

# 下载单个文件
def ftpDownloadFile(ftp, ftpfile, localfile):
    # fid = open(localfile, 'wb') # 以写模式打开本地文件
    bufsize =  1024
    with open(localfile, 'wb') as fid:
        ftp.retrbinary('RETR {0}'.format(ftpfile), fid.write, bufsize) # 接收服务器文件并写入本地文件
    return True

# 下载整个目录下的文件
def ftpDownload(ftp, ftpath, localpath):
    print('Remote Path: {0}'.format(ftpath))
    if not os.path.exists(localpath):
        os.makedirs(localpath)
    ftp.cwd(ftpath)
    print('+---------- downloading ----------+')
    for file in ftp.nlst():
        print(file)
        local = os.path.join(localpath, file)
        if os.path.isdir(file):           # 判断是否为子目录
            if not os.path.exists(local):
                os.makedirs(local)
            ftpDownload(ftp, file, local) # 递归调用
        else:
            ftpDownloadFile(ftp, file, local)
    ftp.cwd('..')
    ftp.quit()
    return True

# 退出ftp连接
def ftpDisConnect(ftp):
    ftp.quit()
             
# 程序入口
if __name__ == '__main__':
    # 输入参数
    ftpserver = 'jsimpson.pps.eosdis.nasa.gov'
    port = 21
    usrname = 'xxxxxx@gmail.com'
    pwd = 'xxxxxxxxxxxxxx'
    ftpath = '/NRTPUB/imerg/late/201403/'
    localpath = 'D:/data/'
  
    ftp = ftpConnect(ftpserver, 21, usrname, pwd)
    flag = ftpDownload(ftp, ftpath, localpath)
    print(flag)
    ftpDisConnect(ftp)
    print("\n+-------- OK!!! --------+\n")

把FtpDownload.py封装成一个类 –>FtpDownloadCls.py,两种方式的实现效果一样

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2019/4/12 22:00
# @Author  : zengsk in HoHai

'''
FTP批量下载数据
'''
import os
import sys
from ftplib import FTP

class FtpDownloadCls:
    def __init__(self, ftpserver, port, usrname, pwd):
        self.ftpserver = ftpserver # ftp主机IP
        self.port = port          # ftp端口
        self.usrname = usrname  # 登陆用户名
        self.pwd = pwd          # 登陆密码
        self.ftp = self.ftpConnect()

    # ftp连接
    def ftpConnect(self):
        ftp = FTP()
        try:
            ftp.connect(self.ftpserver, self.port)
            ftp.login(self.usrname, self.pwd)
        except:
            raise IOError('\n FTP login failed!!!')
        else:
            print(ftp.getwelcome())
            print('\n+------- FTP connection successful!!! --------+\n')
            return ftp

    # 单个文件下载到本地
    def downloadFile(self, ftpfile, localfile):
        bufsize = 1024
        with open(localfile, 'wb') as fid:
            self.ftp.retrbinary('RETR {0}'.format(ftpfile), fid.write, bufsize)
        return True

    # 下载整个目录下的文件,包括子目录文件
    def downloadFiles(self, ftpath, localpath):
        print('FTP PATH: {0}'.format(ftpath))
        if not os.path.exists(localpath):
            os.makedirs(localpath)
        self.ftp.cwd(ftpath)
        print('\n+----------- downloading!!! -----------+\n')
        for i, file in enumerate(self.ftp.nlst()):
            print('{0} <> {1}'.format(i, file))
            local = os.path.join(localpath, file)
            if os.path.isdir(file): # 判断是否为子目录
                if not os.path.exists(local):
                    os.makedirs(local)
                self.downloadFiles(file, local)
            else:
                self.downloadFile(file, local)
        self.ftp.cwd('..')
        return True

    # 退出FTP连接
    def ftpDisConnect(self):
        self.ftp.quit()

# 程序入口
if __name__ == '__main__':
    # 输入参数
    ftpserver = 'hokusai.eorc.jaxa.jp' # ftp主机IP
    port = 21                                  # ftp端口
    usrname = 'rainmap'       # 登陆用户名
    pwd = 'Niskur+1404'       # 登陆密码
    ftpath = '/standard/v7/daily/00Z-23Z/201403'  # 远程文件夹
    localpath = 'D:/data/GSMaP/'                 # 本地文件夹

    Ftp = FtpDownloadCls(ftpserver, port, usrname, pwd)
    Ftp.downloadFiles(ftpath, localpath)
    Ftp.ftpDisConnect()
    print("\n+-------- OK!!! --------+\n")

作者:zengsk
链接:https://www.jianshu.com/p/055bbe9a2e7d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    原文作者:Doyle_hu
    原文地址: https://blog.csdn.net/Doyle_hu/article/details/118965110
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞