Python實現(xiàn)連接FTP并下載文件夾
第一章:連接 FTP 服務(wù)器并實現(xiàn)文件夾下載
① 連接 FTP 服務(wù)器
如果 FTP 不用用戶名密碼就直接可以訪問,那就是用的默認(rèn)用戶名 Anonymous,密碼為空。
# -*- coding: UTF8 -*-
# 2022-3-8
# 作者:小藍棗
# python連接ftp服務(wù)器
from ftplib import FTP
def conn_ftp():
'''
作用:連接ftp服務(wù)器
參數(shù):無
返回:ftp服務(wù)器連接的對象
'''
# FTP連接信息
ftp_ip = "xx.xx.xx.xx"
# 默認(rèn)端口21
ftp_port = 21
# 如果未指定,使用默認(rèn)用戶名為Anonymous,密碼為空
ftp_user = "Anonymous"
ftp_password = ""
ftp = FTP()
# 連接ftp
ftp.connect(ftp_ip, ftp_port)
# ftp登錄
ftp.login(ftp_user, ftp_password)
# 查看歡迎信息
print(ftp.getwelcome())
return ftp
ftp = conn_ftp()

② 進入指定目錄并顯示文件信息
方法 ftp.dir() 返回結(jié)果的結(jié)尾會默認(rèn)帶個 None,目錄下沒有內(nèi)容的話直接會返回個 None。
def display_dir(ftp, path):
'''
作用:進入并展示指定的目錄內(nèi)容
參數(shù)1:ftp連接對象
參數(shù)2:要展示的目錄
返回:無
'''
# 進入指定目錄
ftp.cwd(path)
# 顯示當(dāng)前所在位置
print("當(dāng)前所在位置為:")
print(ftp.pwd())
# 展示目錄內(nèi)容
print("\n顯示目錄內(nèi)容:")
print(ftp.dir())
# 展示目錄下的文件名,*文件夾和文件都會顯示
print("\n文件和文件夾名為:")
for i in ftp.nlst():
print(i)
path = "/CaseData/nc.vo.sdp.testcase.testcase.TestcaseHVO/"
display_dir(ftp, path)
這是原始目錄。


③ 區(qū)分文件和文件夾名
從上面方法 ftp.dir() 返回結(jié)果可以看到包含 <DIR> 標(biāo)識的為文件夾,我們根據(jù)這個特征來進行文件夾區(qū)分。
def diff_dir(ftp, path):
'''
作用:區(qū)分文件和文件夾
參數(shù)1:ftp連接對象
參數(shù)2:要展示的目錄
返回:無
'''
# 進入指定目錄
ftp.cwd(path)
# 顯示當(dāng)前所在位置
print("當(dāng)前所在位置為:")
print(ftp.pwd())
# 展示目錄內(nèi)容
print("\n顯示目錄內(nèi)容:")
dirs = []
ftp.dir(".", dirs.append)
for i in dirs:
# 區(qū)分文件和文件夾
if("<DIR>" in i):
print("目錄為:" + i.split(" ")[-1])
else:
print("文件為:" + i.split(" ")[-1])
path = "/CaseData/nc.vo.sdp.testcase.testcase.TestcaseHVO/"
diff_dir(ftp, path)

④ 文件夾名包含空格處理
split(" ")[-1] 方法有個缺陷,如果文件或文件夾名里包含空格,得到到的文件夾名就不對了,下面的方法可以有效的解決這個問題
def get_dir_name(s):
'''
作用:需要文件或文件夾名
參數(shù)1:需要截取的字符串
返回:文件或文件夾名
'''
dir_name = ""
k = 0
record = ""
for i in s:
if(record == " " and i != " "):
k = k + 1;
if(k >= 3):
dir_name = dir_name + i;
record = i
print(dir_name)
return dir_name
# 測試兩條數(shù)據(jù)
get_dir_name("03-08-22 09:52AM <DIR> C2021.11_ZDHJC_004a")
get_dir_name("03-08-25 10:32AM 89098 hello .exe")

