【问题标题】:Using cookies.txt file with Python Requests将 cookies.txt 文件与 Python 请求一起使用
【发布时间】:2013-01-22 11:13:13
【问题描述】:

我正在尝试使用带有 Python 请求的 cookies.txt 文件(使用 Chrome 扩展程序生成)访问经过身份验证的站点:

import requests, cookielib

cj = cookielib.MozillaCookieJar('cookies.txt')
cj.load()
r = requests.get(url, cookies=cj)

它不会抛出任何错误或异常,但会错误地产生登录屏幕。但是,我知道我的 cookie 文件是有效的,因为我可以使用 wget 成功检索我的内容。知道我做错了什么吗?

编辑:

我正在跟踪 cookielib.MozillaCookieJar._really_load 并且可以验证 cookie 是否已正确解析(即它们具有正确的 domainpathsecure 等令牌值)。但由于事务仍在生成登录表单,看来wget 必须做一些额外的事情(因为完全相同的cookies.txt 文件适用于它)。

【问题讨论】:

标签: python cookies python-requests cookielib


【解决方案1】:

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 字符串。您使用的插件生成的文件不包含这样的字符串,因此您必须自己插入。我在http://code.google.com/p/cookie-txt-export/issues/detail?id=5提出了适当的错误

编辑

会话 cookie 在第 5 列中保存为 0。如果您不将 ignore_expires=True 传递给 load() 方法,则从文件加载时所有此类 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 中,但它们随后是 discarded by cookielib,因为它们在 expires 属性中仍然具有 0 值。为了防止这种情况,我们必须将过期时间set 设置为未来某个时间,如下所示:

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 所做的一致,这就是我在 http://bugs.python.org/issue17164
提出错误的原因 我会注意到,在输入文件的第 5 列用空字符串替换 0s 并将 ignore_discard=True 传递给 load() 是解决问题的替代方法(在这种情况下无需更改到期时间)。

【讨论】:

  • 是的,我正在调用load,并且我已将正确的标题添加到文件顶部,但它仍然无法正常工作(我也尝试使用urllib2 而不是requests )。这完全是个谜。
  • @cjauvin 请永远不要在没有任何警告的情况下放弃编造的代码。
  • 你到底是什么意思?我在没有警告的情况下给出了什么“编造的代码”?
  • @cjauvin 以下两行; cj = cookielib.MozillaCookieJar('cookies.txt') r = requests.get(url, cookies=cj) 不包含对 .load() 方法的调用,您的代码中确实在这两行之间的某个位置。因此,这不是您拥有的真实代码,而是编造的。
  • 感谢您的更新!我充满希望,因为你是对的:ignore_expires 参数确实有所作为,但不幸的是它仍然是相同的结果:无法登录。我想知道是否有一种方法可以比较 wget 所做的与我的脚本所做的(即在确切的 HTTP 事务方面)?
【解决方案2】:

我尝试考虑 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)

【讨论】:

    【解决方案3】:

    这对我有用:

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

    【讨论】:

      【解决方案4】:

      我终于找到了让它工作的方法(我通过查看 curl 的详细输出得到了这个想法):我没有从文件中加载我的 cookie,而是简单地创建了一个带有所需 @987654323 的 dict @对:

      cd = {'v1': 'n1', 'v2': 'n2'}
      r = requests.get(url, cookies=cd)
      

      并且它起作用了(尽管它没有解释为什么以前的方法没有)。感谢大家的帮助,真的很感激。

      【讨论】:

      • 我很高兴你没有问你想要问的问题 - “如何使用 Requests|urllib2|Python 发送 cookie?”因为a)这已经被问及回答了,b)我们有机会学习新的东西。 :)
      猜你喜欢
      • 2016-05-09
      • 1970-01-01
      • 2016-09-01
      • 1970-01-01
      • 2021-01-11
      • 2023-03-23
      • 1970-01-01
      • 2019-06-15
      相关资源
      最近更新 更多