requests humans from for python http download

humans - ¿Cómo descargar un archivo usando Python de una manera "más inteligente"?



python wget (5)

Basándome en los comentarios y en el informe de @ Oli, hice una solución como esta:

from os.path import basename from urlparse import urlsplit def url2name(url): return basename(urlsplit(url)[2]) def download(url, localFileName = None): localName = url2name(url) req = urllib2.Request(url) r = urllib2.urlopen(req) if r.info().has_key(''Content-Disposition''): # If the response has Content-Disposition, we take file name from it localName = r.info()[''Content-Disposition''].split(''filename='')[1] if localName[0] == ''"'' or localName[0] == "''": localName = localName[1:-1] elif r.url != url: # if we were redirected, the real file name we take from the final URL localName = url2name(r.url) if localFileName: # we can force to save the file as specified name localName = localFileName f = open(localName, ''wb'') f.write(r.read()) f.close()

Toma el nombre de archivo de Content-Disposition; si no está presente, utiliza el nombre de archivo de la URL (si se produjo una redirección, se tiene en cuenta la URL final).

Necesito descargar varios archivos a través de http en Python.

La forma más obvia de hacerlo es simplemente usar urllib2:

import urllib2 u = urllib2.urlopen(''http://server.com/file.html'') localFile = open(''file.html'', ''w'') localFile.write(u.read()) localFile.close()

Pero tendré que lidiar con las URL que son desagradables de alguna manera, digamos así: http://server.com/!Run.aspx/someoddtext/somemore?id=121&m=pdf . Cuando se descarga a través del navegador, el archivo tiene un nombre legible para los humanos, es decir. accounts.pdf .

¿Hay alguna forma de manejar eso en Python, así que no necesito saber los nombres de los archivos y codificarlos en mi script?


Combinando gran parte de lo anterior, aquí hay una solución más pitonica:

import urllib2 import shutil import urlparse import os def download(url, fileName=None): def getFileName(url,openUrl): if ''Content-Disposition'' in openUrl.info(): # If the response has Content-Disposition, try to get filename from it cd = dict(map( lambda x: x.strip().split(''='') if ''='' in x else (x.strip(),''''), openUrl.info()[''Content-Disposition''].split('';''))) if ''filename'' in cd: filename = cd[''filename''].strip("/"''") if filename: return filename # if no filename was found above, parse it out of the final URL. return os.path.basename(urlparse.urlsplit(openUrl.url)[2]) r = urllib2.urlopen(urllib2.Request(url)) try: fileName = fileName or getFileName(url,r) with open(fileName, ''wb'') as f: shutil.copyfileobj(r,f) finally: r.close()


Los scripts de descarga de ese tipo tienden a presionar un encabezado que le dice al agente de usuario qué nombre debe darle al archivo:

Content-Disposition: attachment; filename="the filename.ext"

Si puedes agarrar ese encabezado, puedes obtener el nombre de archivo correcto.

Hay otro hilo que tiene un poco de código que ofrecer para Content-Disposition -grabbing.

remotefile = urllib2.urlopen(''http://example.com/somefile.zip'') remotefile.info()[''Content-Disposition'']


Usando wget :

custom_file_name = "/custom/path/custom_name.ext" wget.download(url, custom_file_name)

Usando urlretrieve:

urllib.urlretrieve(url, custom_file_name)

urlretrieve también crea la estructura de directorios si no existe.


2 Kender :

if localName[0] == ''"'' or localName[0] == "''": localName = localName[1:-1]

no es seguro: el servidor web puede pasar un nombre mal formateado como ["file.ext] o [file.ext ''] o incluso estar vacío y localName [0] aumentará la excepción. El código correcto puede verse así:

localName = localName.replace(''"'', '''').replace("''", "") if localName == '''': localName = SOME_DEFAULT_FILE_NAME