web-dev-qa-db-fra.com

Comment savoir si urllib.urlretrieve réussit?

urllib.urlretrieve retourne en silence même si le fichier n'existe pas sur le serveur http distant, il enregistre simplement une page html dans le fichier nommé. Par exemple:

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

retourne simplement en silence, même si abc.jpg n'existe pas sur le serveur google.com, le abc.jpg généré n'est pas un fichier jpg valide, il s'agit en réalité d'une page html. J'imagine que les en-têtes renvoyés (une instance httplib.HTTPMessage) peuvent être utilisés pour indiquer si la récupération a réussi ou non, mais je ne trouve aucun document pour httplib.HTTPMessage.

Quelqu'un peut-il fournir des informations sur ce problème?

50
btw0

Pensez à utiliser urllib2 si cela est possible dans votre cas. Il est plus avancé et facile à utiliser que urllib.

Vous pouvez facilement détecter les erreurs HTTP:

>>> 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 est en fait un objet HTTPResponse avec lequel vous pouvez faire beaucoup de choses utiles

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

Je reste 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
6
Cees Timmerman

Selon la documentation, is undocumented

pour avoir accès au message, on dirait que vous faites quelque chose comme:

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

b est l'instance du message

Depuis que j'ai appris que Python, il est toujours utile d'utiliser la capacité de Python à être introspectif lorsque je tape 

dir(b) 

Je vois beaucoup de méthodes ou de fonctions pour jouer avec

Et puis j'ai commencé à faire des choses avec b

par exemple 

b.items()

Listes de beaucoup de choses intéressantes, je suppose que jouer avec ces choses vous permettra d'obtenir l'attribut que vous voulez manipuler.

Désolé, cette réponse est tellement novice, mais je suis en train d’essayer de maîtriser l’utilisation des capacités d’introspection pour améliorer mon apprentissage, et vos questions sont apparues.

Eh bien, j'ai essayé quelque chose d'intéressant lié à cela. Je me demandais si je pouvais obtenir automatiquement le résultat de chacun des éléments figurant dans le répertoire qui ne nécessitaient pas de paramètres. J'ai donc écrit:

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

Vous pouvez créer une nouvelle URLopener (hériter de FancyURLopener) et générer des exceptions ou gérer les erreurs comme vous le souhaitez. Malheureusement, FancyURLopener ignore les erreurs 404 et autres. Voir cette question:

Comment intercepter l'erreur 404 dans urllib.urlretrieve

2
Christian Davén

Je me suis retrouvé avec ma propre implémentation retrieve, avec l’aide de pycurl, il prend en charge davantage de protocoles que urllib/urllib2. J'espère que cela pourra aider d’autres personnes.

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
1
btw0
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
gzliuqingyun

Résultats sur un autre serveur/site web - ce qui revient dans "B" est un peu aléatoire, mais on peut tester certaines valeurs:

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

Dans le «mauvais» cas (fichier image non existant), "B" a récupéré une petite partie du code HTML (Googlebot?) Et l'a enregistré comme cible, d'où une longueur de contenu de 1363 octets. 

0
fotonix

:) Mon premier article sur StackOverflow est un lurker depuis des années. :)

Malheureusement, dir (urllib.urlretrieve) manque d’informations utiles ... Donc, à partir de ce fil, j’ai essayé d’écrire ceci:

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

qui a produit ceci:

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

Je suppose qu'on peut vérifier:

if b.Content-Length > 0:

Ma prochaine étape consiste à tester un scénario où la récupération échoue ...

0
fotonix