it-swarm.com.de

Python-FTP lädt alle Dateien im Verzeichnis herunter

Python Newb hier also bitte ertragen Sie mit mir. Ich stelle ein Skript zusammen, um alle Dateien aus einem Verzeichnis per FTP herunterzuladen. Bis jetzt habe ich es geschafft, eine Datei zu verbinden und abzurufen, aber ich kann mich scheinbar nicht im Batch arbeiten lassen (alle Dateien aus dem Verzeichnis holen). Hier ist, was ich bis jetzt habe:

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()

Ich wette, Sie können sagen, dass es bei der Ausführung nicht viel tut, daher würden wir uns über Verbesserungsvorschläge freuen

PS Das sind keine Hausaufgaben: DD

Vielen Dank!!

26
Sosti

Ich habe es geschafft, dies zu knacken, und poste jetzt den relevanten Code für zukünftige Besucher:

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

Dies funktionierte für mich unter Python 2.5, Windows XP.

62
Sosti

Wenn dies nur ein Problem ist, das Sie lösen möchten, kann ich den Befehl wget vorschlagen:

cd c:\destination
wget --mirror --continue --no-Host-directories --user=username --password=s3cr3t ftp://hostname/source/path/

Die --continue-Option kann sehr gefährlich sein, wenn Dateien change auf dem Server vorhanden sind. Wenn Dateien nur hinzugefügt sind, ist das sehr freundlich.

Wenn dies jedoch eine Lernübung für Sie ist und Sie Ihr Programm zum Laufen bringen möchten, denke ich, sollten Sie mit dieser Zeile beginnen:

for subdir, dirs, files in os.walk(directory):

directory war in den meisten Fällen das Quellverzeichnis remote, aber die Funktion os.walk() kann kein remote-Verzeichnis abrufen. Sie müssen die zurückgegebenen Dateien selbst durchlaufen, indem Sie einen Rückruf für die Funktion retrlines verwenden.

Werfen Sie einen Blick auf die Optionen MLSD oder NLST anstelle von LIST, da sie wahrscheinlich einfacher zu analysieren sind. (Beachten Sie, dass FTP nicht genau angibt, wie Listen aussehen sollen; es war immer beabsichtigt, von einem Benutzer an einer Konsole gesteuert oder ein bestimmter Dateiname übertragen zu werden. Programme, die clevere Dinge mit FTP-Listen machen, stellen sie dem Benutzer also vor Eine grafische Benutzeroberfläche muss wahrscheinlich einen riesigen Stapel von Sonderfallcode für ungerade oder obskure Server haben. Und sie machen wahrscheinlich alle etwas Dummes, wenn sie mit bösartigen Dateinamen konfrontiert werden.

Können Sie stattdessen sftp verwenden? sftpdoes hat eine Spezifikation dafür, wie Dateiauflistungen analysiert werden sollen, überträgt keinen Benutzernamen/kein Kennwort und gibt nicht die ärgerliche Beeinträchtigung passiver oder aktiver Verbindungen aus Die einzige Verbindung funktioniert also über mehr Firewalls als FTP.

Edit: Sie müssen ein 'callable'-Objekt an die Funktion retrlines übergeben. Ein aufrufbares Objekt ist entweder eine Instanz einer Klasse, die eine __call__-Methode definiert hat, oder eine Funktion. Während die Funktion möglicherweise einfacher zu beschreiben ist, kann eine Instanz einer Klasse nützlicher sein. (Sie können die Instanz verwenden, um die Dateinamen zu sammeln, aber die Funktion müsste in eine globale Variable schreiben. Ungültig.)

Hier ist eines der einfachsten aufrufbaren Objekte:

>>> class c:
...  def __call__(self, *args):
...   print(args)
...
>>> f = c()
>>> f('hello')
('hello',)
>>> f('hello', 'world')
('hello', 'world')

Dadurch wird eine neue Klasse c erstellt, die eine Instanzmethode __call__ definiert. Dies gibt nur seine Argumente ziemlich dumm aus, aber es zeigt, wie minimal wir sprechen. :)

Wenn Sie etwas intelligenteres wollen, können Sie Folgendes tun:

class handle_lines:
  def __init__(self):
    self.lines = []
  def __call__(self, *args):
    self.lines << args[0]

Rufen Sie iterlines mit einem Objekt dieser Klasse auf und suchen Sie im Member lines des Objekts nach Details.

7
sarnold

ich denke, dieser Code ist ein bisschen übertrieben. 

(aus dem Python-Beispiel https://docs.python.org/2/library/ftplib.html ) Nach ftp.login () und dem Setzen von ftp.cwd () können Sie einfach Folgendes verwenden:

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."

um alle Dateien herunterzuladen.

3
kztd

Eine rekursive Lösung (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)
0
Iulian Bute

Ich bin ein Anfänger, also habe ich den Code nicht effizient erstellt, aber ich habe es gemacht und getestet und es funktioniert. Dies ist, was ich zum Herunterladen von Dateien und Ordnern von der FTP-Site getan habe, aber nur eine begrenzte Tiefe in der Dateistruktur.

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")
0
PremVijay