python——ftp服務(wù)器指定日期所有文件的更新下載

盼望著盼望著赋荆,終于迎來(lái)了一篇原創(chuàng)(老淚縱橫)。


也是任務(wù)需求懊昨,花了兩天弄了一下,現(xiàn)在總算是滿(mǎn)足要求了春宣〗桶洌可能容錯(cuò)性還不夠,冗余度應(yīng)該還行月帝。但是寫(xiě)過(guò)了才有體會(huì)躏惋,是真的痛苦。里面的小彎彎邏輯是頭疼嚷辅。下面就來(lái)說(shuō)一下實(shí)現(xiàn)的功能:

大前提:在規(guī)定的文件格式和路徑規(guī)則下

實(shí)現(xiàn):ftp服務(wù)器上指定日期下的所有文件的更新下載

說(shuō)明:

1.大前提簿姨,就是我項(xiàng)目要求的文件存放格式,因?yàn)橛羞@個(gè)才能寫(xiě)出一鍵自動(dòng)化的程序簸搞,否則扁位。。趁俊。應(yīng)該是癡人說(shuō)夢(mèng)(恕我才疏學(xué)淺吧)
歸類(lèi)規(guī)則

2.具體實(shí)現(xiàn)的功能由如下知識(shí)點(diǎn)拼湊:python庫(kù)ftplib的使用域仇;os庫(kù)的使用(本地文件操作);針對(duì)歸類(lèi)規(guī)則思考的程序邏輯結(jié)構(gòu)(這才是最難的寺擂,一點(diǎn)一點(diǎn)摸索出來(lái)的)等暇务。
3.這里的指定日期下可不止一處日期哦泼掠,比如傳感器A下有2019年1月1日,傳感器B也有這個(gè)日期垦细,那么該模塊的功能是同時(shí)更新A與B下的指定日期的文件择镇。怎么樣,是不是挺工程化的括改。


下面貼代碼:

# -*- coding: utf-8 -*-
"""
Created on Wed Feb 20 16:56:26 2019

@author: Raul
"""
import ftplib
import os
import datetime

##  創(chuàng)建地址文件 創(chuàng)建成功返回true 已存在返回false
def mkdir_ifnotExist(path):
    path = path.strip()    # 刪除地址首尾空格
    path = path.rstrip("\\")    # 保留\\之后的內(nèi)容 以空格結(jié)尾
    isExist = os.path.exists(path)
    
    if not isExist :
        os.makedirs(path)
        print("%s did not exist.\nNow is created."%path)
        return True
    else :
        print("%s has exist!"%path)
        return False
    
##  ftp連接函數(shù)
def ftpconnect(ftpserver,port,username,password):
    ftp = ftplib.FTP()
    try:
        ftp.connect(ftpserver,port)
    except:
        raise(IOError('FTP connect failed!'))
    
    try:
        ftp.login(username,password)
    except:
        raise(IOError("FTP login failed!"))
    
    else:
        print("********* ftp連接腻豌、登錄成功!*********")
        # 中文亂碼問(wèn)題
        ftp.encoding = 'GB18030'
        return ftp

##  ftp文件下載函數(shù)
def ftpdownload(ftp,local_path,ftp_path,filename,bufsize = 1024*10):
    # 進(jìn)入下載路徑
    ftp.cwd(ftp_path)
    print("成功進(jìn)入目錄:",ftp.pwd().encode('iso-8859-1').decode('gbk'),"\n下載文件:",filename)    # 將GB18030轉(zhuǎn)換成UFT可以顯示的格式
    save_path = local_path + ftp_path
    # 調(diào)用地址創(chuàng)建函數(shù)
    mkdir_ifnotExist(save_path)
    save_path = save_path + "/" + filename
    fp = open(save_path,'wb')
    #print("打開(kāi)本地保存文件...")
    ftp.retrbinary('RETR %s' % filename, fp.write, bufsize)
    #print("寫(xiě)入文件成功叹谁!")
    fp.close()

##  ftp退出連接函數(shù)  
def ftpquit(ftp):
    try:
        ftp.quit()
    except:
        raise(IOError("FTP quit failed!"))
    else:
        print("*********ftp已斷開(kāi)連接饲梭!*********")

