Как узнать, успешно ли выполнено urllib.urlretrieve?
urllib.urlretrieve
возвращает молча, даже если файл не существует на удаленном http-сервере, он просто сохраняет html-страницу в указанном файле. Например:
urllib.urlretrieve('http://google.com/abc.jpg', 'abc.jpg')
просто возвращается молча, даже если abc.jpg не существует на сервере google.com, сгенерированный abc.jpg
не является допустимым файлом jpg, он фактически является html-страницей. Я думаю, что возвращенные заголовки (экземпляр httplib.HTTPMessage) могут использоваться для фактического определения того, успешны ли результаты поиска или нет, но я не могу найти какой-либо документ для httplib.HTTPMessage
.
Может ли кто-нибудь предоставить некоторую информацию об этой проблеме?
Ответы
Ответ 1
Рассмотрите возможность использования urllib2
, если это возможно в вашем случае. Он более продвинутый и простой в использовании, чем urllib
.
Вы можете легко обнаруживать любые ошибки 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
- фактически HTTPResponse
объект, который вы можете сделать много полезного:
>>> resp = urllib2.urlopen("http://google.com/")
>>> resp.code
200
>>> resp.headers["content-type"]
'text/html; charset=windows-1251'
>>> resp.read()
"<<ACTUAL HTML>>"
Ответ 2
Я делаю это просто:
# 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
Ответ 3
В соответствии с документацией есть недокументированный
чтобы получить доступ к сообщению, похоже, что вы делаете что-то вроде:
a, b=urllib.urlretrieve('http://google.com/abc.jpg', r'c:\abc.jpg')
b - это экземпляр сообщения
Поскольку я узнал, что Python всегда полезно использовать возможности Python для интроспекции при вводе
dir(b)
Я вижу множество методов или функций для воспроизведения с помощью
И затем я начал делать вещи с помощью b
например
b.items()
Перечисляет много интересных вещей, я подозреваю, что игра с этими вещами позволит вам получить атрибут, который вы хотите манипулировать.
Извините, это такой новичок, но я пытаюсь освоить, как использовать возможности самоанализа, чтобы улучшить свое обучение, и ваши вопросы просто появились.
Ну, я попробовал что-то интересное, связанное с этим, - мне было интересно, могу ли я автоматически получить вывод из каждой из вещей, которые появились в каталоге, где не нужны параметры, поэтому я написал:
needparam=[]
for each in dir(b):
x='b.'+each+'()'
try:
eval(x)
print x
except:
needparam.append(x)
Ответ 4
Вы можете создать новый URLopener (наследовать от FancyURLopener) и генерировать исключения или обрабатывать ошибки любым способом. К сожалению, FancyURLopener игнорирует 404 и другие ошибки. См. Этот вопрос:
Как уловить ошибку 404 в urllib.urlretrieve
Ответ 5
Я закончил свою собственную реализацию retrieve
, с помощью pycurl
он поддерживает больше протоколов, чем urllib/urllib2, надеюсь, что это может помочь другим людям.
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
Ответ 6
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
Ответ 7
:) Мой первый пост на StackOverflow, был lurker в течение многих лет.:)
К сожалению, dir (urllib.urlretrieve) недостаточно полезной информации.
Поэтому из этой темы я пробовал написать это:
a,b = urllib.urlretrieve(imgURL, saveTo)
print "A:", a
print "B:", b
который произвел это:
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
Я думаю, можно проверить:
if b.Content-Length > 0:
Мой следующий шаг - проверить сценарий, в котором происходит сбой получения...
Ответ 8
Результаты против другого сервера/веб-сайта - то, что возвращается в "В", является немного случайным, но можно проверить определенные значения:
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
В "плохом" случае (несуществующий файл образа) "B" извлек небольшой фрагмент кода (Googlebot?) HTML и сохранил его как цель, а значит Content-Length из 1363 байта.