Python實現(xiàn)連接FTP并下載文件夾
第一章:連接 FTP 服務(wù)器并實現(xiàn)文件夾下載
① 連接 FTP 服務(wù)器
如果 FTP 不用用戶名密碼就直接可以訪問,那就是用的默認用戶名 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" # 默認端口21 ftp_port = 21 # 如果未指定,使用默認用戶名為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é)尾會默認帶個 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-03python中pandas操作apply返回多列的實現(xiàn)
本文主要介紹了python中pandas操作apply返回多列的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08python神經(jīng)網(wǎng)絡(luò)facenet人臉檢測及keras實現(xiàn)
這篇文章主要為大家介紹了python神經(jīng)網(wǎng)絡(luò)facenet人臉檢測及keras實現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-05-05Python虛擬環(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