##  拷貝ftp服務(wù)器指定日期所有文件函數(shù)
def copy_new_file(ftp):
    nlst = ftp.nlst()
    for name in nlst:
        # 調(diào)用具體實(shí)現(xiàn)功能函數(shù) 該函數(shù)為自迭代函數(shù)
        find_assign_file(ftp,name,0)
        # 邏輯需要 服務(wù)器退出到根目錄下
        while ftp.nlst() != nlst:
            ftp.cwd("..")

##  查找指定文件自迭代函數(shù)
def find_assign_file(ftp,file_name,year_flag):
    # year_flag: 當(dāng)當(dāng)前路徑為指定年份時(shí)為1,否則為0
    folder_flag = 1    # folder_flag  0:非文件夾 1:文件夾
    cmd_count = 0    # 目錄進(jìn)入層數(shù)記錄
    global detectionfolder_list    # 每個(gè)測(cè)點(diǎn)上的節(jié)點(diǎn)目錄    
    global tmp_file     # 存放每個(gè)日期文件下的文件名列表 [[node1],[node2],...,[nodeN]]
    global record       # tmp_file的索引 使用:tmp_file[recor]
    global date_flag    # 0:非指定日期焰檩;1:指定日期憔涉;2:為當(dāng)前指定日期的檢測(cè)節(jié)點(diǎn)文件夾;3:保存指定日期文件夾中的文件
    try:
        ftp.cwd(file_name)         #需要判斷的元素
        ftp.cwd("..")              #如果能通過(guò)路勁打開(kāi)必為文件夾析苫,在此返回上一級(jí)
    # 不能通過(guò)路徑打開(kāi)必為文件兜叨,抓取其錯(cuò)誤信息
    except ftplib.error_perm as fe:
        folder_flag = 0    # 發(fā)現(xiàn)文件txt         
        if date_flag == 2:    # 父文件為節(jié)點(diǎn)文件夾
            date_flag = 3     # 下載標(biāo)志
    finally:
        if folder_flag == 1:    # 要訪問(wèn)的是文件夾
            father_file_list = ftp.nlst()    # 獲取當(dāng)前路徑下所有文件夾
            # 逐個(gè)訪問(wèn)該路徑下所有文件夾
            for father_name in father_file_list:
                try:
                    ftp.cwd(father_name)
                    # 若當(dāng)前路徑下不為空
                    if ftp.nlst() != []:
                        # 逐個(gè)訪問(wèn)其子文件夾
                        for child_name in ftp.nlst():
                            # 獲取節(jié)點(diǎn)文件名
                            try:
                                ftp.cwd(child_name)
                                cmd_count = 1 
                                ftp.cwd(ftp.nlst()[0])
                                cmd_count = 2
                                ftp.cwd(ftp.nlst()[0])
                                cmd_count = 3
                                ftp.cwd(ftp.nlst()[0])
                                cmd_count = 4
                                # 操作正常返回到原路徑
                                ftp.cwd("..")
                                ftp.cwd("..")
                                ftp.cwd("..")
                                ftp.cwd("..")
                            except (ftplib.error_perm,IndexError) as fe:
                                if cmd_count == 3:
                                    ftp.cwd("..")
                                    detectionfolder_list = ftp.nlst()
                                    ftp.cwd("..")
                                    ftp.cwd("..")
                                else:
                                    while cmd_count > 0 :
                                        ftp.cwd("..")
                                        cmd_count -= 1
                                pass
                            # 當(dāng)且僅當(dāng)date_flag == 1(符合查找日期要求)且 父文件為節(jié)點(diǎn)文件夾(子文件夾則為輸出文件) 進(jìn)入輸出文件名模塊
                            if date_flag == 1 and (father_name in detectionfolder_list):
                                date_flag = 2    # 查詢(xún)成功
                            else:
                                # 當(dāng)前子文件不是節(jié)點(diǎn)文件夾時(shí)
                                if (child_name not in detectionfolder_list):
                                    # 如果年份滿(mǎn)足查詢(xún)要求,令年份標(biāo)志為1
                                    if (father_name == "2019年"): #"""or father_name == "1月" """): and (child_name == "1月" """or child_name == "1日" """)):
                                        year_flag = 1    # 年份標(biāo)志為避免差錯(cuò)年份衩侥,比如查找2019年1月1日国旷,如不添加其,則也會(huì)查找到2018年1月1日
                                    # 如果年份標(biāo)志為1茫死,且月跪但、日也滿(mǎn)足查詢(xún)要求,此時(shí)令date_flag=1峦萎,即查詢(xún)到指定日期
                                    if year_flag == 1 and father_name == "1月" and child_name=="1日":
                                        date_flag = 1
                                    else:
                                        date_flag = 0
                                # 當(dāng)前子文件是節(jié)點(diǎn)文件但父文件不符合查詢(xún)?nèi)掌?                                elif father_name != "1日":
                                    date_flag = 0                      
                            # 進(jìn)入子文件迭代查詢(xún)
                            find_assign_file(ftp,child_name,year_flag)
                            # 查詢(xún)完成后退回原路徑
                            ftp.cwd("..")
                            # 只有當(dāng)找到文件才會(huì)返回
                            # 一個(gè)節(jié)點(diǎn)文件夾進(jìn)行一次查詢(xún)即可(因?yàn)楣?jié)點(diǎn)文件夾中都是txt)
                            break
                    # 子文件的路徑下為空屡久,返回到父路徑
                    else:
                        ftp.cwd("..")
                # 父路徑為空,跳過(guò)
                except ftplib.error_perm as er:
                    pass
        # 訪問(wèn)的是文件txt                                              
        else:
            if date_flag == 3:    # 3是符合讀取要求的標(biāo)志
                # 令日期下文件夾數(shù)加1
                tmp_file.append([])
                for name in ftp.nlst():
                    # 如果當(dāng)前路徑下的文件不在上一時(shí)刻該文件夾下 則下載
                    if name not in tmp_file[record]:
                        t = ftp.pwd().encode('iso-8859-1').decode('gbk')
                        ftpdownload(ftp,save_path + t,"",name)
                        # 更新該文件夾下文件內(nèi)容
                        tmp_file[record] += name
                date_flag = 1    # 重置查找日期標(biāo)志為1爱榔,檢查下一節(jié)點(diǎn)文件夾
                record += 1      # 日期文件計(jì)數(shù)+1被环,跟著程序進(jìn)入下一符合查詢(xún)?nèi)掌诘娜掌谖募A下,這相當(dāng)于:tmp_file=[[第一個(gè)符合查詢(xún)要求的文件夾],[第二個(gè)符合查詢(xún)要求的文件夾],...,[record]]
                                 # 我們根據(jù)查詢(xún)順序默認(rèn)相同的原理详幽,記錄一個(gè)隨查找自增長(zhǎng)的序號(hào)以索引符合要求的查找文件夾


