Python newb在这里请耐心等待。我正在整理一个脚本,通过FTP从目录下载所有文件。到目前为止,我已经设法连接并获取一个文件,但我似乎无法批量工作(从目录中获取所有文件)这是我到目前为止:
from ftplib import FTP
import os, sys, os.path
def handleDownload(block):
file.write(block)
print ".",
ddir='C:\\Data\\test\\'
os.chdir(ddir)
ftp = FTP('test1/server/')
print 'Logging in.'
ftp.login('user1\\anon', 'pswrd20')
directory = '\\data\\test\\'
print 'Changing to ' + directory
ftp.cwd(directory)
ftp.retrlines('LIST')
print 'Accessing files'
for subdir, dirs, files in os.walk(directory):
for file in files:
full_fname = os.path.join(root, fname);
print 'Opening local file '
ftp.retrbinary('RETR C:\\Data\\test\\' + fname,
handleDownload,
open(full_fname, 'wb'));
print 'Closing file ' + filename
file.close();
ftp.close()
我打赌你可以告诉我,当我运行它时它没有做太多,所以任何改进建议都将不胜感激
PS这不是作业:DD
谢谢!
答案 0 :(得分:62)
我设法破解了这一点,所以现在为未来的访问者发布相关的代码:
filenames = ftp.nlst() # get filenames within the directory
print filenames
for filename in filenames:
local_filename = os.path.join('C:\\test\\', filename)
file = open(local_filename, 'wb')
ftp.retrbinary('RETR '+ filename, file.write)
file.close()
ftp.quit() # This is the “polite” way to close a connection
这适用于Python 2.5,Windows XP。
答案 1 :(得分:7)
如果这只是您想要解决的问题,我可能会建议wget
命令:
cd c:\destination
wget --mirror --continue --no-host-directories --user=username --password=s3cr3t ftp://hostname/source/path/
如果服务器上的文件更改,则--continue
选项可能非常危险。如果文件只是添加,那么它非常友好。
但是,如果这是一个学习练习,你想让你的课程有效,我想你应该从这一行开始:
for subdir, dirs, files in os.walk(directory):
directory
在您的大多数程序中都是远程源目录,但os.walk()
函数无法遍历远程目录。您需要使用提供给retrlines
函数的回调自己迭代返回的文件。
查看MLSD
或NLST
选项而不是LIST
,它们可能更容易解析。 (请注意,FTP实际上并没有指定列表的外观;它总是打算由控制台上的人驱动,或者传输特定的文件名。因此,使用FTP列表做聪明事情的程序会将它们呈现给用户对于奇怪或模糊的服务器,GUI可能必须拥有大量的特殊情况代码。当面对恶意文件名时,他们可能都会做一些愚蠢的事情。)
您可以使用sftp
吗? sftp
确实有关于如何解析文件列表的规范,不清楚地传输用户名/密码,并且没有被动与活动连接的巨大烦恼 - 它只使用单一连接,这意味着它可以在比FTP更多的防火墙上工作。
修改:您需要将“可调用”对象传递给retrlines
函数。可调用对象是定义__call__
方法的类的实例,或者是函数。虽然函数可能更容易描述,但类的实例可能更有用。 (您可以使用实例来收集文件名,但该函数必须写入全局变量。不好。)
这是最简单的可调用对象之一:
>>> class c:
... def __call__(self, *args):
... print(args)
...
>>> f = c()
>>> f('hello')
('hello',)
>>> f('hello', 'world')
('hello', 'world')
这将创建一个新类c
,用于定义实例方法__call__
。这只是以相当愚蠢的方式打印它的参数,但它显示了我们谈论的最小化。 :)
如果你想要更聪明的东西,它可以做这样的事情:
class handle_lines:
def __init__(self):
self.lines = []
def __call__(self, *args):
self.lines << args[0]
使用此类的对象调用iterlines
,然后查看对象的lines
成员以获取详细信息。
答案 2 :(得分:3)
我认为这段代码有点过分。
(来自python示例https://docs.python.org/2/library/ftplib.html)在ftp.login()和设置ftp.cwd()之后你可以使用:
os.chdir(ddir)
ls = ftp.nlst()
count = len(ls)
curr = 0
print "found {} files".format(count)
for fn in ls:
curr += 1
print 'Processing file {} ... {} of {} ...'.format(fn, curr, count)
ftp.retrbinary('RETR ' + fn, open(fn, 'wb').write)
ftp.quit()
print "download complete."
下载所有文件。
答案 3 :(得分:0)
我是初学者,所以我没有有效地编写代码,但我做了它并测试它是否正常工作。这就是我从ftp站点下载文件和文件夹所做的工作,但文件结构只有有限的深度。
try:
a = input("Enter hostname : ")
b = input("Enter username : ")
c = input("Enter password : ")
from ftplib import FTP
import os
os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp")
os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp")
ftp = FTP(host = a, user= b, passwd = c)
D = ftp.nlst()
for d in D:
l = len(d)
char = False
for i in range(0,l):
char = char or d[i]=="."
if not char:
ftp.cwd("..")
ftp.cwd("..")
E = ftp.nlst("%s"%(d))
ftp.cwd("%s"%(d))
try:
os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s"%(d))
except:
print("you can debug if you try some more")
finally:
os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s"%(d))
for e in E:
l1 = len(e)
char1 = False
for i in range(0,l1):
char1 = char1 or e[i]=="."
if not char1:
ftp.cwd("..")
ftp.cwd("..")
F = ftp.nlst("%s/%s"%(d,e))
ftp.cwd("%s/%s"%(d,e))
try:
os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s\\%s"%(d,e))
except:
print("you can debug if you try some more")
finally:
os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s\\%s"%(d,e))
for f in F:
if "." in f[2:]:
with open(f,'wb') as filef:
ftp.retrbinary('RETR %s' %(f), filef.write)
elif not "." in f:
try:
os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s\\%s\\%s"%(d,e,f))
except:
print("you can debug if you try some more")
elif "." in e[2:]:
os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s"%(d))
ftp.cwd("..")
ftp.cwd("..")
ftp.cwd("..")
ftp.cwd("%s"%(d))
with open(e,'wb') as filee:
ftp.retrbinary('RETR %s' %(e), filee.write)
elif "." in d[2:]:
ftp.cwd("..")
ftp.cwd("..")
os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp")
with open(d,'wb') as filed:
ftp.retrbinary('RETR %s'%(d), filed.write)
ftp.close()
print("Your files has been successfully downloaded and saved. Bye")
except:
print("try again you can do it")
finally:
print("code ran")
答案 4 :(得分:-1)
我们可以从python程序中调用dos脚本,而不是使用Python lib来ftp下载目录。在dos脚本中,我们将使用本机ftp协议,该协议可以使用mget *.*
从文件夹下载所有文件。
fetch.bat
ftp -s:fetch.txt
fetch.txt
open <ipaddress>
<userid>
<password>
bin (set the mnode to binary)
cd </desired directory>
mget *.*
bye
fetch.py
import os
os.system("fetch.bat")