⑤ 使用遞歸實現(xiàn):FTP服務(wù)器里的文件夾下載到本地
思路:
首先是看目錄或文件里是否包含關(guān)鍵詞,包含關(guān)鍵詞進行下載。
并判斷是否是目錄,如果是目錄的話,本地根據(jù)目錄結(jié)構(gòu)進行遞歸,同時本地創(chuàng)建文件夾。
使用了 2 個方法,下面的方法用來判斷是否包含關(guān)鍵詞,上面的方法就是目錄結(jié)構(gòu)下的遞歸。
注意:由于是一個 ftp 連接對象,遞歸過程中進去某個目錄下,遞歸結(jié)束要回到之前的目錄。
import pathlib
def download_dir(ftp, path, local_path):
'''
作用: 下載目錄
參數(shù)1:ftp連接對象
參數(shù)2:要展示的目錄
參數(shù)3:本地存放路徑
返回:無
'''
# 進入指定目錄
ftp.cwd(path)
# 區(qū)分文件和文件夾
dirs = []
ftp.dir(".", dirs.append)
for i in dirs:
try:
# 識別為目錄進行遞歸
if("<DIR>" in i):
dir_name = get_dir_name(i)
local_path_new = local_path + "/" + dir_name
# 本地創(chuàng)建文件夾
pathlib.Path(local_path_new).mkdir(parents=True, exist_ok=True)
# 調(diào)用下載目錄方法
download_dir(ftp, dir_name, local_path_new)
# 識別為文件進行下載
else:
file_name = get_dir_name(i)
local_filename = local_path + "/" + file_name
f = open(local_filename, "wb")
# 下載ftp文件
ftp.retrbinary('RETR ' + file_name, f.write)
f.close()
except Exception as e:
print(e)
# 退出當(dāng)前目錄
ftp.cwd("..")
def download_file(ftp, key, path, local_path):
'''
作用: 根據(jù)關(guān)鍵詞下載文件
參數(shù)1:ftp連接對象
參數(shù)2:下載的關(guān)鍵詞
參數(shù)3:要展示的目錄
參數(shù)4:本地存放路徑
返回:無
'''
# 進入指定目錄
ftp.cwd(path)
# 區(qū)分文件和文件夾
dirs = []
ftp.dir(".", dirs.append)
for i in dirs:
if(key in i):
try:
# 識別為目錄進行遞歸
if("<DIR>" in i):
dir_name = get_dir_name(i)
local_path_new = local_path + "/" + dir_name
# 本地創(chuàng)建文件夾
pathlib.Path(local_path_new).mkdir(parents=True, exist_ok=True)
# 調(diào)用下載目錄方法
download_dir(ftp, dir_name, local_path_new)
else:
file_name = get_dir_name(i)
local_filename = local_path + "/" + file_name
f = open(local_filename, "wb")
# 下載ftp文件
ftp.retrbinary('RETR ' + file_name, f.write)
f.close()
except Exception as e:
print(e)
# 設(shè)置編碼,解決上傳的文件包含中文的問題
ftp.encoding = 'GBK'
key = "C2021.11_ZDHJC"
path = "/CaseData/nc.vo.sdp.testcase.testcase.TestcaseHVO/"
local_path = "D:/ftp下載"
download_file(ftp, key, path, local_path)
可以看到符合關(guān)鍵詞的目錄被下載到本地了。

并且里面的嵌套目錄也同步被下載了。

第二章:問題解決
① 下載的文件名包含中文【‘utf-8’ codec can’t decode byte …】
設(shè)置下 FTP 對象的編碼為 GBK 即可。
ftp.encoding = 'GBK'
不然會報如下錯誤:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd7 in position 114: invalid continuation byte
② 指定的路徑存在問題【550 The system cannot find the file specified.】
開始我用 split(" ")[-1] 方法截取文件名,由于有的文件含有中文,截取后的文件名稱不對了。
就報了 ftplib.error_perm: 550 The system cannot find the file specified. 的錯誤。
③ 下載文件前未加RETR標(biāo)識【500 Command not understood.】
下載文件時 FTP 路徑前要加個 'RETR ',不然就會報 500 錯誤,注意后面還跟了個空格。
# 下載ftp文件
ftp.retrbinary('RETR ' + file_name, f.write)
不然就報 ftplib.error_perm: 500 Command not understood. 錯誤了。
以上就是Python實現(xiàn)連接FTP并下載文件夾的詳細內(nèi)容,更多關(guān)于Python FTP下載文件夾的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python和flask中返回JSON數(shù)據(jù)的方法
下面小編就為大家整理了一篇python和flask中返回JSON數(shù)據(jù)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03
python中pandas操作apply返回多列的實現(xiàn)
本文主要介紹了python中pandas操作apply返回多列的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08
python神經(jīng)網(wǎng)絡(luò)facenet人臉檢測及keras實現(xiàn)
這篇文章主要為大家介紹了python神經(jīng)網(wǎng)絡(luò)facenet人臉檢測及keras實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05
Python虛擬環(huán)境的創(chuàng)建和包下載過程分析
這篇文章主要介紹了Python虛擬環(huán)境的創(chuàng)建和包下載,本文通過實例給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
快速解釋如何使用pandas的inplace參數(shù)的使用
這篇文章主要介紹了快速解釋如何使用pandas的inplace參數(shù)的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07

