2009-06-12 19 views
48

powraca w trybie dyskretnym, nawet jeśli plik nie istnieje na zdalnym serwerze http, po prostu zapisuje stronę html w podanym pliku. Na przykład:Jak sprawdzić, czy urllib.urlretrieve się powiedzie?

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

prostu zwraca cicho, nawet jeśli abc.jpg nie istnieje na serwerze google.com, wygenerowany abc.jpg nie jest prawidłowy plik jpg, to faktycznie strona html. Przypuszczam, że zwrócone nagłówki (instancja httplib.HTTPMessage) mogą być używane do rzeczywistego stwierdzenia, czy odzyskiwane są sukcesy, czy nie, ale nie mogę znaleźć żadnego dokumentu dla httplib.HTTPMessage.

Czy ktoś może podać jakieś informacje na temat tego problemu?

Odpowiedz

22

Rozważ skorzystanie z urllib2, jeśli jest to możliwe w twoim przypadku. Jest bardziej zaawansowany i łatwy w użyciu niż urllib.

można wykryć ewentualne błędy HTTP łatwo:

>>> 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 jest rzeczywiście HTTPResponse obiekt, który można zrobić wiele pożytecznych rzeczy:

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

Czy jednak urllib2 może zapewnić zachowanie pamięci podręcznej urlretrieve? Czy będziemy musieli go ponownie wdrożyć? – Kiv

+0

Zobacz tę niesamowitą recepturę z ActiveState: http://code.activestate.com/recipes/491261/ Używamy go w naszym bieżącym projekcie, działa bezbłędnie –

+1

urlopen nie zapewnia funkcji hook (aby wyświetlić pasek postępu dla przykład) jak urlretrieve. –

2

Zgodnie z dokumentacją jest to undocumented

, aby uzyskać dostęp do wiadomości, że wygląda jak zrobić coś takiego:

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

b jest instancja wiadomość

Odkąd dowiedziałem się, że Python zawsze przydaje się, aby wykorzystać zdolność Pythona do introspekcji, kiedy wpisuję

widzę wiele metod lub funkcji, aby grać z

a potem zaczął robić rzeczy b

np

b.items() 

Listy wiele ciekawych rzeczy, podejrzewam, że zabawy z te rzeczy pozwolą ci uzyskać atrybut, którym chcesz manipulować.

Przepraszam, że jest to odpowiedź tak początkującego, ale staram się opanować, jak wykorzystać zdolności introspekcji, aby poprawić moją naukę, a pytania pojawiły się po prostu.

Dobrze Próbowałem coś ciekawego związane z tym, zastanawiałem się, czy mogę automatycznie uzyskać wyjście z każdej rzeczy, która pojawiła się w katalogu, w którym nie potrzeba parametry więc napisałem:

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

Nie ma dla mnie statusu, a Twój kod działa tylko raz. Spróbuj 'dla k in b: print"% s:% r "% (k, b [k])' –

1

skończyło się z moim retrieve realizacji , z pomocą pycurl obsługuje więcej protokołów niż urllib/urllib2, mam nadzieję, że może pomóc innym.

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

Możesz utworzyć nowy URLopener (dziedziczą po FancyURLopener) i zgłaszać wyjątki lub obsługiwać błędy w dowolny sposób. Niestety FancyURLopener ignoruje 404 i inne błędy. Zobacz na to pytanie:

How to catch 404 error in urllib.urlretrieve

6

I keep it 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 
+0

Lepszym pomysłem jest 'shutil.copyfileobj'. – lericson

+1

Jak to, 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

:) mój pierwszy post na StackOverflow, były lurker lat. :)

Niestety dir (urllib.urlretrieve) zawiera niedobór użytecznych informacji. Więc z tego wątku dotąd próbowałem pisać tak:

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

która wyprodukowała ten:

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 

Chyba można sprawdzić:

if b.Content-Length > 0: 

Moim następnym krokiem jest przetestowanie scenariusz, w którym pobieranie nie powiedzie się ...

+0

b.getheader ("Długość treści") normalnie byłaby większa niż 0, nawet w przypadku 404 (jeśli plik nie istnieje) –

0

Wyniki z innego serwera/strony - co wraca w „B” jest nieco przypadkowa, ale można przetestować dla pewnych wartości:

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 

w „złym” sprawy (non-istniejący plik obrazu) „B” pobrana mały kawałek (Googlebot?) Kod HTML i zapisany jako cel, stąd Długość treści 1363 bajtów.

Powiązane problemy