2012-07-17 14 views
7

Estoy escribiendo un analizador Google Scholar, y basado en this answer, estoy configurando cookies antes de tomar el HTML. Este es el contenido de mi cookies.txt archivo:¿Por qué Python dice que este archivo de cookies de Netscape no es válido?

# Netscape HTTP Cookie File 
# http://curlm.haxx.se/rfc/cookie_spec.html 
# This file was generated by libcurl! Edit at your own risk. 

.scholar.google.com  TRUE /  FALSE 2147483647  GSP  ID=353e8f974d766dcd:CF=2 
.google.com  TRUE /  FALSE 1317124758  PREF ID=353e8f974d766dcd:TM=1254052758:LM=1254052758:S=_biVh02e4scrJT1H 
.scholar.google.co.uk TRUE /  FALSE 2147483647  GSP  ID=f3f18b3b5a7c2647:CF=2 
.google.co.uk TRUE /  FALSE 1317125123  PREF ID=f3f18b3b5a7c2647:TM=1254053123:LM=1254053123:S=UqjRcTObh7_sARkN 

y este es el código que estoy usando para agarrar el código HTML:

import http.cookiejar 
import urllib.request, urllib.parse, urllib.error 

def get_page(url, headers="", params=""): 
    filename = "cookies.txt" 
    request = urllib.request.Request(url, None, headers, params) 
    cookies = http.cookiejar.MozillaCookieJar(filename, None, None) 
    cookies.load() 
    cookie_handler = urllib.request.HTTPCookieProcessor(cookies) 
    redirect_handler = urllib.request.HTTPRedirectHandler() 
    opener = urllib.request.build_opener(redirect_handler,cookie_handler) 
    response = opener.open(request) 
    return response 

start = 0 
search = "Ricardo Altamirano" 
results_per_fetch = 20 
host = "http://scholar.google.com" 
base_url = "/scholar" 
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; U; ru; rv:5.0.1.6) Gecko/20110501 Firefox/5.0.1 Firefox/5.0.1'} 
params = urllib.parse.urlencode({'start' : start, 
           'q': '"' + search + '"', 
           'btnG' : "", 
           'hl' : 'en', 
           'num': results_per_fetch, 
           'as_sdt' : '1,14'}) 

url = base_url + "?" + params 
resp = get_page(host + url, headers, params) 

El rastreo completo es:

Traceback (most recent call last): 
    File "C:/Users/ricardo/Desktop/Google-Scholar/BibTex/test.py", line 29, in <module> 
    resp = get_page(host + url, headers, params) 
    File "C:/Users/ricardo/Desktop/Google-Scholar/BibTex/test.py", line 8, in get_page 
    cookies.load() 
    File "C:\Python32\lib\http\cookiejar.py", line 1767, in load 
    self._really_load(f, filename, ignore_discard, ignore_expires) 
    File "C:\Python32\lib\http\cookiejar.py", line 1997, in _really_load 
    filename) 
http.cookiejar.LoadError: 'cookies.txt' does not look like a Netscape format cookies file 

I He buscado documentación en el formato de archivo de cookies de Netscape, pero no encuentro nada que me muestre el problema. ¿Hay nuevas líneas que deben incluirse? Cambié los finales de línea al estilo Unix, por las dudas, pero eso no resolvió el problema. La especificación más cercana que puedo encontrar es this, que no me indica nada que me falta. Los campos en cada una de las últimas cuatro líneas están separados por pestañas, no espacios, y todo lo demás me parece correcto.

+0

