Pergunta

urllib.urlretrieve retorna silenciosamente, mesmo que o arquivo não existe no servidor http remoto, ele só salva uma página html para o arquivo nomeado. Por exemplo:

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

apenas retorna silenciosamente, mesmo se abc.jpg não existe no google.com servidor, o abc.jpg gerado não é um arquivo jpg válida, é realmente uma página html. Eu acho que os cabeçalhos retornados (a httplib.HTTPMessage exemplo) podem ser usados ??para realmente dizer se os sucessos de recuperação ou não, mas não consigo encontrar qualquer documento para httplib.HTTPMessage.

Alguém pode fornecer algumas informações sobre este problema?

Foi útil?

Solução

Considere o uso de urllib2 se possível no seu caso. É mais avançado e fácil de usar do que urllib.

Você pode detectar quaisquer erros de 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 é objeto realmente HTTPResponse que você pode fazer um monte de coisas úteis com:

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

Outras dicas

Eu mantê-lo simples:

# 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

De acordo com a documentação é é indocumentados

para obter acesso à mensagem parece que você fazer algo como:

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

b é a instância mensagem

Uma vez eu aprendi que Python é sempre útil usar a capacidade do Python para ser introspectivo quando digito

dir(b) 

Eu vejo um monte de métodos ou funções para jogar com

E então eu comecei a fazer as coisas com b

Por exemplo

b.items()

Listas muitas coisas interessantes, eu suspeito que brincar com essas coisas vão permitir que você obtenha o atributo que você deseja manipular.

Infelizmente este é tal resposta de um novato, mas eu estou tentando mestre como usar as habilidades de introspecção para melhorar a minha aprendizagem e suas perguntas só apareceu.

Bem, eu tentei algo interessante relacionado a este, eu estava me perguntando se eu poderia obter automaticamente a saída de cada uma das coisas que apareceram no diretório que não precisam de parâmetros então eu escrevi:

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

Você pode criar um novo URLopener (Herdar do FancyURLopener) e lançar exceções ou erros de lidar com qualquer maneira que você quer. Infelizmente, FancyURLopener ignora 404 e outros erros. Veja esta pergunta:

Como pegar 404 erro no urllib.urlretrieve

Eu acabei com a minha própria implementação retrieve, com a ajuda de pycurl ele suporta mais protocolos que urllib / urllib2, espero que possa ajudar outras pessoas.

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

:) Meu primeiro post no StackOverflow, ter sido um lurker por anos. :)

Infelizmente dir (urllib.urlretrieve) é deficiente em informações úteis. Assim, desde esta discussão, até agora, eu tentei escrever este:

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

que produziu o seguinte:

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

Eu acho que pode-se verificar:

if b.Content-Length > 0:

Meu próximo passo é testar um cenário em que a recuperação falhar ...

Os resultados contra outro servidor / website - o que vem de volta em "B" é um pouco aleatório, mas pode-se testar para determinados 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

No caso 'ruim' "B" recuperado um pequeno pedaço de código (arquivo de imagem não-existente) (Googlebot?) HTML e salva-lo como o alvo, portanto, Content-Length de 1363 bytes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top