2012-07-17 31 views
7

我正在編寫一個Google Scholar解析器,並且基於this answer,我在抓取HTML之前設置了Cookie。這是我cookies.txt文件的內容:爲什麼Python說這個Netscape cookie文件無效?

# 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,這並不表示我失蹤。最後四行中每一行的字段都由製表符分隔,而不是空格,而其他所有內容對我來說都是正確的。

+0

[netscape cookie規範](http://curl.haxx.se/rfc/cookie_spec.html)曾經在某人(AOL?)破壞歷史之前被netscape.com託管。 – n611x007 2013-11-03 18:28:51

+0

更新規格爲[rfc2965](http://tools.ietf.org/html/rfc2965.html)* Set-Cookie2 * – n611x007 2013-11-03 18:31:33

+0

對於任何有興趣的人,實際上你可以做'cookies.save(cookie_file,ignore_discard = True ,ignore_expires = True)'創建一個有效的cookie文件作爲實例,與無效的cookies.txt進行比較。逐行或逐字節比較,並逐一刪除該行,最終找到原因。 – 2014-02-21 10:24:59

回答

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文件」(僅限空格,單詞之間沒有大寫字母匹配)。與蟒蛇提示測試:

>>> 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的呼應行表示回到我身邊時,我在提示符下鍵入line,包括\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: 

在我使用的stepnext命令的組合來驗證上述樣品PDB會話正則表達式測試( self.magic_re.search(magic))實際通過。

+0

優秀的答案! (以及一個很好的調試python的例子)。我不知道在我的系統中是否有其他內容已經改變,但是代碼在沒有任何改動的情況下運行。'cookies.txt'文件的第一行與你的相同,包括空格,製表符等,所以我我不確定是什麼問題引發了這個問題。 – 2012-07-20 13:12:22

+0

@RicardoAltamirano只是一個猜測:文本編碼的變化,例如。像非官方的utf-8'\ xef \ xbb \ xbf'這樣的主導BOM可能會導致這樣的效果,並且可能不是很明顯,因爲只有二進制內容已經改變,但作爲文本可能看起來相同。如果您之前使用過'open'和後面的'codecs.open',則代碼中的相同想法可能會發生變化。 – n611x007 2013-11-03 14:31:16

+0

@naxa:我在答案中顯示的'open()'和'f.readline()'會話(在Python 2中)很容易顯示任何這樣的代碼點。 IIRC UTF-8 BOM仍然是從'codecs.open()'或'io.open()'文件對象返回的Unicode值的一部分,並且指示'u'' Unicode字符串文字將是一個死的贈品任何狀況之下。 – 2013-11-03 16:07:27

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 
    

最後,我真的希望實現可能被更新到新的變化。