暑假做的唯一一個有意義的項目吧,其實原理很簡單。主要是其中學了不少Ubuntu的東西。今天正好沒事,整理一下,以便后面查閱。
首先推薦一個好用的FTP管理程序--IIS7服務器管理工具:
“IIS7服務器管理工具是一款windows全系、Linux系統下鏈接並操控VPS、VNC、FTP等遠程服務器、雲服務器。
界面簡單明了,操作易上手,功能強大,支持批量導入服務器,並批量打開,多窗口化管理,除此之外,加載本地硬盤、硬盤映射、加載服務器的聲音,遠程聲卡讀取等,完全實現各類場景使用,對於FTP鏈接界面,朋友FTP定時上傳,定時下載(也可以說定時上傳下載 定時備份),對於經常使用FTP的小伙伴來說,非常適用。
工具支持自動更新,壓縮包只有7.62M,方便簡潔,一步到位。“
使用說明:
一、 程序說明。
ftp.py程序說明。
程序功能:這個程序主要由三個功能。1.瀏覽ftp服務器目錄。2.隨機下載一個文件。3.隨機下載多個文件。
1. 瀏覽ftp服務器目錄。
這個功能主要是在登入進ftp服務器后,生成一個隨機數,根據隨機數,進行判斷往哪個目錄下索引。如果是根目錄,只會向下索引。如果是底層目錄,只會向上索引。
2. 隨機下載一個文件。
這個功能主要是在登入進ftp服務器后,生成一個隨機數,根據隨機數,隨機下載一個文件。需要注意的是,生成隨機數之前,要進行判斷。如果沒有要下載的文件,就要切換目錄,進行下載。
3. 隨機多個文件下載
這個功能主要是在登入ftp服務器后,隨機下載多個文件。實現原理為,首先進入一個目錄下,判斷是否有文件下載,如果有文件下載,則下載多個文件,如果沒有,則改變目錄。完成后改變目錄。
所需參數:“ip,port,username,passwd,usermodel”。傳入參數由一個字符串組成。用逗號進行分割。
所需環境:需要搭建好ftp服務器。以及有python環境的系統上運行。
注意事項:
1. 下載路徑默認為”/home/”。如果程序出錯提示為“不能寫入”,需要對文件權限進行提升。
2. 在實現用戶模式時,程序已經默認多次執行。即每次運行程序時,就會隨機多次(至少一次,最多5次)執行,用來模擬用戶行為。
3. ftp服務器搭建詳見ftp服務器搭建教程。

