Cookies немного сложнее, чем просто пары ключ-значение. Браузеры также должны отслеживать, для каких URL-адресов действуют cookie-файлы (с помощью правил об именах хостов, номерах портов, путях URL-адресов и о том, будет ли соединение зашифровано) и как долго их хранить (срок действия которых истек). Некоторые файлы cookie предназначены для истечения срока действия, когда вы закрываете браузер, и поэтому срок их действия не установлен.
Однако вы не храните всю эту информацию в базе данных. Вы только сохранили ключи и значения, и когда вы затем добавляете куки в новый requests.Session()
cookiejar, эти куки помечаются как универсальные и постоянные . Файлы cookie будут отправлены на все URL-адреса, срок их действия не истечет, и они никогда не будут удалены по любой причине. Этот тип куки иногда называют supercookie . Но сервер по-прежнему также устанавливает обычные файлы cookie с полной информацией о сроке действия и сроке действия URL, и из-за этих настроек они являются различными файлами cookie .
Вы можете подтвердить это, перебирая объекты cookie в вашем образце httpbin.org
код:
>>> from requests import Session
>>> sess = Session()
>>> sess.cookies.update({"sessioncookie": "1234567890"})
>>> __ = sess.get("https://httpbin.org/cookies/set/sessioncookie/0987654321")
>>> for cookie in sess.cookies: print(cookie)
...
<Cookie sessioncookie=1234567890 for />
<Cookie sessioncookie=0987654321 for httpbin.org/>
Здесь есть два отдельных файла cookie: один для /
(все пути, все домены) и один только для httpbin.org
. Оба будут отправлены.
Вам необходимо сохранить гораздо больше информации в базе данных, чтобы воссоздать «нормальные» куки. Если вам не нужно читаемое хранилище, то библиотека requests
явно делает cookiejar маринованным:
import pickle
cookiedata = pickle.dumps(session.cookies, pickle.HIGHEST_PROTOCOL)
Это двоичные данные, сохраняйте их как таковые. Вы можете восстановить ваши куки с помощью:
session.cookies.update(pickle.loads(cookiedata))
В противном случае, если вам нужен JSON, вам придется хранить все атрибуты Cookie
:
cookie_attrs = [
"version", "name", "value", "port", "domain", "path", "secure",
"expires", "discard", "comment", "comment_url", "rfc2109"
]
cookiedata = json.dumps([
{attr: getattr(cookie, attr) for attr in cookie_attrs}
for cookie in session.cookies
])
и восстановление из JSON с помощью
for entry in json.loads(cookiedata):
session.cookies.set(**entry)
С технической точки зрения, есть также атрибут _rest
, который отслеживает атрибут HttpOnly
файлов cookie (во вложенном словаре), но этот атрибут в противном случае не игнорируется requests
, поскольку он применяется только к браузерам, в которых файлы cookie с этот атрибут, установленный на True
, недоступен из JavaScript.
В принципе, атрибуты domain
, path
, name
делают cookie уникальным , но если сервер устанавливает, скажем, cookie с определенным значением port
, и вы Сериализовал этот файл cookie и восстановил его позже, теперь этот файл cookie будет отправляться независимо от порта, используемого для целевого URL-адреса (при прочих равных условиях), и это может фактически привести к поломке, если сайт решит, что просмотр такого файла cookie в другом месте был вопрос.