2012-07-17 7 views
6

Este sencillo Python 3 guión:¿Cómo puedo arreglar un ValueError: leer de la excepción de archivo cerrado?

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) 

plantea esta excepción:

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 

pensé que esto podría ser un problema temporal, por lo que añade alguna excepción sencillo el manejo de este modo:

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 

pero esto solo imprime Downloading... ad infinitum.

+0

Si mira en 'http: // scholar.google.com/robots.txt', verá que Google prohíbe las descargas automáticas de esta página. Y si intentas usar 'wget', obtendrás el error' 403 Forbidden'. Sospecho que esto también le está sucediendo a tu script. –

+0

@senderle No hay una API, entonces la estoy analizando manualmente. –

+0

@senderle, lo más probable es que necesite enviar una cookie para obtener el contenido. –

Respuesta

4

La URL devuelve un error de código 403 y al parecer urllib.request.urlretrieve no es bueno para detectar todos los errores HTTP, porque está utilizando urllib.request.FancyURLopener y este último intento de tragar error devolviendo una urlinfo en lugar de elevar un error.

acerca de la corrección si aún desea utilizar urlretrieve puede anular FancyURLopener como esto (código incluye para mostrar también el error):

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") 

Else y esto es lo que i recomiendan puede utilizar urllib.request.urlopen como el siguiente:

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

Gracias por la ayuda. +1 y la aceptación para el parche de mono y la ayuda general, aunque desde entonces me he dado cuenta, según los comentarios anteriores, de que 'robots.txt' no permite descargar esos archivos. Me olvidé completamente de verificar eso. –

Cuestiones relacionadas