1 #!/usr/bin/env Python3 2 # -*- encoding:utf-8 -*- 3 from ftplib import FTP 4 from random import randint 5 import time 6 import sys 7 8 9 10 11 def ftpconnect(ip, port, username, passwd): 12 ftp = FTP() 13 #ftp.set_debuglevel(2) # 打開調試級別2,顯示詳細信息 14 ftp.connect(ip, port) # 連接的ftp服務器ip和port 15 ftp.login(username, passwd) # 連接的用戶名和密碼 16 print(ftp.getwelcome()) # 打印出歡迎信息。 17 return ftp 18 19 def showdownloadfile(ftp): 20 #print("當前目錄下的文件:文件夾名字:"+ftp.pwd()) 21 mu_dir = gettable(ftp) 22 #print("當前文件夾: "+ftp.pwd()+" 可供下載的文件:") 23 behind_name = [] 24 for name in mu_dir: 25 if mu_dir[name] == "文件": 26 behind_name.append(name) 27 #print(name) 28 return behind_name 29 30 def showfolderfile(ftp): 31 #print("當前目錄下的文件:文件夾名字:"+ftp.pwd()) 32 mu_dir = gettable(ftp) 33 #print("當前文件夾: "+ftp.pwd()+" 可供索引的文件夾:") 34 folder_name = [] 35 for name in mu_dir: 36 if mu_dir[name] == "文件夾": 37 folder_name.append(name) 38 #print(name) 39 return folder_name 40 41 def randomdownload(ftp, localpath, str): 42 # 當前目錄下可供下載的文件名字 43 behind_name = showdownloadfile(ftp) 44 #print("當前文件夾: "+ftp.pwd()+" 可供下載的文件:") 45 #print(behind_name) 46 # 隨機數 47 while len(behind_name) == 0: # 說明沒有可以下載的文件 48 # 切換文件夾 49 changetable(ftp,str) 50 behind_name = showdownloadfile(ftp) 51 file_random = randint(0, len(behind_name)-1) 52 filename = behind_name[file_random] 53 print("當前目錄為: "+ftp.pwd()) 54 print("下載文件為 "+filename) 55 # 設置下載數據 56 bufsize = 1024 # 設置緩沖區大小 57 new_path = localpath+filename # 設置下載路徑 58 59 fp = open(new_path, 'wb') 60 ftp.retrbinary('RETR ' + filename, fp.write, bufsize) # 下載FTP文件。FTP命令 RETR filename 61 fp.close() 62 print(filename+' 下載成功') 63 64 65 def downloadfiles(ftp, localpath, str): # 根目錄不能繼續向下,沒有目錄不能索引(這個可以自動實現)。 66 # 在當前目錄下隨機下載幾個文件 67 behind_name = showdownloadfile(ftp) 68 #folder_name = showfolderfile(ftp) 69 while len(behind_name) == 0: # 說明沒有可以下載的文件 70 # 切換文件夾 71 changetable(ftp, str) 72 behind_name = showdownloadfile(ftp) 73 74 randomb = randint(0, len(behind_name)-1) 75 while randomb: # 在這個文件夾下隨機下載幾個 76 randomdownload(ftp, localpath, str) 77 randomb -= 1 78 # 切換目錄下載(可能向下或者向上) 79 #viewtable(ftp) 80 81 82 83 84 def gettable(ftp): # 獲取目錄結構 85 dir_del = [] 86 87 table_dir = {} 88 ftp.dir('.', dir_del.append) # 根據文件目錄,進行拆分。 89 for name in dir_del: 90 strname = str(name) 91 temp = strname.split(' ') 92 attrname = [] 93 for j in range(0,len(temp)): 94 if temp[j] != '': 95 attrname.append(temp[j]) 96 m = ' '.join(attrname[8:]) 97 if strname.startswith('d'): 98 #print('文件夾:', m) 99 table_dir[m] = '文件夾' 100 else: 101 #print('文件:', m) 102 table_dir[m] = '文件' 103 return table_dir # 字典,key值是文件名,value是類型 104 105 def viewtable(ftp,str): 106 #gettable(ftp) # 獲取當前目錄 107 changtimes = randint(1, 4) # 隨機切換幾次目錄 108 while changtimes: 109 changtimes -= 1 110 folder_name = showfolderfile(ftp) 111 print("當前目錄下為: "+ftp.pwd()) 112 print("目錄結構:") 113 print(gettable(ftp)) 114 if len(folder_name) > 0: # 有可供索引的文件夾 115 if ftp.pwd() == str: # 為根目錄,只能向下索引 116 print("向下索引后目錄為:") 117 randomf = randint(0, len(folder_name)-1) 118 path = ftp.pwd()+folder_name[randomf] 119 ftp.cwd(path) 120 print("當前目錄下為: "+ftp.pwd()) 121 print("目錄結構:") 122 print(gettable(ftp)) 123 124 else: # 向上向下索引都可以 125 downorup = randint(0, 1) 126 if downorup: # 向下索引 127 print("向下索引后目錄為:") 128 randomf = randint(0, len(folder_name)-1) 129 path = ftp.pwd()+folder_name[randomf] 130 ftp.cwd(path) 131 print("當前目錄下為: "+ftp.pwd()) 132 print("目錄結構:") 133 print(gettable(ftp)) 134 135 else: 136 print("向上索引后,目錄為:") 137 path = '../' 138 ftp.cwd(path) 139 print("當前目錄下為: "+ftp.pwd()) 140 print("目錄結構:") 141 print(gettable(ftp)) 142 else: # 沒有可供索引的文件夾,可以向上索引。 143 if ftp.pwd() != str: 144 print("向上索引后,目錄為:") 145 path = '../' 146 ftp.cwd(path) 147 print("當前目錄下為: "+ftp.pwd()) 148 print("目錄結構:") 149 print(gettable(ftp)) 150 151 def changetable(ftp,str): 152 folder_name = showfolderfile(ftp) 153 if len(folder_name) > 0: # 有可供索引的文件夾 154 if ftp.pwd() == str: # 為根目錄,只能向下索引 155 randomf = randint(0, len(folder_name)-1) 156 path = ftp.pwd()+folder_name[randomf] 157 ftp.cwd(path) 158 159 else: # 向上向下索引都可以 160 downorup = randint(0, 1) 161 if downorup: # 向下索引 162 randomf = randint(0, len(folder_name)-1) 163 path = ftp.pwd()+folder_name[randomf] 164 ftp.cwd(path) 165 166 else: 167 path = '../' 168 ftp.cwd(path) 169 else: # 沒有可供索引的文件夾,可以向上索引。 170 if ftp.pwd() != str: 171 path = '../' 172 ftp.cwd(path) 173 def ftpmain(ip, port, username, passwd, localpath, userModel): 174 # 1.連接到ftp服務器 175 ftp = ftpconnect(ip, port, username, passwd) 176 # 2.開始交互 177 str = ftp.pwd() 178 #print(str) 179 # usermodel 也可以是一個列表序列,讓一個用戶,執行多個操作。 180 cmdtimes = randint(1, 5) # 這隨機多次執行用戶模式。 181 #downloadtimes = 3 # 多個文件多次下載 182 while cmdtimes: 183 cmdtimes -= 1 184 if userModel == 1: # 瀏覽模式 185 viewtable(ftp, str) 186 changetable(ftp, str) 187 continue 188 if userModel == 2: # 下載模式 189 randomdownload(ftp, localpath, str) 190 changetable(ftp, str) 191 continue 192 if userModel == 3: # 同時下載多個文件模式 193 #while downloadtimes: 194 downloadfiles(ftp, localpath, str) 195 changetable(ftp, str) 196 #downloadtimes -= 1 197 continue 198 else: # 錯誤處理機制 199 print('無法識別傳遞的模式編號:') 200 break 201 202 ftp.quit() 203 204 205 if __name__ == "__main__": 206 agrvlist = sys.argv[1].split(',') 207 ip = agrvlist[0] 208 port = int(agrvlist[1]) 209 username = agrvlist[2] 210 passwd = agrvlist[3] 211 usermodel = int(agrvlist[4]) 212 ftpmain(ip, port, username, passwd, "/home/username/", usermodel)
從程序中我們可以看出,其實還是很簡單的。主要是引入ftplib庫。用pip就可以。
下面簡單說一下,我在編程中主要遇到的問題:
1.區分ftp服務器里面的文件夾和文件。
這里是解決的方法:

