为什么Python说这个Netscape cookie文件无效?

时间:2012-07-17 19:24:32

标签: python cookies

我正在编写Google Scholar解析器,基于this answer,我在抓取HTML之前设置了Cookie。这是我的cookies.txt文件的内容:

# 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

这是我用来抓取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)

完整的追溯是:

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

我一直在寻找有关Netscape cookie文件格式的文档,但我找不到任何能告诉我问题的内容。是否需要包含新行?为了以防万一,我将行结尾更改为Unix样式,但这并没有解决问题。我能找到的最接近的规格是this,这并不表示我缺少任何东西。最后四行中每一行的字段由制表符分隔,而不是空格,其他所有内容对我来说都是正确的。

3 个答案:

答案 0 :(得分:10)

我在您的示例代码或cookies.txt文件的副本中看不到任何明显错误的内容。

我已经检查了MozillaCookieJar._really_load method的源代码,它会抛出您看到的异常。

此方法的第一件事是读取您指定的文件的第一行(使用f.readline())并使用re.search查找正则表达式模式"#( Netscape)? HTTP Cookie File"。这是您的文件失败。

肯定看起来就像你的cookies.txt会匹配那种格式一样,所以你看到的错误是非常令人惊讶的。

请注意,您的文件之前使用简单的open(filename) call打开,因此它将以文本模式打开并支持通用行结束,这意味着您在Windows上运行此文件无关紧要。无论文件本身使用了什么新行约定,代码都会看到\n换行终止字符串。

在这种情况下,我要做的是三重检查,你的文件的第一行是非常正确的。它需要包含“#HTTP Cookie文件”或“#Netscape HTTP Cookie文件”(仅限空格,单词之间没有选项卡,大小写匹配)。使用python提示符测试:

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

当我在提示符下输入line时,Python回显了我的行表示,包括\n换行符。任何惊喜,如制表符或unicode零宽度空格都会显示为转义码。我还验证了cookiejar代码使用的正则表达式匹配。

您还可以使用pdb python debugger来验证http.cookiejar模块的确实作用:

>>> 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:

在上面的示例pdb会话中,我使用stepnext命令的组合来验证正则表达式测试(self.magic_re.search(magic))是否实际通过。

答案 1 :(得分:2)

根据我的情况,MozillaCookieJar需要进行两项修改(/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7 /)

  1. 神奇的标题

    您可以删除检查逻辑或添加我喜欢的魔术标题

      

    '#Netscape HTTP Cookie文件

  2. 新文件格式似乎允许您省略过期

    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
    
  3. 最后,我真的希望可以将实施更新为新的更改。

答案 2 :(得分:1)

请在您的开发控制台中

copy('# Netscape HTTP Cookie File\n' + document.cookie.split(/; /g).map(e => e.replace('=', '\t')).map(e => window.location.hostname.replace('www.', '.') + '\tTRUE\t/\tFALSE\t-1\t' + e).join('\n'))

Netscape格式的cookie将在您系统的剪贴板中:)