FTP経由でディレクトリからすべてのファイルをダウンロードするスクリプトをまとめています。これまでのところ、1つのファイルを接続して取得することはできましたが、バッチで動作するようには思えません(ディレクトリからすべてのファイルを取得する)。
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()
実行してもあまり効果がないことがわかると思いますので、改善のための提案は大歓迎です。
私はこれをクラックすることができたので、将来の訪問者のために関連するコードを投稿します:
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で機能しました。
これが単にあなたが解決したい問題であるなら、私はwget
コマンドを提案するかもしれません:
_cd c:\destination
wget --mirror --continue --no-Host-directories --user=username --password=s3cr3t ftp://hostname/source/path/
_
_--continue
_オプションは、サーバー上のファイルchangeの場合、非常に危険です。ファイルがaddedのみの場合、非常にフレンドリーです。
ただし、これが学習課題であり、プログラムを機能させたい場合は、次の行を確認することから始めてください。
_for subdir, dirs, files in os.walk(directory):
_
directory
はほとんどのプログラムでremoteソースディレクトリでしたが、os.walk()
関数はをウォークできませんremoteディレクトリ。 retrlines
関数に提供されたコールバックを使用して、返されたファイルを自分で繰り返す必要があります。
MLSD
の代わりにNLST
またはLIST
オプションを見てください。おそらく、それらは解析しやすいでしょう。 (FTPはリストの表示方法を実際に指定しないことに注意してください。コンソールで人間が操作するか、特定のファイル名を転送することを常に意図していました。 GUIは、奇妙なサーバーや不明瞭なサーバーのために、おそらく特別なケースコードの膨大な山を持たなければなりません。そして、それらはすべて、悪意のあるファイル名に直面したとき、おそらく愚かなことをします。
代わりに sftp
を使用できますか? sftp
doesには、ファイル一覧の解析方法に関する仕様があり、ユーザー名/パスワードを平文で送信せず、巨人がいませんパッシブ接続とアクティブ接続の煩わしさ-単一の接続を使用するだけです。つまり、FTPよりも多くのファイアウォールで機能します。
Edit: 'callable'オブジェクトをretrlines
関数に渡す必要があります。呼び出し可能オブジェクトは、___call__
_メソッドを定義したクラスのインスタンス、または関数のいずれかです。関数の記述は簡単かもしれませんが、クラスのインスタンスの方が便利な場合があります。 (インスタンスを使用してファイル名を収集できますが、関数はグローバル変数に書き込む必要があります。悪い。)
最も単純な呼び出し可能オブジェクトの1つを次に示します。
_>>> class c:
... def __call__(self, *args):
... print(args)
...
>>> f = c()
>>> f('hello')
('hello',)
>>> f('hello', 'world')
('hello', 'world')
_
これにより、インスタンスメソッド___call__
_を定義する新しいクラスc
が作成されます。これは引数をかなり馬鹿げた方法で表示するだけですが、私たちが話している最小限度を示しています。 :)
よりスマートなものが必要な場合は、次のようなことができます。
_class handle_lines:
def __init__(self):
self.lines = []
def __call__(self, *args):
self.lines << args[0]
_
このクラスのオブジェクトでiterlines
を呼び出してから、オブジェクトのlines
メンバーで詳細を確認します。
このコードはちょっとやり過ぎだと思います。
(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."
すべてのファイルをダウンロードします。
再帰的ソリューション(py 2.7):
import os, ftplib, shutil, operator
def cloneFTP((addr, user, passw), remote, local):
try:
ftp = ftplib.FTP(addr)
ftp.login(user, passw)
ftp.cwd(remote)
except:
try: ftp.quit()
except: pass
print 'Invalid input ftp data!'
return False
try: shutil.rmtree(local)
except: pass
try: os.makedirs(local)
except: pass
dirs = []
for filename in ftp.nlst():
try:
ftp.size(filename)
ftp.retrbinary('RETR '+ filename, open(os.path.join(local, filename), 'wb').write)
except:
dirs.append(filename)
ftp.quit()
res = map(lambda d: cloneFTP((addr, user, passw), os.path.join(remote, d), os.path.join(local, d)), dirs)
return reduce(operator.iand, res, True)
私は初心者なので、コードを効率的に作成していませんが、作成し、動作することをテストしました。これは、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")