urlretrieve has attribute python networking urllib

has - urllib python install



¿Cómo saber si urllib.urlretrieve tiene éxito? (8)

urllib.urlretrieve devuelve silenciosamente incluso si el archivo no existe en el servidor http remoto, solo guarda una página html en el archivo nombrado. Por ejemplo:

urllib.urlretrieve(''http://google.com/abc.jpg'', ''abc.jpg'')

simplemente regresa silenciosamente, incluso si abc.jpg no existe en el servidor google.com, el abc.jpg generado no es un archivo jpg válido, en realidad es una página html. Supongo que los encabezados devueltos (una instancia de httplib.HTTPMessage) se pueden usar para decir realmente si la recuperación tiene éxito o no, pero no puedo encontrar ningún documento para httplib.HTTPMessage .

¿Alguien puede proporcionar información sobre este problema?


:) Mi primera publicación en , ha sido un acecho durante años. :)

Tristemente, dir (urllib.urlretrieve) es deficiente en información útil. Así que de este hilo hasta el momento intenté escribir esto:

a,b = urllib.urlretrieve(imgURL, saveTo) print "A:", a print "B:", b

que produjo esto:

A: /home/myuser/targetfile.gif B: Accept-Ranges: bytes Access-Control-Allow-Origin: * Cache-Control: max-age=604800 Content-Type: image/gif Date: Mon, 07 Mar 2016 23:37:34 GMT Etag: "4e1a5d9cc0857184df682518b9b0da33" Last-Modified: Sun, 06 Mar 2016 21:16:48 GMT Server: ECS (hnd/057A) Timing-Allow-Origin: * X-Cache: HIT Content-Length: 27027 Connection: close

Creo que uno puede verificar:

if b.Content-Length > 0:

Mi siguiente paso es probar un escenario donde falla la recuperación ...


Considere usar urllib2 si es posible en su caso. Es más avanzado y fácil de usar que urllib .

Puede detectar cualquier error HTTP fácilmente:

>>> import urllib2 >>> resp = urllib2.urlopen("http://google.com/abc.jpg") Traceback (most recent call last): <<MANY LINES SKIPPED>> urllib2.HTTPError: HTTP Error 404: Not Found

resp es en realidad HTTPResponse objeto HTTPResponse que puede hacer muchas cosas útiles con:

>>> resp = urllib2.urlopen("http://google.com/") >>> resp.code 200 >>> resp.headers["content-type"] ''text/html; charset=windows-1251'' >>> resp.read() "<<ACTUAL HTML>>"


De acuerdo con la documentación, está undocumented

para tener acceso al mensaje, parece que haces algo como:

a, b=urllib.urlretrieve(''http://google.com/abc.jpg'', r''c:/abc.jpg'')

b es la instancia del mensaje

Desde que aprendí que Python siempre es útil usar la habilidad de Python para ser introspectivo cuando escribo

dir(b)

Veo muchos métodos o funciones con los que jugar

Y luego comencé a hacer cosas con b

por ejemplo

b.items()

Enumera muchas cosas interesantes, sospecho que jugar con estas cosas te permitirá obtener el atributo que deseas manipular.

Lo siento, esta es la respuesta de un principiante, pero estoy tratando de dominar cómo usar las habilidades de introspección para mejorar mi aprendizaje y sus preguntas simplemente aparecieron.

Bueno, probé algo interesante relacionado con esto, me preguntaba si podría obtener automáticamente el resultado de cada una de las cosas que aparecían en el directorio que no necesitaban parámetros, así que escribí:

needparam=[] for each in dir(b): x=''b.''+each+''()'' try: eval(x) print x except: needparam.append(x)


Lo mantengo simple:

# Simple downloading with progress indicator, by Cees Timmerman, 16mar12. import urllib2 remote = r"http://some.big.file" local = r"c:/downloads/bigfile.dat" u = urllib2.urlopen(remote) h = u.info() totalSize = int(h["Content-Length"]) print "Downloading %s bytes..." % totalSize, fp = open(local, ''wb'') blockSize = 8192 #100000 # urllib.urlretrieve uses 8192 count = 0 while True: chunk = u.read(blockSize) if not chunk: break fp.write(chunk) count += 1 if totalSize > 0: percent = int(count * blockSize * 100 / totalSize) if percent > 100: percent = 100 print "%2d%%" % percent, if percent < 100: print "/b/b/b/b/b", # Erase "NN% " else: print "Done." fp.flush() fp.close() if not totalSize: print


Puede crear un nuevo URLopener (heredar de FancyURLopener) y lanzar excepciones o manejar errores de la forma que desee. Desafortunadamente, FancyURLopener ignora 404 y otros errores. Ver esta pregunta:

Cómo atrapar el error 404 en urllib.urlretrieve


Resultados contra otro servidor / sitio web: lo que aparece en "B" es un poco aleatorio, pero se pueden probar ciertos valores:

A: get_good.jpg B: Date: Tue, 08 Mar 2016 00:44:19 GMT Server: Apache Last-Modified: Sat, 02 Jan 2016 09:17:21 GMT ETag: "524cf9-18afe-528565aef9ef0" Accept-Ranges: bytes Content-Length: 101118 Connection: close Content-Type: image/jpeg A: get_bad.jpg B: Date: Tue, 08 Mar 2016 00:44:20 GMT Server: Apache Content-Length: 1363 X-Frame-Options: deny Connection: close Content-Type: text/html

En el caso ''malo'' (archivo de imagen no existente), "B" recuperó una pequeña porción del código HTML (Googlebot?) Y lo guardó como destino, por lo tanto, Content-Length de 1363 bytes.


Terminé con mi propia implementación de retrieve , con la ayuda de pycurl admite más protocolos que urllib / urllib2, espero que pueda ayudar a otras personas.

import tempfile import pycurl import os def get_filename_parts_from_url(url): fullname = url.split(''/'')[-1].split(''#'')[0].split(''?'')[0] t = list(os.path.splitext(fullname)) if t[1]: t[1] = t[1][1:] return t def retrieve(url, filename=None): if not filename: garbage, suffix = get_filename_parts_from_url(url) f = tempfile.NamedTemporaryFile(suffix = ''.'' + suffix, delete=False) filename = f.name else: f = open(filename, ''wb'') c = pycurl.Curl() c.setopt(pycurl.URL, str(url)) c.setopt(pycurl.WRITEFUNCTION, f.write) try: c.perform() except: filename = None finally: c.close() f.close() return filename


class MyURLopener(urllib.FancyURLopener): http_error_default = urllib.URLopener.http_error_default url = "http://page404.com" filename = "download.txt" def reporthook(blockcount, blocksize, totalsize): pass ... try: (f,headers)=MyURLopener().retrieve(url, filename, reporthook) except Exception, e: print e