在Python Requests中使用cookies.txt文件
我正在尝试用一个 cookies.txt
文件(这个文件是用Chrome扩展生成的)来访问一个需要登录的网站,使用的是Python的Requests库:
import requests, cookielib
cj = cookielib.MozillaCookieJar('cookies.txt')
cj.load()
r = requests.get(url, cookies=cj)
虽然没有报错或异常,但我却看到的是登录界面,这显然是不对的。不过我知道我的cookie文件是有效的,因为我用 wget
命令成功获取到了内容。你们觉得我哪里做错了呢?
补充:
我在追踪 cookielib.MozillaCookieJar._really_load
,可以确认这些cookie被正确解析(也就是说,它们的 domain
、path
、secure
等值都是对的)。但是因为最后还是显示登录表单,看来 wget
可能做了其他一些事情(因为同样的 cookies.txt
文件在它那边是可以用的)。
5 个回答
这个对我有效:
from http.cookiejar import MozillaCookieJar
from pathlib import Path
import requests
cookies = Path('/Users/name/cookies.txt')
jar = MozillaCookieJar(cookies)
jar.load()
requests.get('https://path.to.site.com', cookies=jar)
<Response [200]>
我试着考虑了Piotr Dobrogost勇敢研究的关于MozillaCookieJar
的所有内容,但还是没能解决问题。最后我受够了,干脆自己解析了那个该死的cookies.txt
文件,现在一切都好了:
import re
import requests
def parseCookieFile(cookiefile):
"""Parse a cookies.txt file and return a dictionary of key value pairs
compatible with requests."""
cookies = {}
with open (cookiefile, 'r') as fp:
for line in fp:
if not re.match(r'^\#', line):
lineFields = line.strip().split('\t')
cookies[lineFields[5]] = lineFields[6]
return cookies
cookies = parseCookieFile('cookies.txt')
import pprint
pprint.pprint(cookies)
r = requests.get('https://example.com', cookies=cookies)
MozillaCookieJar
是从 FileCookieJar
继承而来的,后者在构造函数中有以下说明:
Cookies are NOT loaded from the named file until either the .load() or
.revert() method is called.
你需要调用 .load()
方法。
另外,正如 Jermaine Xu 提到的,文件的第一行需要包含 # Netscape HTTP Cookie File
或 # HTTP Cookie File
这样的字符串。你使用的插件生成的文件并不包含这样的字符串,所以你需要自己添加。我在这里提交了一个相关的bug:http://code.google.com/p/cookie-txt-export/issues/detail?id=5
编辑
会话cookie在第五列用0来表示。如果你在调用 load()
方法时没有传入 ignore_expires=True
,那么所有这样的cookie在从文件加载时都会被丢弃。
文件 session_cookie.txt
:
# Netscape HTTP Cookie File
.domain.com TRUE / FALSE 0 name value
Python脚本:
import cookielib
cj = cookielib.MozillaCookieJar('session_cookie.txt')
cj.load()
print len(cj)
输出:
0
编辑 2
虽然我们成功地将cookie放入了上面的jar中,但它们随后会被 cookielib
丢弃,因为它们在 expires
属性中仍然是 0
。为了防止这种情况,我们需要 设置 过期时间为将来的某个时间,像这样:
for cookie in cj:
# set cookie expire date to 14 days from now
cookie.expires = time.time() + 14 * 24 * 3600
编辑 3
我检查了 wget 和 curl,它们都使用 0
作为过期时间来表示会话cookie,这意味着这是一个事实上的标准。然而,Python 的实现使用空字符串来达到同样的目的,因此在这个问题中出现了困扰。我认为 Python 在这方面的行为应该与 wget 和 curl 保持一致,这就是我在这里提交bug的原因:http://bugs.python.org/issue17164
我想补充的是,将输入文件第五列中的 0
替换为空字符串,并在调用 load()
时传入 ignore_discard=True
是解决这个问题的另一种方法(在这种情况下不需要更改过期时间)。