2010-11-04 23 views
2

Donc j'essaye d'écrire un script pour télécharger un fichier image avec python et j'ai trouvé ce def en utilisant google mais chaque image que je le télécharge sort "corrompue". Toutes les idées ...Python Downloader

def download(url): 
"""Copy the contents of a file from a given URL 
to a local file. 
""" 
import urllib 
webFile = urllib.urlopen(url) 
localFile = open(url.split('/')[-1], 'w') 
localFile.write(webFile.read()) 
webFile.close() 
localFile.close() 

Edit: la balise de code n'a pas retenu les renfoncements très bien, mais je peux vous assurer qu'ils sont là, ce n'est pas mon problème.

+2

Pourquoi n'utilisez-vous pas 'urllib2'? –

+0

Aucune raison, c'est juste la façon dont la fonction était quand je l'ai trouvé. – John

+0

Notez que si le fichier est très volumineux, il est très inefficace de lire tout cela en mémoire comme ceci. Comme indiqué ci-dessous, urllib.urlretrieve() est une bien meilleure option. – nealmcb

Répondre

5

Vous devez ouvrir le fichier local en mode binaire:

localFile = open(url.split('/')[-1], 'wb') 

Sinon, les caractères CR/LF dans le flux binaire seront mutilées, corrompre le fichier.

3

Vous devez inclure le drapeau 'b' si vous avez l'intention d'écrire un fichier binaire. Ligne 7 devient:

localFile = open(url.split('/')[-1], 'wb') 

Il n'est pas nécessaire pour que le code fonctionne, mais à l'avenir vous pourriez envisager:

  • Importation en dehors de vos fonctions.
  • En utilisant os.path.basename, plutôt que l'analyse de chaîne pour obtenir le composant name d'un chemin.
  • Utilisation de l'instruction with pour gérer les fichiers, plutôt que de devoir les fermer manuellement. Il rend votre code plus propre et garantit qu'il est correctement fermé si votre code génère une exception.

Je réécrire votre code comme:

import urllib 
import os.path 

def download(url): 
"""Copy the contents of a file from a given URL 
to a local file in the current directory. 
""" 
with urllib.urlopen(url) as webFile: 
    with open(os.path.basename(url), 'wb') as localFile: 
    localFile.write(webFile.read()) 
6

Vous pouvez simply do

urllib.urlretrieve(url, filename) 

et vous épargner des ennuis.

+0

oui, merci de le signaler. C'est finalement ce que j'ai fini par faire. Et juste utilisé ntpath.basename pour retirer le nom de fichier à la fin de l'URL – John

0
import subprocess 
outfile = "foo.txt" 
url = "http://some/web/site/foo.txt" 
cmd = "curl.exe -f -o %(outfile)s %(url)s" % locals() 
subprocess.check_call(cmd) 

écosser dehors peut sembler inélégante mais quand vous commencez à rencontrer des problèmes avec des sites plus sophistiqués, mais curl a une richesse de la logique pour la manipulation que vous passer à travers les barrières imposées par les serveurs Web (cookies, l'authentification, sessions, etc.

wget est une autre alternative.

2

Il sort corrompu parce que la fonction que vous utilisez écrit les octets dans le fichier, comme si c'était du texte brut. Cependant, ce que vous devez faire est de lui écrire les octets en mode binaire (wb). Voici une idée de ce que vous devez faire:

import urllib 

def Download(url, filename): 
    Data = urllib.urlopen(url).read() 
    File = open(filename, 'wb') 
    File.Write(Data) 
    #Neatly close off the file... 
    File.flush() 
    File.close() 
    #Cleanup, for you neat-freaks. 
    del Data, File