使用cookies.txt文件与Python Requests库

26

我正在尝试使用 Python Requests 访问一个需要身份验证的网站,并使用一个由 Chrome 扩展生成的 cookies.txt 文件:

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文件适用于它)。


我使用这个扩展程序:https://chrome.google.com/webstore/detail/cookietxt-export/lopabhfecdfhgogdbojmaicoicjekelh?hl=en - cjauvin
5个回答

18

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放入上面的罐子中,但由于它们在expires属性中仍然具有0值,所以随后被cookielib 丢弃。为了防止这种情况发生,我们必须将过期时间设置为未来的某个时间,如下所示:

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列中用空字符串替换0并传递ignore_discard=Trueload()是解决问题的另一种替代方法(在这种情况下不需要更改过期时间)。


1
@cjauvin请不要再随意给出没有任何警告的虚构代码。 - Piotr Dobrogost
那你具体是什么意思?我给了什么“虚构的代码”而没有警告? - cjauvin
@cjauvin,以下两行代码:cj = cookielib.MozillaCookieJar('cookies.txt') r = requests.get(url, cookies=cj)并没有调用.load()方法,而你的代码中在这两行之间确实有这个方法的调用。因此,这不是你真正的代码,而是一个虚构的代码。 - Piotr Dobrogost
谢谢更新!我充满希望,因为你是对的:ignore_expires参数确实有所不同,但不幸的是结果仍然相同:无法登录。我在想是否有一种方法可以比较wget和我的脚本所做的事情(即确切的HTTP事务)? - cjauvin
没错,它(指代码)能够工作(使用你第二次编辑中的技巧):太好了!由于这是对我的实际问题的恰当答案(与我刚刚发布的不同),我当然接受它作为答案。非常感谢Piotr! - cjauvin
显示剩余3条评论

10

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


救了我的一天...如果你的文本文件像我一样有一些空行,请确保使用try和except块。我会自己发布答案。 - PanDe

4
这对我有用:
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]>

2

我试图编辑Tristan的答案并添加一些信息,但似乎SO编辑队列已满,因此,我写下了这个答案,因为我曾经非常困扰于如何使用Python请求现有的cookies。

  1. 首先,从Chrome获取cookies。最简单的方法是使用一个名为“cookies.txt”的扩展程序。
https://chrome.google.com/webstore/detail/get-cookiestxt/bgaddhkoddajcdgocldbbfleckgcbcid/related

下载这些cookie后,请使用以下代码来确保您能够无误地解析文件。
import re, requests, pprint
    
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 = re.findall(r'[^\s]+', line) #capturing anything but empty space
                try:
                    cookies[lineFields[5]] = lineFields[6]
                except Exception as e:
                    print (e)
          
    return cookies
    
cookies = parseCookieFile('cookies.txt') #replace the filename
pprint.pprint(cookies)

接下来,使用Python Request库与这些cookie进行交互。
x = requests.get('your__url', verify=False, cookies=cookies)
print (x.content)

这应该能帮助你避免去不同的SO帖子上尝试那些对我从未起作用的cookielib和其他方法,节省你的时间。

0
我终于找到了一种方法让它工作了(我是通过查看 curl 的详细输出得到的灵感):不需要从文件中加载我的 cookies,我只需创建一个包含所需value/name对的字典即可:
cd = {'v1': 'n1', 'v2': 'n2'}
r = requests.get(url, cookies=cd)

它起作用了(尽管它没有解释为什么之前的方法不起作用)。感谢所有的帮助,真的很感激。


2
我很高兴你没有问你本来想问的问题 - “如何使用Requests|urllib2|Python发送cookies?”因为a)这个问题已经被问过并得到了答案,b)我们有机会学习新东西。 :) - Piotr Dobrogost

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接