【问题标题】:Putting a `Cookie` in a `CookieJar`将 Cookie 放入 CookieJar
【发布时间】:2011-10-16 05:52:20
【问题描述】:

我正在使用新的 Python 请求库来发出 http 请求。我从服务器获取一个 cookie 作为文本。如何将其转换为带有 cookie 的 CookieJar

【问题讨论】:

  • 我看到了你的 Python 邮件列表消息,我在这里看到了你绝望的原因。
  • 我没看到。最佳答案有什么不好/令人费解的?
  • 最佳答案很棒,之前的答案让我绝望了。
  • 有了requests.Session()无需担心饼干罐。会话对象为您管理接收和发送 cookie。
  • 请参阅this answer,了解不使用Session 对象的方法。

标签: python cookies http-request python-requests


【解决方案1】:

我对这个问题感到困惑。 requests 库会为您将 cookie 放入 jar 中。

import requests
import cookielib


URL = '...whatever...'
jar = cookielib.CookieJar()
r = requests.get(URL, cookies=jar)
r = requests.get(URL, cookies=jar)

对 URL 的第一个请求将填充 jar。第二个请求会将 cookie 发送回服务器。标准库的 urllib 模块 cookielib 也是如此。 (文档目前可用于 2.x 版本)

【讨论】:

  • 刚刚发布了一个新版本 (v0.6.0),它允许您使用简单的字典将 cookie 附加到请求中。 docs.python-requests.org/en/latest/user/quickstart/#cookies
  • 这对我不起作用,所以我要求similar question 澄清。
  • 请注意,如果您使用的是requests.Session 对象,则不需要;它会完全为你处理饼干罐。
  • 只是想指出“import cookielib”仅在 2.X 下有效 - 在 3.X 中,它是“import http.cookiejar”。
  • 我无法让这段代码工作。即使将 cookie jar 传递给每个请求也不会保留我的 cookie,但是在 cmets 中列出的 requests.Session 并进一步向下运行完美。
【解决方案2】:

Session 的请求也将接收和发送 cookie。

s = requests.Session()

s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get("http://httpbin.org/cookies")

print(r.text)
# '{"cookies": {"sessioncookie": "123456789"}}'

