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()