web-dev-qa-db-fra.com

Mettre un `Cookie` dans un` CookieJar`

J'utilise la nouvelle bibliothèque Python Requests pour effectuer des requêtes http. J'obtiens un cookie du serveur sous forme de texte. Comment transformer cela en une CookieJar avec le cookie?

36
Ram Rachum

Je suis confus par cette question. La bibliothèque de demandes mettra les cookies dans le pot pour vous.

import requests
import cookielib


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

La première demande à l'URL remplira le fichier. La deuxième demande renverra les cookies au serveur. Il en va de même pour le module urllib de la bibliothèque standard cookielib . (doc actuellement disponible pour la version 2.x)

44
dstanek

Une demande Session recevra et enverra également des cookies.

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"}}'

(Code ci-dessus volé à http://www.python-requests.org/en/latest/user/advanced/#session-objects )

Si vous souhaitez que les cookies persistent sur le disque entre les exécutions de votre code, vous pouvez directement utiliser un fichier jar de cookie et les enregistrer/charger. Plus lourd, mais toujours assez facile:

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)

Puis regardez dans le fichier:

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

Pour vous aider, j'ai écrit un module entier. Je l'ai essayé avec ma page Web personnelle et les cookies de Google. Je suppose donc que cela fonctionne.

J'ai obtenu de l'aide de Comment ajouter un cookie à une instance cookielib CookieJar existante en Python?

J'ai beaucoup de code non polythonique ici, y compris un semi-kludge, donc votre kilométrage peut varier. Ajustez-le à votre guise, en particulier avec les éléments supposés (tels que le port 80), la "requête" en tant qu'argument ci-dessous est du type requests.request et je me suis rendu compte que l'argument "méthode" devait être en majuscules. J'espère pouvoir aider!

Note: Je n'ai pas eu le temps d'ajouter des commentaires pour des éclaircissements, vous devrez donc utiliser la source.

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
4
Snakes and Coffee

Cookielib.LWPCookieJar contient des méthodes de chargement et de sauvegarde. Regardez le format et voyez s'il correspond au format de cookie natif, vous pourrez peut-être charger votre cookie directement dans un fichier jar à l'aide de StringIO. Sinon, si les demandes utilisent urllib2 sous le capot, ne pouvez-vous pas ajouter un gestionnaire de cookies à l'ouvre-porte par défaut?

3
fuzzyman

J'essaie de faire la même chose. C’est ce que j’ai fait jusqu’à présent et, pour une raison quelconque, les cookies ne sont pas envoyés dans l’entête. Cependant, cela pourrait vous amener assez loin pour résoudre votre problème.

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)
2
Ken Cochrane

Je pense que beaucoup de ces réponses manquent le point. Parfois, cette autre bibliothèque n'utilise pas les requêtes sous le capot. Ou n'expose pas le cookiejar qu'il utilise. Parfois tout ce que nous avons est la chaîne de cookie. Dans mon cas, j'essaie d'emprunter le cookie d'authentification de pyVmomi.

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)

Ce qui nous donne le cookie_jar suivant:

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

Que nous pouvons utiliser comme d'habitude:

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

Essayez ce site: Article sur l'espace vide

Au fil des années, j'ai trouvé l'espace vide extrêmement utile pour ce type de travail. J'espère que j'ai aidé, bien que je sois un cancre. Le code est disponible sur Recettes de l'espace vide En tant que code source .py bien que le fichier de téléchargement soit un fichier ".py-".

1
Snakes and Coffee

En supposant que vous avez demandé url et que vous ayez headers comme réponse. Le type de type url est une chaîne. Le type type de headers est list.

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)
1
Utku Zihnioglu

Lorsque dstanek a répondu , les demandes placent automatiquement les cookies de réponse dans un pot de cookies pour vous.
Cependant, si vous spécifiez manuellement une entrée d'en-tête Cookie, les requêtes ne le seront pas mettent ces cookies dans un fichier jar pour vous. Cela signifie que toutes les demandes ultérieures manqueront de votre jeu initial de cookies, mais que de nouveaux cookies seront envoyés.

Si vous devez créer manuellement un cookie pour les demandes, utilisez requests.cookies.RequestsCookieJar . Dans le cas où leur exemple de code change:

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)

Notez que si vous fournissez un cookie et un en-tête Cookie, l'en-tête est prioritaire, mais le cookie sera toujours conservé pour les demandes futures.

0
Mr. Llama