[especificación de cookies de Netscape] (http://curl.haxx.se/rfc/cookie_spec.html) que solía alojarse en netscape.com antes de que alguien (AOL?) Arruinara la historia. – n611x007

+0

una especificación actualizada como [rfc2965] (http://tools.ietf.org/html/rfc2965.html) con * Set-Cookie2 * – n611x007

+0

Para cualquier persona interesada, en realidad puede hacer 'cookies.save (cookie_file, ignore_discard = True , ignore_expires = True) 'para crear un archivo de cookie válido como instancia para comparar con cookies.txt no válido. Línea por línea o bye por byte para comparar, y eliminar la línea uno por uno, finalmente encontraría la razón. –

Respuesta

10

No veo nada en su código de ejemplo o copia del archivo cookies.txt que es obviamente incorrecto.

He comprobado el código fuente del MozillaCookieJar._really_load method, que arroja la excepción que ves.

Lo primero que hace este método es leer la primera línea del archivo que especificó (usando f.readline()) y usar re.search para buscar el patrón de expresión regular "#(Netscape)? HTTP Cookie File". Esto es lo que falla para su archivo.

Ciertamente parece como su cookies.txt coincidiría con ese formato, por lo que el error que ve es bastante sorprendente.

Tenga en cuenta que su archivo se abre con un simple open(filename) call anteriormente, por lo que se abrirá en modo texto con soporte de finalización de línea universal, lo que significa que no importa que esté ejecutando esto en Windows. El código verá \n cadenas terminadas en nueva línea, independientemente de qué convención de nueva línea se usó en el archivo.

Lo que haría en este caso es triple-check que la primera línea de su archivo es realmente correcta. Necesita contener "Archivo de cookies HTTP #" o "Archivo de cookies HTTP # Netscape" (solo espacios, sin pestañas, entre las palabras, coincidencia de mayúsculas). Probar esto con el símbolo del pitón:

>>> f = open('cookies.txt') 
>>> line = f.readline() 
>>> line 
'# Netscape HTTP Cookie File\n' 
>>> import re 
>>> re.search("#(Netscape)? HTTP Cookie File", line) 
<_sre.SRE_Match object at 0x10fecfdc8> 

Python se hizo eco de la representación en línea de nuevo a mí cuando he escrito line en el indicador, incluyendo el carácter de nueva línea \n. Las sorpresas como los tabuladores o los espacios de ancho cero Unicode aparecerán allí como códigos de escape. También verifiqué que la expresión regular utilizada por el código cookiejar coincide.

También puede utilizar el pdb python debugger para verificar lo que el módulo de http.cookiejar realmente:

>>> import pdb 
>>> import http.cookiejar 
>>> jar = http.cookiejar.MozillaCookieJar('cookies.txt') 
>>> pdb.run('jar.load()') 
> <string>(1)<module>() 
(Pdb) s 
--Call-- 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1759)load() 
-> def load(self, filename=None, ignore_discard=False, ignore_expires=False): 
(Pdb) s 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1761)load() 
-> if filename is None: 
(Pdb) s 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1762)load() 
-> if self.filename is not None: filename = self.filename 
(Pdb) s 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1765)load() 
-> f = open(filename) 
(Pdb) n 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1766)load() 
-> try: 
(Pdb) 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1767)load() 
-> self._really_load(f, filename, ignore_discard, ignore_expires) 
(Pdb) s 
--Call-- 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1989)_really_load() 
-> def _really_load(self, f, filename, ignore_discard, ignore_expires): 
(Pdb) s 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1990)_really_load() 
-> now = time.time() 
(Pdb) n 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1992)_really_load() 
-> magic = f.readline() 
(Pdb) 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1993)_really_load() 
-> if not self.magic_re.search(magic): 
(Pdb) 
> /opt/local/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/http/cookiejar.py(1999)_really_load() 
-> try: 

En la sesión de muestra pdb arriba he utilizado una combinación de los comandos step y next para verificar que la prueba de expresión regular (self.magic_re.search(magic)) en realidad pasó.

+0

¡Excelente respuesta! (y un buen ejemplo de depuración de python también). No sé si algo más ha cambiado en mi sistema, pero el código funciona en este momento sin alteraciones en 'cookies.txt' La primera línea del archivo era idéntica a la suya, incluyendo espacios, pestañas, etc. No estoy seguro de qué problema estaba desatando el problema. –

+0

@RicardoAltamirano solo una conjetura: un cambio de codificación de texto, por ej. la lista de materiales líder como el utf-8 no oficial '\ xef \ xbb \ xbf' podría causar tal efecto y puede no ser muy obvio ya que solo los contenidos binarios han cambiado, pero como texto puede parecer lo mismo. La misma idea podría cambiar en el código si anteriormente usaste 'abrir' y luego' codecs.open'. – n611x007

+0

@naxa: la sesión 'open()' y 'f.readline()' que muestro en mi respuesta (en Python 2) mostraría fácilmente tales puntos de código. IIRC una BOM UTF-8 seguiría siendo parte del valor Unicode devuelto por un objeto de archivo 'codecs.open()' o 'io.open()', y los literales de cadena Unicode reveladores 'u'' serían una obviedad En todo caso. –

2

A partir de mi escenario, dos modificaciones son necesarias para la MozillaCookieJar bajo (/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/)

  1. La cabecera de la magia

    puede eliminar la lógica de verificación o añadir esa cabecera magia que yo prefiero

    '# Netscape HTTP archivo cookie

  2. El nuevo formato de archivo parece le permiten omite el expira

    vals = line.split("\t") 
    if len(vals) == 7 : 
        domain, domain_specified, path, secure, expires, name, value = vals 
    if len(vals) == 6 : 
        domain, domain_specified, path, secure, name, value = vals 
        expires = None 
    

Por último Realmente espero que la aplicación podría ser actualizado con los nuevos cambios.

Cuestiones relacionadas