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?
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>>"
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
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)
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:
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
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
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.
:) 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 ...