1.背景。
最近接到一個任務,需要寫一個python腳本,從客戶公司的服務器拉取圖片存放到我們公司的sftp服務器。
由於沒頭沒腦,所以我采用無限遍歷,將對方服務器中文件的路徑原原本本的復制到我們公司的服務器。、
后來發現對方數據量過於龐大,所以決定將路徑分別存放到多個csv中,csv就充當了數據庫
然后第二個腳本是在csv里獲取需要下載的圖片地址將他存入sftp。
流程圖
2.ftp
剛開始寫的是這樣一個版本,后來因為運行到一半的時候,由於ftp連接斷掉,腳本拋出異常停了,重頭開始需要很多時間,所以后來又做了斷點續傳
import time
from ftplib import FTP
import os
import csv
"""
1.操作日志
2.
"""
data_num = 1
class FTP_OP(object):
def __init__(self, host, username, password, port):
"""
初始化ftp
:param host: ftp主機ip
:param username: ftp用戶名
:param password: ftp密碼
:param port: ftp端口 (默認21)
"""
self.host = host
self.username = username
self.password = password
self.port = port
self.csv = None
def ftp_connect(self):
"""
連接ftp
:return:
"""
ftp = FTP()
ftp.set_debuglevel(0) # 不開啟調試模式
ftp.connect(host=self.host, port=self.port) # 連接ftp
ftp.login(self.username, self.password) # 登錄ftp
return ftp
def download_file(self, dst_file_path ):
"""
從ftp下載文件到本地
:param dst_file_path: 本地存放路徑
:return:
"""
ftp = self.ftp_connect()
print(ftp.getwelcome() ) #顯示登錄ftp信息
ftp.cwd("ftpstufGAP")
for dir in ftp_file_path:
ftp.cwd(dir)
for file_name in ftp.nlst(ftp.pwd()):
self.judge_file_dir(ftp, file_name, dst_file_path)
ftp.cwd("..")
ftp.quit()
def judge_file_dir(self,ftp,file_name,dst_file_path):
'''
遞歸便利文件
:param ftp:
:param file_name:
:param dst_file_path:
:return:
'''
if file_name.find(".") != -1:
if file_name.lower().endswith(".jpg") or file_name.lower().endswith(".png"):
print("記錄成功",file_name)
else:
ftp.cwd(file_name)
for file_name in ftp.nlst(ftp.pwd()):
res = self.judge_file_dir(ftp,file_name,dst_file_path)
if not res:
continue
ftp.cwd("..")
def write_csv(self,ftp_file):
'''將self.csv的數據寫入data.csv文件'''
global data_num
### 1萬條寫一個csv
if len(self.csv)>10000:
data_num +=1
self.csv.clear()
self.csv = [["Number", "FolderBane", "BarCode", "FileName"]]
with open('downLoad/data/data%s.csv'%data_num, 'w',encoding="utf-8", newline='')as csv_file:
# 獲取一個csv對象進行內容寫入
writer = csv.writer(csv_file)
for row in self.csv:
# writerow 寫入一行數據
writer.writerow(row)
return True
if __name__ == "__main__":
host = "127.0.0.1"
username = "anonymous"
password = ""
port = 21
ftp_file_path = ["2020","2019"] # 下載的文件夾子
dst_file_path = os.getcwd()
ftp = FTP_OP(host=host, username=username, password=password, port=port)
start_time = time.time()
print("記錄開始")
ftp.download_file(dst_file_path)
between_time = time.time()
print("記錄結束,用時%.2fs"%(between_time-start_time))
3.sftp 圖片上傳
將本地的文件上傳到sftp服務器,由於paramiko,沒有提供一次行創建多層目錄的功能,所以采用了一個笨辦法,把目錄按"/"切割成字符串
在逐步拼接出目錄,使用 sftp.listdir(sftp_path) 方法,如果拋出異常則目錄不存在是用 sftp.mkdir(sftp_path)創建出這一級目錄。
class SFTP_OP(object):
def __init__(self, host, username, password, port):
self.host = host
self.port = port
self.username = username
self.password = password
self.set= set()
def sftp_upload(self,local_list,remote):
sf = paramiko.Transport((self.host,self.port))
sf.connect(username = self.username,password = self.password)
sftp = paramiko.SFTPClient.from_transport(sf)
for local_url in local_list:
sftp_url = os.path.join(remote,local_url.split("downLoad/")[-1])
sftp_path_list = sftp_url.split("/")[4:-1]
sftp_path = "/upload/pim/photobaseimages"
for path in sftp_path_list:
sftp_path = sftp_path + "/" +path
if sftp_path in self.set:
continue
else:
try:
sftp.listdir(sftp_path)
self.set.add(sftp_path)
except Exception as e:
sftp.mkdir(sftp_path)
self.set.add(sftp_path)
print("local_url"+local_url)
print("sftp_url"+sftp_url)
sftp.put(local_url,sftp_url)#上傳文件
print("上傳成功",sftp_url)
sf.close()