2012-07-17 14 views
6

Ten prosty Python 3 scenariusz:Jak naprawić błąd ValueError: odczyt wyjątku zamkniętego pliku?

import urllib.request 

host = "scholar.google.com" 
link = "/scholar.bib?q=info:K7uZdMSvdQ0J:scholar.google.com/&output=citation&hl=en&as_sdt=1,14&ct=citation&cd=0" 
url = "http://" + host + link 
filename = "cite0.bib" 
print(url) 
urllib.request.urlretrieve(url, filename) 

podnosi ten wyjątek:

Traceback (most recent call last): 
    File "C:\Users\ricardo\Desktop\Google-Scholar\BibTex\test2.py", line 8, in <module> 
    urllib.request.urlretrieve(url, filename) 
    File "C:\Python32\lib\urllib\request.py", line 150, in urlretrieve 
    return _urlopener.retrieve(url, filename, reporthook, data) 
    File "C:\Python32\lib\urllib\request.py", line 1597, in retrieve 
    block = fp.read(bs) 
ValueError: read of closed file 

myślałem, że to może być tymczasowy problem, więc dodałem kilka prostych wyjątek obsługi tak:

import random 
import time 
import urllib.request 

host = "scholar.google.com" 
link = "/scholar.bib?q=info:K7uZdMSvdQ0J:scholar.google.com/&output=citation&hl=en&as_sdt=1,14&ct=citation&cd=0" 
url = "http://" + host + link 
filename = "cite0.bib" 
print(url) 
while True: 
    try: 
     print("Downloading...") 
     time.sleep(random.randint(0, 5)) 
     urllib.request.urlretrieve(url, filename) 
     break 
    except ValueError: 
     pass 

ale to po prostu drukuje Downloading... ad infinitum.

+0

Jeśli zajrzysz w "http: // scholar.google.com/robots.txt", zobaczysz, że Google zabrania automatycznego pobierania tej strony. A jeśli spróbujesz użyć 'wget' otrzymasz błąd' 403 Forbidden'. Podejrzewam, że dzieje się tak również z twoim scenariuszem. –

+0

@senderle Nie ma interfejsu API, więc parsuję go ręcznie. –

+0

@senderle, najprawdopodobniej musisz wysłać plik cookie, aby uzyskać zawartość. –

Odpowiedz

4

Twój adres URL zwraca kod błędu 403 i widocznie urllib.request.urlretrieve nie jest dobry w wykrywaniu wszystkich błędów HTTP, ponieważ używa urllib.request.FancyURLopener i tę ostatnią okazję do przełknięcia błąd poprzez odesłanie urlinfo zamiast podnoszenia błąd.

O naprawić, jeśli nadal chcesz używać urlretrieve można zastąpić FancyURLopener tak (kod zawarte również pokazać błąd):

import urllib.request 
from urllib.request import FancyURLopener 


class FixFancyURLOpener(FancyURLopener): 

    def http_error_default(self, url, fp, errcode, errmsg, headers): 
     if errcode == 403: 
      raise ValueError("403") 
     return super(FixFancyURLOpener, self).http_error_default(
      url, fp, errcode, errmsg, headers 
     ) 

# Monkey Patch 
urllib.request.FancyURLopener = FixFancyURLOpener 

url = "http://scholar.google.com/scholar.bib?q=info:K7uZdMSvdQ0J:scholar.google.com/&output=citation&hl=en&as_sdt=1,14&ct=citation&cd=0" 
urllib.request.urlretrieve(url, "cite0.bib") 

indziej i to co polecam można użyć urllib.request.urlopen tak:

fp = urllib.request.urlopen('http://scholar.google.com/scholar.bib?q=info:K7uZdMSvdQ0J:scholar.google.com/&output=citation&hl=en&as_sdt=1,14&ct=citation&cd=0') 
with open("citi0.bib", "w") as fo: 
    fo.write(fp.read()) 
+0

Dzięki za pomoc. +1 i akceptuję łatanie małp i ogólną pomoc, mimo że już sobie uświadomiłem, za powyższe komentarze, że 'robots.txt' uniemożliwia pobieranie tych plików. Zupełnie zapomniałem to sprawdzić. –