(上面的代码从http://www.python-requests.org/en/latest/user/advanced/#session-objects窃取)

如果您希望 cookie 在代码运行之间保留在磁盘上,您可以直接使用 cookie jar 并保存/加载它们。更麻烦,但仍然很容易:

import requests
import cookielib

cookie_file = '/tmp/cookies'
cj = cookielib.LWPCookieJar(cookie_file)

# Load existing cookies (file might not yet exist)
try:
    cj.load()
except:
    pass

s = requests.Session()
s.cookies = cj

s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get("http://httpbin.org/cookies")

# Save cookies to disk, even session cookies
cj.save(ignore_discard=True)

然后查看文件:

$ cat /tmp/cookies 
#LWP-Cookies-2.0
Set-Cookie3: sessioncookie=123456789; path="/"; domain="httpbin.org"; path_spec; discard; version=0

【讨论】:

  • 我真希望这能被选上。选择的最佳答案根本不适用于 requests-2.3.0
  • 谢谢ignore_discard=True 的提示!我不明白为什么我的 jar 保存了一个空文件。
【解决方案3】:

我认为其中许多答案都没有抓住重点。有时,其他库并没有在后台使用请求。或者不公开它正在使用的 cookiejar。有时 我们所拥有的 就是 cookie 字符串。就我而言,我正在尝试从 pyVmomi 借用 auth cookie。

import requests
import http.cookies
raw_cookie_line = 'foo="a secret value"; Path=/; HttpOnly; Secure; '
simple_cookie = http.cookies.SimpleCookie(raw_cookie_line)
cookie_jar = requests.cookies.RequestsCookieJar()
cookie_jar.update(simple_cookie)

这给了我们以下cookie_jar

In [5]: cookie_jar
Out[5]: <RequestsCookieJar[Cookie(version=0, name='foo', value='a secret value', port=None, port_specified=False, domain='', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=True, expires=None, discard=False, comment='', comment_url=False, rest={'HttpOnly': True}, rfc2109=False)]>

我们可以正常使用:

requests.get(..., cookies=cookie_jar)

【讨论】:

    【解决方案4】:

    为了帮助你,我写了一个完整的模块。我用我的个人网页和 google 的 cookie 进行了尝试,所以我认为它可以工作。

    我得到了How to add cookie to existing cookielib CookieJar instance in Python?的帮助

    我在这里有很多非pythonic 代码,包括一个半杂乱无章的代码,所以你的里程可能会有所不同。根据需要调整它,特别是对于假定的项目(例如端口 80),“请求”作为下面的参数是 requests.request 类型,我意识到“方法”参数必须全部大写。希望我能帮上忙!

    注意:我没有时间添加 cmets 进行澄清,因此您必须使用源代码。

    import Cookie,cookielib,requests,datetime,time  #had this out but realized later I needed it when I continued testing
    
    def time_to_tuple(time_string):
        wday = {'Mon':0,'Tue':1,'Wed':2,'Thu':3,'Fri':4,'Sat':5,'Sun':6}
        mon = {'Jan':1,'Feb':2,'Mar':3,'Apr':4,'May':5,'Jun':6,'Jul':7,'Aug':8,'Sep':9,'Oct':10,'Nov':11,'Dec':12}
        info = time_string.split(' ')
        info = [i.strip() for i in info if type(i)==str]
        month = None
        for i in info:
            if '-' in i:
                tmp = i.split('-')
                for m in tmp:
                    try:
                        tmp2 = int(m)
                        if tmp2<31:
                            mday = tmp2
                        elif tmp2 > 2000:
                            year = tmp2
                    except:
                        for key in mon:
                            if m.lower() in key.lower():
                                month = mon[key]
            elif ':' in i:
                tmp = i.split(':')
                if len(tmp)==2:
                    hour = int(tmp[0])
                    minute = int(tmp[1])
                if len(tmp)==3:
                    hour = int(tmp[0])
                    minute = int(tmp[1])
                    second = int(tmp[2])
            else:
                for item in wday:
                    if ((i.lower() in item.lower()) or (item.lower() in i.lower())):
                        day = wday[item]
                if month is None:
                    for item in mon:
                        if ((i.lower() in item.lower()) or (item.lower() in i.lower())):
                            month = mon[item]
        return year,month,mday,hour,minute,second
    
    def timefrom(year,month,mday,hour,minute,second):
        time_now = time.gmtime()
        datetime_now = datetime.datetime(time_now.tm_year,time_now.tm_mon,
                                         time_now.tm_mday,time_now.tm_hour,
                                         time_now.tm_min,time_now.tm_sec)
        then = datetime.datetime(year,month,mday,hour,minute,second)
        return (datetime_now-then).total_seconds()
    
    def timeto(year,month,mday,hour,minute,second):
        return -1*timefrom(year,month,mday,hour,minute,second)
    
    
    
    ##['comment', 'domain', 'secure', 'expires', 'max-age', 'version', 'path', 'httponly']
    def parse_request(request):
        headers = request.headers
        cookieinfo = headers['set-cookie'].split(';')
        name = 'Undefined'
        port=80
        port_specified=True
        c = Cookie.SmartCookie(headers['set-cookie'])
        cj = cookielib.CookieJar()
        for m in c.values():
            value = m.coded_value
            domain = m['domain']
            expires = m['expires']
            if type(expires) == str:
                tmp = time_to_tuple(expires)
                expires = timeto(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5])
            max_age=m['max-age']
            version = m['version']
            if version == '':
                version = 0
            path = m['path']
            httponly = m['httponly']
            if httponly == '':
                if 'httponly' in headers['set-cookie'].lower():
                    httponly = True
            else:
                httponly = False
            secure = m['secure']
            comment=m['comment']
            port = 80
            port_specified=False
            domain_specified=True
            domain_initial_dot = domain.startswith('.')
            path_specified=True
            discard = True
            comment_url=None
            rest={'HttpOnly':httponly}
            rfc2109=False
            ck = cookielib.Cookie(version,name,value,port,port_specified,domain,
                                  domain_specified,domain_initial_dot,path,path_specified,
                                  secure,expires,discard,comment,comment_url,rest,rfc2109)
            cj.set_cookie(ck)
        return cj
    

    【讨论】:

    • 我有 name="undefined" 因为我无法找出名字在哪里。如果有人能指出在哪里,我很乐意更新代码。
    • 如果你有太多的cookie(我怀疑,考虑到cookie的功能),请随意使用yield而不是return。
    • 刚刚推送了一个新版本 (v0.6.0),它允许您使用简单的字典将 cookie 附加到请求中。 docs.python-requests.org/en/latest/user/quickstart/#cookies
    • 这些代码不都等同于现有的cookielib.CookieJar.extract_cookies(response, request) ???
    【解决方案5】:

    好吧 cookielib.LWPCookieJar 上面有加载和保存方法。查看格式并查看它是否与本机 cookie 格式匹配,您可能可以使用 StringIO 将 cookie 直接加载到 cookie jar 中。或者,如果请求在后台使用 urllib2,您不能将 cookie 处理程序添加到默认开启程序吗?

    【讨论】:

      【解决方案6】:

      我正在尝试做同样的事情。这是我到目前为止所拥有的,由于某种原因,它没有在标题中发送 cookie。不过,它可能会让您走得更远,以解决您的问题。

      import requests
      import cookielib
      import logging
      
      log = logging.getLogger(__name__)
      
      def auth(auth_url, cookies):
          cj = cookielib.CookieJar()
          for x in cookies:
               if len(cookies[x]) > 0:
                   ck = cookielib.Cookie(version=1, name=x, value=cookies[x], 
                          port=None, port_specified=False, domain='.example.com', 
                          domain_specified=True, 
                          domain_initial_dot=True, path='/', 
                          path_specified=True, secure=False, 
                          expires=None, discard=True, 
                          comment=None, comment_url=None, 
                          rest=None, rfc2109=True)
                   log.info(ck)
                   cj.set_cookie(ck)
      
          log.info("cookies = %s " % cj)
          response = requests.get(auth_url, cookies=cj)
          log.info("response %s \n" % response)
          log.info("response.headers %s \n" % response.headers)
          log.info("response.content %s \n" % response.content)
      

      【讨论】:

      【解决方案7】:

      假设您已请求 url 并且您收到了 headers 作为响应。 url 的类型类型是字符串。 headers 的类型类型是列表。

      import urllib2
      import cookielib
      
      class dummyResponse:
          def __init__(self,headers):
              self.headers=headers
          def info(self):
              return dummyInfo(self.headers)
      
      class dummyInfo:
          def __init__(self,headers):
              self.headers=headers
          def getheaders(self,key):
              #Headers are in the form: 'Set-Cookie: key=val\r\n'. We want 'key=val'
              newMatches=[]
              for header in self.headers:
                  if header.lower().startswith(key.lower()):
                      clearHeader=header[len(key)+1:].strip()
                      newMatches.append(clearHeader)
              return newMatches
      
      req=urllib2.Request(url)
      resp=dummyResponse(headers)
      
      jar=cookielib.CookieJar()
      jar.extract_cookies(resp, req)
      

      【讨论】:

        【解决方案8】:

        作为dstanek answered,请求会自动为您将响应cookie放入cookie罐中。
        但是,如果您手动指定 Cookie 标头条目,请求不会为您将这些 cookie 放入 jar 中。这意味着任何后续请求都将缺少您的初始 cookie 集,但会包含任何新的 cookie。

        如果您确实需要为请求手动创建 cookie jar,请使用 requests.cookies.RequestsCookieJar。如果他们的示例代码发生变化:

        jar = requests.cookies.RequestsCookieJar()
        jar.set('tasty_cookie', 'yum',   domain='httpbin.org', path='/cookies')
        jar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
        url = 'http://httpbin.org/cookies'
        r = requests.get(url, cookies=jar)
        

        请注意,如果您提供一个 cookie jar一个 Cookie 标头,则标头优先,但 cookie jar 仍将保留以供将来的请求使用。

        【讨论】:

          【解决方案9】:

          试试这个网站:Voidspace article

          多年来,我发现 voidspace 对于做这类事情非常有用。希望我能帮上忙,虽然我是个笨蛋。代码位于Voidspace Recipes 虽然下载文件是“.py-”文件,但作为源代码.py。

          【讨论】:

          • 对于这样一个简单的任务来说真的过于复杂了。我想我唯一能做的就是等待 requests 实现 cookie 处理。
          • 我是一名网络程序员,但我主要负责发送 cookie。我回家后会修改,因为公司互联网不允许程序化网络潜水。
          • 刚刚发布了一个新版本 (v0.6.0),它允许您使用简单的字典将 cookie 附加到请求中。 docs.python-requests.org/en/latest/user/quickstart/#cookies
          【解决方案10】:

          overthink 的答案的简化版本,关于如何在 Python3 中获取 cookiejar 和持久化 cookie:

          import requests
          
          s = requests.Session()
          
          r1 = s.get('https://stackoverflow.com')
          print("r1",r1.cookies) #Have cookie
          print("s",s.cookies)  #Have cookie(jar)
          
          r2 = s.get('https://stackoverflow.com') #The cookie from r1 is resend
          print("r2",r2.cookies) #No cookie (could be a new one)
          print("s",s.cookies)  #Keep the cookie(jar) from r1
          

          要在会话之间保留 cookie,您必须在 Session 中保存和重复使用 cookiejar(s 变量)。 如果您在其他站点上的 r1/r2/s 之间得到不同的答案,请检查是否存在重定向。例如,r1/r2 将不会获得https://www.stackoverflow.com 的 cookie,因为它被重定向到没有 www 的站点。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-06-08
            • 2011-08-23
            • 2017-06-22
            • 1970-01-01
            • 2018-03-24
            • 2015-09-25
            • 1970-01-01
            相关资源
            最近更新 更多