## RUN
# 固定參數(shù)信息
ftpserver = '192.168.1.100'
port = 2122
username = 'raul'
password = '123321'
save_path = "C:/Users/Administrator/Desktop/橋梁備份數(shù)據(jù)"
# 全局變量
detectionfolder_list = []       # 每個(gè)測(cè)點(diǎn)上的節(jié)點(diǎn)目錄   
tmp_file = []                   # 存放每個(gè)日期文件下的文件名列表 [[node1],[node2],...,[nodeN]]
date_flag = 0    # 0:非指定日期筛欢;1:指定日期;2:為當(dāng)前指定日期的檢測(cè)節(jié)點(diǎn)文件夾唇聘;3:保存指定日期文件夾中的文件
record = 0                      # tmp_file的索引 使用:tmp_file[recor]
# 運(yùn)行結(jié)構(gòu)
# 1.連接ftp服務(wù)器
ftp = ftpconnect(ftpserver,port,username,password)
# 2.拷貝新文件 ps:這里還需改動(dòng)版姑,即將程序中的 年-月-日要求改為具體要求,即當(dāng)時(shí)時(shí)間的日期datetime.datetime.now().year/month/day
copy_new_file(ftp)
# 3.斷開(kāi)ftp服務(wù)器連接
ftpquit(ftp)

函數(shù)各個(gè)模塊寫(xiě)得還算清晰(無(wú)盡的寫(xiě)+一點(diǎn)點(diǎn)強(qiáng)迫癥)迟郎,注釋也寫(xiě)的算完整的漠酿。需要注意的是這里我用于測(cè)試的,日期給的2019年1月1日谎亩,如果真的放到系統(tǒng)中實(shí)時(shí)更新炒嘲,應(yīng)調(diào)用datetime.datetime.now().year/month/day來(lái)替代宇姚。
但需要說(shuō)一下的是,這里的邏輯夫凸,懂的人可能能從我的程序里面看出來(lái)浑劳,也不是很特別復(fù)雜,但還是有些繞的夭拌。所以如果你也想自己嘗試一下的話魔熏,最好先按照我的來(lái)跑一遍。跑通了鸽扁,再自己飛~

