2009-06-12 23 views
48

urllib.urlretrieve ritorna in silenzio anche se il file non esiste sul server http remoto, semplicemente salva una pagina HTML per il file denominato. Per esempio:Come sapere se urllib.urlretrieve ha esito positivo?

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

torna solo in silenzio, anche se abc.jpg non esiste sul server di google.com, il generato abc.jpg non è un file jpg valida, in realtà è una pagina html. Credo che le intestazioni restituite (un'istanza httplib.HTTPMessage) possono essere utilizzati per dire realmente se i successi di recupero o no, ma non riesco a trovare alcun documento per httplib.HTTPMessage.

Qualcuno può fornire alcune informazioni su questo problema?

risposta

22

Valuta di utilizzare urllib2 se possibile nel tuo caso. È più avanzato e facile da usare rispetto a urllib.

è possibile rilevare eventuali errori HTTP facilmente:

>>> 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 è in realtà HTTPResponse oggetto che si può fare un sacco di cose utili con:

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

È possibile che urllib2 fornisca il comportamento di caching di urlretrieve? O dovremmo reimplementarlo? – Kiv

+0

Vedere questa fantastica destinazione da ActiveState: http://code.activestate.com/recipes/491261/ Lo stiamo usando nel nostro progetto attuale, funziona perfettamente –

+1

urlopen non fornisce una funzione di aggancio (per mostrare la barra di avanzamento per esempio) come urlretrieve. –

2

Secondo la documentazione si è undocumented

per ottenere l'accesso al messaggio sembra che si fa qualcosa di simile:

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

b è l'istanza di messaggio

Da quando ho imparato che Python è sempre utile usare la capacità di Python di essere introspettiva quando digito

dir(b) 

Vedo un sacco di metodi o funzioni di giocare con

E poi ho iniziato a fare le cose con b

ad esempio

b.items() 

Liste sacco di cose interessanti, ho il sospetto che giocare con queste cose ti permetteranno di ottenere l'attributo che vuoi manipolare.

Spiacente, questo è tale risposta di un principiante, ma sto cercando di padroneggiare come utilizzare le capacità di introspezione per migliorare il mio apprendimento e le vostre domande appena spuntato.

Beh ho provato qualcosa di interessante relativo a questo, mi chiedevo se avrei potuto ottenere automaticamente l'uscita da ciascuna delle cose che si presentò nella directory che non ha bisogno di parametri così ho scritto:

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

Nessuno stato per me e il tuo codice funziona solo una volta. Prova 'per k in b: stampa"% s:% r "% (k, b [k])' –

1

ho finito con la mia retrieve implementazione , con l'aiuto di pycurl supporta più protocolli di urllib/urllib2, spero che possa aiutare altre persone.

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 
2

È possibile creare un nuovo URLopener (ereditare da FancyURLopener) e generare eccezioni o gestire errori qualsiasi modo si desidera. Sfortunatamente, FancyURLopener ignora 404 e altri errori. Vedere questa domanda:

How to catch 404 error in urllib.urlretrieve

6

lo tengo semplice:

# 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 
+0

Un'idea migliore è 'shutil.copyfileobj'. – lericson

+1

Come mai, lericson? –

0
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 
0

:) Il mio primo post su StackOverflow, sono stati un lurker per anni. :)

Purtroppo dir (urllib.urlretrieve) è carente in informazioni utili. Così da questa discussione finora ho provato a scrivere questo:

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

che ha prodotto questo:

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 

Credo che si possa verificare:

if b.Content-Length > 0: 

Il mio prossimo passo è quello di testare un scenario in cui il recupero non riesce ...

+0

b.getheader ('Content-length') normalmente dovrebbe essere maggiore di 0 anche su 404 (se il file non esiste) –

0

Risultati rispetto a un altro server/sito Web - cosa torna in "B" è un po 'casuale, ma si può verificare alcuni valori:

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 

Nel caso 'cattivo'(inesistente file immagine) "B" recuperato un piccolo pezzo di (Googlebot?) Codice HTML e salvato come destinazione, quindi Content-Length di 1363 byte.

Problemi correlati