在使用FTP服務器的時候,有時候需要定時將服務器上面的內容同步到本地,此時有一個腳本能夠自動化的更新就再好不過了。
本文提供一種自動化同步機制
對於FTP服務器,一般使用可視化軟件 filezila,這樣可以比較快捷的更新文件內容,但是數據量大的時候,即使是使用filezila也不行.
python之中, 它裏面自帶的一個庫文件 ftplib , 可以用它來連接FTP服務器。
使用filezila連接到服務器之後,基本可x看到下面這個樣子,當我們點擊一下‘最近修改’, 文件基本會按照時間順序排序
這正是一個關鍵
因此,思路就是根據最近修改的時間來決定下載更新文件到本地
按照先廣度,再深度這種思路,找到最近更新的文件,然後下載下來
上代碼:
#coding:utf-8
import datetime
import random
import time
import string
import re
import sched
import os
from functools import cmp_to_key
from ftplib import FTP
ftpserveraddress = " 127.0.0.1" #目標FTP服務器網址
ftp_acc = 'username' #服務器賬號
ftp_psw = 'password' #服務器密碼
log_root = 'local_path' #本地存貯路徑
cur_year=time.strftime("%Y",time.localtime())
#cur_mon=time.strftime("%b",time.localtime())
#cur_day=time.strftime("%d",time.localtime())
#cur_hour=time.strftime("%H",time.localtime())
#cur_min=time.strftime("%M",time.localtime())
st = sched.scheduler(time.time,time.sleep) #初始化調度器
def run_to_download(checktime):
'''
parameter:
checktime 檢查最近checktime定義的時間內更新的文件
'''
currenttime=time.time()
print ("current new time is ",time.strftime("%Y-%m-%d_%H-%M-%S",time.localtime()))
ftp = FTP(ftpserveraddress)
ftp.login(ftp_acc,ftp_psw)
print (ftp.getwelcome())
update_file_lists=[]
second_update_folder_name_list=[]
#過濾符合目標時間內的文件
def first_filter(line):
'''
line 是FTP服務器上面各個文件的屬性合集,類似於 在linux上輸入 ls- l命令之後的內容
'''
ll=line.split()
tmp={}
if ll[8].find("-0")>-1 and ".zip" not in ll[8]:
fileinfo=ll
#fileinfo是一個list, 包含文件的這些屬性['drw-rw-rw-', '1', 'user', 'group', '0', 'Aug', '8', '13:25', '.']
filetime=str(cur_year)+"-"+fileinfo[5]+"-"+fileinfo[6]+' '+fileinfo[7] #根據文件的第6,7,8項屬性得到了文件更新的時間 "'2018-Aug-8 13:25'"
format_time=datetime.datetime.strptime(filetime,"%Y-%b-%d %H:%M")#組合轉化文件最後修改的時間,最終將時間轉爲爲標準計數時間
format_time=format_time.strftime("%Y%m%d%H%M")
format_time=time.strptime(format_time,"%Y%m%d%H%M")
format_time=time.mktime(format_time)
#根據當前時間減去文件更新時間,跟checktime比較,即得到最近指定時間內更新的文件
if (currenttime-format_time < int(checktime)) and len(fileinfo[8]) > 2: #十個小時內(36000的單位是秒)有文件更新的話,記錄下來
tmp['update_file_name']=ll[8] #ll[8存貯着文件目錄名字
tmp['file_update_time']=format_time
tmp['file_update_time_format_time']=filetime
update_file_lists.append(tmp)
ftp.retrlines("LIST",first_filter) #調用上面的過濾函數,選擇出符合條件的文件或者文件夾
update_file_lists = sorted(update_file_lists,key=cmp_to_key(lambda x,y:x['file_update_time']-y['file_update_time']) ) #將最近更新的文件排序,優先下載更新時間比較久的文件
for i in update_file_lists:
print (" the folder %s modify at %s ,this file need update " % (i['update_file_name'],i['file_update_time_format_time']) )
second_update_folder_name_list.append(i['update_file_name'])
print ("current id list is ...............")
print (second_update_folder_name_list)
#進入下一級目錄,基本同樣的規則
for i in range(0, len(second_update_folder_name_list)):
r_log = '\\'+second_update_folder_name_list[i]
ftp.cwd(r_log)
print(r_log)
log_dir = []
def second_filter(line):
ll=line.split()
#print(ll)
fileinfo=ll #獲取當前目錄下的文件夾屬性值
#['drw-rw-rw-', '1', 'user', 'group', '0', 'Aug', '8', '13:25', '.']
filetime=str(cur_year)+"-"+fileinfo[5]+"-"+fileinfo[6]+' '+fileinfo[7] #"'2018-Aug-8 13:25'"
format_time=datetime.datetime.strptime(filetime,"%Y-%b-%d %H:%M")#組合轉化文件最後修改的時間,最終將時間轉爲爲標準計數時間
format_time=format_time.strftime("%Y%m%d%H%M")
format_time=time.strptime(format_time,"%Y%m%d%H%M")
format_time=time.mktime(format_time)
#print("check time is ", checktime )
if (currenttime-format_time < int(checktime)) and len(fileinfo[8]) > 2: #十個小時內(36000的單位是秒)有文件更新的話,記錄下來
log_dir.append(ll[8]) #ll[8存貯着文件目錄名字]
ftp.retrlines("LIST",second_filter)
print(log_dir)
for i in range(0, len(log_dir)):
record_log = "/" + r_log.strip('\\') + "/" + log_dir[i] +"/"
#print ("log_dir is %s"%log_dir[i])
print ("log_dir %s has update"%record_log)
loglist = ftp.nlst(record_log)
print ("loglist is %s"%loglist)
ftp.cwd(record_log)
#print("pwd is %s"%ftp.pwd())
for log in loglist:
log_path = log_root + record_log
#print (log_path)
if not os.path.exists(log_path): #判斷本地目錄是否存在,沒有就重新創建
os.makedirs(log_path)
#xxx = log_root + "/" + log # dir is ../log
xxx = log_path + log # dir is ../log-123456
if os.path.exists(xxx): #因爲沒有對log文件進行時間排序,因此會出現這個文件夾持續更新的情況,所以加上一層判斷,如果文件已經存在,不用再次更新
#print("%s is exists, do not need update again" % xxx)
pass
else:
fp = open(xxx,'wb')
ftp.retrbinary('RETR '+log,fp.write)
fp.close()
print ("log %s didn't exists , is updating now ..." % log)
print ("........before clear , the id list , id _lists is..........")
print (update_file_lists)
print (second_update_folder_name_list)
update_file_lists.clear()
second_update_folder_name_list.clear()
print("after clear , the id list , id _lists, and log_dir is : ")
print (update_file_lists)
print (second_update_folder_name_list)
print("---------------------------finished-----------------------------------------")
st.enter(60,1,run_to_download,(360,)) #360 is the checktime
if __name__ == '__main__':
st.enter(1,1,run_to_download,(360,)) #360 is the checktime
st.run()
收穫主要是,python3上面的排序方法, sort函數中的cmp函數不用了, 這裏用了新的方法
另外,ftp服務器中,獲取文件更新時間的方法比較特別