給兩個(gè)效果圖(gif9.62MB蒜绽,加載慢直接看圖或無(wú)視):
程序演示
對(duì)整個(gè)FTP服務(wù)器的監(jiān)聽(tīng)
只更新指定日期下文件

這里在說(shuō)一下win7上ftp服務(wù)器的搭建,戳這里桶现。
搭建需注意如下幾點(diǎn):

  • 請(qǐng)把FTP服務(wù)器和Web管理工具的所有子文件選項(xiàng)打鉤(涂滿(mǎn)深色表示未全選躲雅,不行滴)
    FTP服務(wù)器和Web管理工具全選√
  • 添加網(wǎng)址IP地址的時(shí)候,可下拉選擇可用IP中當(dāng)前電腦查詢(xún)得到的IP

    (cmd下ipconfig的IPV4地址)
    添加網(wǎng)站使用的IP
  • 添加FTP站點(diǎn)時(shí)的IP同上選擇
    添加FTP站點(diǎn)的IP
    注意骡和,端口最好改一下相赁,雖然全網(wǎng)默認(rèn)21.
    最后創(chuàng)建發(fā)布完成后,瀏覽器輸入:
    ftp://192.168.1.100:2121+用戶(hù)名和密碼
    訪問(wèn)成功即創(chuàng)建成功慰于!
    還有一個(gè)使用的注意點(diǎn):訪問(wèn)成功后钮科,如果您使用的局域網(wǎng)路由器網(wǎng)線,那么您的這個(gè)瀏覽器登錄FTP服務(wù)器的方法婆赠,只能在你本機(jī)操作绵脯,如果想讓別的電腦也通過(guò)瀏覽器訪問(wèn)的話,需要在192.168.1.1上對(duì)路由器的對(duì)外IP進(jìn)行統(tǒng)一設(shè)置才行休里。否則外界讀取到的IP并非你本機(jī)IP的矛盾會(huì)暴露出來(lái)的哦桨嫁。但是通過(guò)命令行或程序,比如上文的python的ftplib庫(kù)函數(shù)進(jìn)行ftp服務(wù)器的登錄連接份帐,是沒(méi)問(wèn)題的。(可能是因?yàn)椴簧婕盀g覽器上NDS的問(wèn)題)

我們沒(méi)能力發(fā)現(xiàn)知識(shí)楣导,我們只是知識(shí)的寄生蟲(chóng)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末废境,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子筒繁,更是在濱河造成了極大的恐慌噩凹,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毡咏,死亡現(xiàn)場(chǎng)離奇詭異驮宴,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)呕缭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)堵泽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)修己,“玉大人,你說(shuō)我怎么就攤上這事迎罗〔欠撸” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵纹安,是天一觀的道長(zhǎng)尤辱。 經(jīng)常有香客問(wèn)我,道長(zhǎng)厢岂,這世上最難降的妖魔是什么光督? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮塔粒,結(jié)果婚禮上结借,老公的妹妹穿的比我還像新娘。我一直安慰自己窗怒,他們只是感情好映跟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著扬虚,像睡著了一般努隙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辜昵,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天荸镊,我揣著相機(jī)與錄音,去河邊找鬼堪置。 笑死躬存,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的舀锨。 我是一名探鬼主播岭洲,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼坎匿!你這毒婦竟也來(lái)了盾剩?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤替蔬,失蹤者是張志新(化名)和其女友劉穎告私,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體承桥,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡驻粟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凶异。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜀撑。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挤巡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出屯掖,到底是詐尸還是另有隱情玄柏,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布贴铜,位于F島的核電站粪摘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏绍坝。R本人自食惡果不足惜徘意,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望轩褐。 院中可真熱鬧椎咧,春花似錦、人聲如沸把介。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)拗踢。三九已至脚牍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巢墅,已是汗流浹背诸狭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留君纫,地道東北人驯遇。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蓄髓,于是被迫代替她去往敵國(guó)和親叉庐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容