1 def gettable(ftp): # 獲取目錄結構 2 dir_del = [] 3 4 table_dir = {} 5 ftp.dir('.', dir_del.append) # 根據文件目錄,進行拆分。 6 for name in dir_del: 7 strname = str(name) 8 temp = strname.split(' ') 9 attrname = [] 10 for j in range(0,len(temp)): 11 if temp[j] != '': 12 attrname.append(temp[j]) 13 m = ' '.join(attrname[8:]) 14 if strname.startswith('d'): 15 #print('文件夾:', m) 16 table_dir[m] = '文件夾' 17 else: 18 #print('文件:', m) 19 table_dir[m] = '文件' 20 return table_dir # 字典,key值是文件名,value是類型
主要是先獲取服務器文件夾里面的詳細信息,通過分析,利用python的數據結構來區分。
下面是我的分析過程:
這是ftp服務器主目錄下,通過ftp.dir(),然后輸出結果為:
['drwxrwxrwx 2 0 0 4096 Jul 04 21:17 hello', '-rw------- 1 1001 131 3 Jul 05 10:20 test', '-rwxrwxrwx 1 1000 1000 2840284 Apr 20 2016 test.ogg']
通過查閱發現:hello是文件夾,test和test.ogg是文件。
然后進一步查分,最后通過'd'來區分。
strname.startswith('d')
2.獲取外部輸入
這個程序不是直接編譯通過的,而是要傳遞外部參數。利用sys庫進行操作。通過控制台運行函數。

1 if __name__ == "__main__": 2 agrvlist = sys.argv[1].split(',') 3 ip = agrvlist[0] 4 port = int(agrvlist[1]) 5 username = agrvlist[2] 6 passwd = agrvlist[3] 7 usermodel = int(agrvlist[4])
由於 外部參數都是以字符串形式傳入,所以要進行格式轉換操作。
3.限制下載速度。
這個功能在程序中沒有實現。后來通過閱讀關於網絡的書籍,關於tcp的過程,其實是可以通過設置緩沖區的大小來模擬延遲的。當然這個下載速度服務器是由主導權的。
這個項目主要學到的東西在ftp服務器搭建中,放到下個隨筆中。