如何在 Python 中使用库 requests
发出请求后响应的处理
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
bot = requests.session()
bot.get('http://google.com')
将所有的cookie保存到一个文件中,然后从文件中恢复cookie。
如何在 Python 中使用库 requests
发出请求后响应的处理
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
bot = requests.session()
bot.get('http://google.com')
将所有的cookie保存到一个文件中,然后从文件中恢复cookie。
暂时没有直接的方法可以这样做,但这并不难。
你可以从会话中获取一个 CookieJar
对象,使用 session.cookies
,然后使用 pickle
将其存储到文件中。
完整示例:
import requests, pickle
session = requests.session()
# Make some calls
with open('somefile', 'wb') as f:
pickle.dump(session.cookies, f)
加载过程如下:
session = requests.session() # or an existing session
with open('somefile', 'rb') as f:
session.cookies.update(pickle.load(f))
requests
库使用requests.cookies.RequestsCookieJar()
子类,该子类明确支持pickling和类似字典的API。RequestsCookieJar.update()
方法可用于使用从pickle文件加载的cookie更新现有会话cookie jar。
在像 r = requests.get()
这样的调用之后,r.cookies
将返回一个 RequestsCookieJar
对象,你可以直接使用 pickle
来对其进行序列化。
import pickle
def save_cookies(requests_cookiejar, filename):
with open(filename, 'wb') as f:
pickle.dump(requests_cookiejar, f)
def load_cookies(filename):
with open(filename, 'rb') as f:
return pickle.load(f)
#save cookies
r = requests.get(url)
save_cookies(r.cookies, filename)
#load cookies and do a request
requests.get(url, cookies=load_cookies(filename))
如果您想将cookie以人类可读的格式保存,您需要做一些工作,将RequestsCookieJar
提取到LWPCookieJar
中。
import cookielib
def save_cookies_lwp(cookiejar, filename):
lwp_cookiejar = cookielib.LWPCookieJar()
for c in cookiejar:
args = dict(vars(c).items())
args['rest'] = args['_rest']
del args['_rest']
c = cookielib.Cookie(**args)
lwp_cookiejar.set_cookie(c)
lwp_cookiejar.save(filename, ignore_discard=True)
def load_cookies_from_lwp(filename):
lwp_cookiejar = cookielib.LWPCookieJar()
lwp_cookiejar.load(filename, ignore_discard=True)
return lwp_cookiejar
#save human-readable
r = requests.get(url)
save_cookies_lwp(r.cookies, filename)
#you can pass a LWPCookieJar directly to requests
requests.get(url, cookies=load_cookies_from_lwp(filename))
all(isinstance(c, cookielib.Cookie) for c in r.cookies)
是 True
,那么为什么在 save_cookies_lwp
中还要再次创建每个 cookie 项呢? - consatan我提供一种使用 JSON 的方法:
保存 cookie -
import json
with open('cookie.txt', 'w') as f:
json.dump(requests.utils.dict_from_cookiejar(bot.cookies), f)
并加载 cookie -
import json
session = requests.session() # or an existing session
with open('cookie.txt', 'r') as f:
cookies = requests.utils.cookiejar_from_dict(json.load(f))
session.cookies.update(cookies)
dict_from_cookiejar
函数会丢失 host 信息,因此如果存在多个不同 host 的同名 cookie 时,该函数将无法正常工作。 - MarSoft对@miracle2k的回答进行扩展,requests documented 与任何cookielib CookieJar
兼容。 LWPCookieJar
(和MozillaCookieJar
)可以将其 cookie 保存到文件中并从文件中加载。以下是一个完整的代码片段,可用于为请求会话保存和加载 cookie。 ignore_discard
参数用于与 httpbin 进行测试,但您可能不想在真正的代码中包含它。
import os
from cookielib import LWPCookieJar
import requests
s = requests.Session()
s.cookies = LWPCookieJar('cookiejar')
if not os.path.exists('cookiejar'):
# Create a new cookies file and set our Session's cookies
print('setting cookies')
s.cookies.save()
r = s.get('http://httpbin.org/cookies/set?k1=v1&k2=v2')
else:
# Load saved cookies from the file and use them in a request
print('loading saved cookies')
s.cookies.load(ignore_discard=True)
r = s.get('http://httpbin.org/cookies')
print(r.text)
# Save the session's cookies back to the file
s.cookies.save(ignore_discard=True)
我发现其他答案存在以下问题:
这个答案解决了这两个问题:
import requests.cookies
def save_cookies(session, filename):
if not os.path.isdir(os.path.dirname(filename)):
return False
with open(filename, 'w') as f:
f.truncate()
pickle.dump(session.cookies._cookies, f)
def load_cookies(session, filename):
if not os.path.isfile(filename):
return False
with open(filename) as f:
cookies = pickle.load(f)
if cookies:
jar = requests.cookies.RequestsCookieJar()
jar._cookies = cookies
session.cookies = jar
else:
return False
然后只需调用 save_cookies(session, filename)
来保存,或者调用 load_cookies(session, filename)
来加载。就是这么简单。
session.cookies = LWPCookieJar('cookies.txt')
CookieJar API需要你手动调用load()和save()方法。如果你不关心cookies.txt格式,我有一个ShelvedCookieJar实现可在变更时自动持久化。
cj = cookielib.LWPCookieJar(cookie_file)
cj.load()
session.cookies = cj
- ChaimGjar.shelf.close()
,否则结果不会被刷新到磁盘上,而且在调用jar.shelf.close()
后该存储器不能再被使用,因此管理该存储器的生命周期并不简单。 - Jason R. CoombsPython 3 代码:
请注意,网络上绝大多数的 cookies 都是 Netscape cookies。因此,如果您想将 cookies 保存到 Mozilla cookies.txt 文件格式中(该格式也被 Lynx 和 Netscape 浏览器使用),请使用 MozillaCookieJar。
from http.cookiejar import MozillaCookieJar
import requests
s = requests.Session()
s.cookies = MozillaCookieJar('cookies.txt')
# or s.cookies = MozillaCookieJar() and later use s.cookies.filename = 'cookies.txt' or pass the file name to save method.
response = s.get('https://www.msn.com')
s.cookies.save()
如果文件已经存在,写入的文件将覆盖原有内容,从而擦除其中包含的所有cookie。可以使用load()或revert()方法恢复保存的cookie。
请注意,如果没有传递ignore_discard参数并请求保存会话cookie,save()方法不会保存会话cookie。
s.cookies.save(ignore_discard=True)
使用load方法:
从文件加载cookies。
旧的cookies会被保留,除非被新加载的cookie覆盖。
s.cookies.load()
使用还原方法:
清除所有的 Cookie,并从保存的文件中重新加载 Cookie。
s.cookies.revert()
如果您使用load或revert方法,可能需要传递一个true ignore_discard参数。
关于使用MozillaCookieJar的注意事项:
注意:这会丢失有关RFC 2965 cookie以及端口等较新或非标准cookie属性的信息。
requests.update()
一样添加/更新cookie。 - user136036将Cookies转换为字典列表并保存到JSON或数据库的简单方法。
这是一个具有session
属性的类的方法。
def dump_cookies(self):
cookies = []
for c in self.session.cookies:
cookies.append({
"name": c.name,
"value": c.value,
"domain": c.domain,
"path": c.path,
"expires": c.expires
})
return cookies
def load_cookies(self, cookies):
for c in cookies:
self.session.cookies.set(**c)
名称
、值
、域名
、路径
、过期时间
。您可以直接将cookies对象进行序列化:
cookies = pickle.dumps(session.cookies)
字典表示法遗漏了很多信息:过期时间、域名、路径等等......
这取决于您打算如何使用cookies,但是如果您没有关于过期时间的信息,例如,您应该手动实现跟踪过期的逻辑。
将库返回的对象进行pickling(序列化)可以让你轻松地重构状态,然后您可以依赖于库的实现。
显然,以这种方式,pickled(序列化的)对象的使用者需要使用相同的库。
session = requests.session(cookies=cookies)
对我来说,这引发了一个异常,说session()不接受参数。
我通过使用cookie.get_dict上的键/值并手动将它们添加到会话中来解决了这个问题:
session.cookies.set(cookies.keys()[n],cookies.values()[n])
session.cookies.set(cookies.keys()[n],cookies.values()[n])
对我也起作用了,谢谢! - Javier C. H.
requests.utils.dict_from_cookiejar
和requests.utils.cookiejar_from_dict
不是必需的。它们无法保存不同域名下相同名称的cookies,也无法保存所有必需的cookie数据。由于这些问题,我曾经花费了很长时间进行调试。 - Elmodict_from_cookiejar
函数没有保存主机信息。实际上,在当前版本中,session.cookies
可以直接进行pickle和unpickle,无需转换为dict
。 此外,requests.utils.dict_from_cookiejar
可以替换为session.cookies.get_dict()
,cookiejar_from_dict
可以替换为session.cookies.update(my_dict)
。 - MarSoftopen() as f
之后应该有一个f.close()
。否则,两个连续的open()
将会引发 "TypeError: can't pickle _thread.RLock objects"。 - Weekendwith
语句时,您不需要显式调用f.close()
。_上下文管理器_会为您隐式调用f.close()
。请参见https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files答案中的两个单独的`with`语句未嵌套。 - GordonAitchJay