一、会话对象  

  会话对象让你能够跨请求保持某些参数。它也会在同一个 Session 实例发出的所有请求之间保持 cookie, 期间使用 urllib3 的 connection pooling 功能。所以如果你向同一主机发送多个请求,底层的 TCP 连接将会被重用,从而带来显著的性能提升。 (参见 HTTP persistent connection).会话对象具有主要的 Requests API 的所有方法。我们来跨请求保持一些 cookie:

  1. s = requests.Session()
  2.  
  3. s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
  4. r = s.get("http://httpbin.org/cookies")
  5.  
  6. print(r.text)
  7. # '{"cookies": {"sessioncookie": "123456789"}}'

  会话也可用来为请求方法提供缺省数据。这是通过为会话对象的属性提供数据来实现的:

  1. s = requests.Session()
  2. s.auth = ('user', 'pass')
  3. s.headers.update({'x-test': 'true'})
  4.  
  5. # both 'x-test' and 'x-test2' are sent # “x-test”和“x-test2”都已发送
  1. s.get('http://httpbin.org/headers', headers={'x-test2': 'true'})

  任何你传递给请求方法的字典都会与已设置会话层数据合并。方法层的参数覆盖会话的参数。

  不过需要注意,就算使用了会话,方法级别的参数也不会被跨请求保持。下面的例子只会和第一个请求发送 cookie ,而非第二个:

  1. s = requests.Session()
  2.  
  3. r = s.get('http://httpbin.org/cookies', cookies={'from-my': 'browser'})
  4. print(r.text)
  5. # '{"cookies": {"from-my": "browser"}}'
  6.  
  7. r = s.get('http://httpbin.org/cookies')
  8. print(r.text)
  9. # '{"cookies": {}}'

  如果你要手动为会话添加 cookie,就使用 Cookie utility 函数 来操纵 Session.cookies。会话还可以用作前后文管理器:

  1. with requests.Session() as s:
  2. s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')

  这样就能确保 with 区块退出后会话能被关闭,即使发生了异常也一样。  

  从字典参数中移除一个值,有时你会想省略字典参数中一些会话层的键。要做到这一点,你只需简单地在方法层参数中将那个键的值设置为 None ,那个键就会被自动省略掉。

  包含在一个会话中的所有数据你都可以直接使用。学习更多细节请阅读 会话 API 文档

二、请求与响应对象

  任何时候进行了类似 requests.get() 的调用,你都在做两件主要的事情。其一,你在构建一个 Request 对象, 该对象将被发送到某个服务器请求或查询一些资源。其二,一旦 requests 得到一个从服务器返回的响应就会产生一个 Response 对象。该响应对象包含服务器返回的所有信息,也包含你原来创建的 Request 对象。如下是一个简单的请求,从 Wikipedia 的服务器得到一些非常重要的信息:

  1. >>> r = requests.get('http://en.wikipedia.org/wiki/Monty_Python')

如果想访问服务器返回给我们的响应头部信息,可以这样做:

  1. >>> r.headers
  2. {'content-length': '56170', 'x-content-type-options': 'nosniff', 'x-cache':
  3. 'HIT from cp1006.eqiad.wmnet, MISS from cp1010.eqiad.wmnet', 'content-encoding':
  4. 'gzip', 'age': '3080', 'content-language': 'en', 'vary': 'Accept-Encoding,Cookie',
  5. 'server': 'Apache', 'last-modified': 'Wed, 13 Jun 2012 01:33:50 GMT',
  6. 'connection': 'close', 'cache-control': 'private, s-maxage=0, max-age=0,
  7. must-revalidate', 'date': 'Thu, 14 Jun 2012 12:59:39 GMT', 'content-type':
  8. 'text/html; charset=UTF-8', 'x-cache-lookup': 'HIT from cp1006.eqiad.wmnet:3128,
  9. MISS from cp1010.eqiad.wmnet:80'}

然而,如果想得到发送到服务器的请求的头部,我们可以简单地访问该请求,然后是该请求的头部:

三、准备的请求(Prepared Request)

  当你从 API 或者会话调用中收到一个 Response 对象时, request属性其实是使用了 PreparedRequest。有时在发送请求之前,你需要对body 或者 header (或者别的什么东西)做一些额外处理,下面演示了一个简单的做法:

  1. from requests import Request, Session
  2.  
  3. s = Session()
  4. req = Request('GET', url,
  5. data=data,
  6. headers=header
  7. )
  8. prepped = req.prepare()
  9.  
  10. # do something with prepped.body 做某事准备好的body
  11. # do something with prepped.headers 做某事准备好的headers
  12.  
  13. resp = s.send(prepped,
  14. stream=stream,
  15. verify=verify,
  16. proxies=proxies,
  17. cert=cert,
  18. timeout=timeout
  19. )
  20.  
  21. print(resp.status_code)

  由于你没有对 Request 对象做什么特殊事情,你立即准备和修改了 PreparedRequest 对象,然后把它和别的参数一起发送到 requests.* 或者 Session.*

  然而,上述代码会失去 Requests Session 对象的一些优势, 尤其 Session 级别的状态,例如 cookie 就不会被应用到你的请求上去。要获取一个带有状态的 PreparedRequest, 请用 Session.prepare_request() 取代 Request.prepare() 的调用,如下所示:

  1. from requests import Request, Session
  2.  
  3. s = Session()
  4. req = Request('GET', url,
  5. data=data
  6. headers=headers
  7. )
  8.  
  9. prepped = s.prepare_request(req)
  10.  
  11. # do something with prepped.body
  12. # do something with prepped.headers
  13.  
  14. resp = s.send(prepped,
  15. stream=stream,
  16. verify=verify,
  17. proxies=proxies,
  18. cert=cert,
  19. timeout=timeout
  20. )
  21.  
  22. print(resp.status_code)

四、证书验证

  Requests 可以为 HTTPS 请求验证 SSL 证书,就像 web 浏览器一样。SSL 验证默认是开启的,如果证书验证失败,Requests 会抛出 SSLError:

  1. >>> requests.get('https://requestb.in')
  2. requests.exceptions.SSLError: hostname 'requestb.in' doesn't match either of '*.herokuapp.com', 'herokuapp.com'

  在该域名上没有设置SSL,所以失败了。但 Github 设置了 SSL:

  1. >>> requests.get('https://github.com', verify=True)
  2. <Response [200]>

  你可以为 verify 传入 CA_BUNDLE 文件的路径,或者包含可信任 CA 证书文件的文件夹路径,例如下:

  1. >>> requests.get('https://github.com', verify='/path/to/certfile')

  或者将其保持在会话中:

  1. s = requests.Session()
  2. s.verify = '/path/to/certfile'

  注意:如果 verify 设为文件夹路径,文件夹必须通过 OpenSSL 提供的 c_rehash 工具处理。

  你还可以通过 REQUESTS_CA_BUNDLE 环境变量定义可信任 CA 列表。

  如果你将 verify 设置为 False,Requests 也能忽略对 SSL 证书的验证。

  1. >>> requests.get('https://kennethreitz.org', verify=False)
  2. <Response [200]>

  默认情况下, verify 是设置为 True 的。选项 verify 仅应用于主机证书。

  # 对于私有证书,你也可以传递一个 CA_BUNDLE 文件的路径给 verify。你也可以设置 # REQUEST_CA_DUNDLE 环境变量。

五、客户端证书

  你也可以指定一个本地证书用作客户端证书,可以是单个文件(包含密钥和证书)或一个包含两个文件路径的元组:

  1. >>> requests.get('https://kennethreitz.org', cert=('/path/client.cert', '/path/client.key'))
  2. <Response [200]>

  或者保持在会话中:

  1. s = requests.Session()
  2. s.cert = '/path/client.cert'

  如果你指定了一个错误路径或一个无效的证书:

  1. >>> requests.get('https://kennethreitz.org', cert='/wrong_path/client.pem')
  2. SSLError: [Errno 336265225] _ssl.c:347: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib

  警告:本地证书的私有 key 必须是解密状态。目前,Requests 不支持使用加密的 key。

六、CA证书  

  Requests 默认附带了一套它信任的根证书,来自于 Mozilla trust store。然而它们在每次 Requests 更新时才会更新。这意味着如果你固定使用某一版本的 Requests,你的证书有可能已经 太旧了。

  从 Requests 2.4.0 版之后,如果系统中装了 certifi 包,Requests 会试图使用它里边的 证书。这样用户就可以在不修改代码的情况下更新他们的可信任证书。

  为了安全起见,我们建议你经常更新 certifi!

七、响应体内容工作流

  默认情况下,当你进行网络请求后,响应体会立即被下载。你可以通过 stream 参数覆盖这个行为,推迟下载响应体直到访问 Response.content 属性:

  1. tarball_url = 'https://github.com/kennethreitz/requests/tarball/master'
  2. r = requests.get(tarball_url, stream=True)

  此时仅有响应头被下载下来了,连接保持打开状态,因此允许我们根据条件获取内容:

  1. if int(r.headers['content-length']) < TOO_LONG:
  2. content = r.content
  3. ...

  你可以进一步使用 Response.iter_content 和 Response.iter_lines 方法来控制工作流,或者以 Response.raw 从底层 urllib3 的 urllib3.HTTPResponse <urllib3.response.HTTPResponse 读取未解码的响应体。

  如果你在请求中把 stream 设为 True,Requests 无法将连接释放回连接池,除非你 消耗了所有的数据,或者调用了 Response.close。 这样会带来连接效率低下的问题。如果你发现你在使用 stream=True 的同时还在部分读取请求的 body(或者完全没有读取 body),那么你就应该考虑使用 with 语句发送请求,这样可以保证请求一定会被关闭:

  1. with requests.get('http://httpbin.org/get', stream=True) as r:
  2. # 在此处理响应。

八、保持活动状态(持久连接)

  好消息——归功于 urllib3,同一会话内的持久连接是完全自动处理的!同一会话内你发出的任何请求都会自动复用恰当的连接!

  注意:只有所有的响应体数据被读取完毕连接才会被释放为连接池;所以确保将 stream 设置为 False 或读取 Response 对象的 content 属性。

九、流式上传

  Requests支持流式上传,这允许你发送大的数据流或文件而无需先把它们读入内存。要使用流式上传,仅需为你的请求体提供一个类文件对象即可:

  1. with open('massive-body') as f:
  2. requests.post('http://some.url/streamed', data=f)

  警告:强烈建议你用二进制模式(binary mode)打开文件。这是因为 requests 可能会为你提供 header 中的 Content-Length,在这种情况下该值会被设为文件的字节数。如果你用文本模式打开文件,就可能碰到错误。

十、块编码请求

  对于出去和进来的请求,Requests 也支持分块传输编码。要发送一个块编码的请求,仅需为你的请求体提供一个生成器(或任意没有具体长度的迭代器):

  1. def gen():
  2. yield 'hi'
  3. yield 'there'
  4.  
  5. requests.post('http://some.url/chunked', data=gen())

  对于分块的编码请求,我们最好使用 Response.iter_content() 对其数据进行迭代。在理想情况下,你的 request 会设置 stream=True,这样你就可以通过调用 iter_content 并将分块大小参数设为 None,从而进行分块的迭代。如果你要设置分块的最大体积,你可以把分块大小参数设为任意整数。

十一、POST多个分块编码的文件

  你可以在一个请求中发送多个文件。例如,假设你要上传多个图像文件到一个 HTML 表单,使用一个多文件 field 叫做 "images":

  1. <input type="file" name="images" multiple="true" required="true"/>

  要实现,只要把文件设到一个元组的列表中,其中元组结构为 (form_field_name, file_info):

  1. >>> url = 'http://httpbin.org/post'
  2. >>> multiple_files = [
  3. ('images', ('foo.png', open('foo.png', 'rb'), 'image/png')),
  4. ('images', ('bar.png', open('bar.png', 'rb'), 'image/png'))]
  5. >>> r = requests.post(url, files=multiple_files)
  6. >>> r.text
  7. {
  8. ...
  9. 'files': {'images': 'data:image/png;base64,iVBORw ....'}
  10. 'Content-Type': 'multipart/form-data; boundary=3131623adb2043caaeb5538cc7aa0b3a',
  11. ...
  12. }

  警告:强烈建议你用二进制模式(binary mode)打开文件。这是因为 requests 可能会为你提供 header 中的 Content-Length,在这种情况下该值会被设为文件的字节数。如果你用文本模式打开文件,就可能碰到错误。

十二、事件挂钩

  Requests有一个钩子系统,你可以用来操控部分请求过程,或信号事件处理。

  可用的钩子:

    response:从一个请求产生的响应

  你可以通过传递一个{hook_name:callback_function} 字典给hooks请求

requests学习笔记02的更多相关文章

  1. 软件测试之loadrunner学习笔记-02集合点

    loadrunner学习笔记-02集合点 集合点函数可以帮助我们生成有效可控的并发操作.虽然在Controller中多用户负载的Vuser是一起开始运行脚本的,但是由于计算机的串行处理机制,脚本的运行 ...

  2. 机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN)

    机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN) 关键字:邻近算法(kNN: k Nearest Neighbors).python.源 ...

  3. OpenCV 学习笔记 02 使用opencv处理图像

    1 不同色彩空间的转换 opencv 中有数百种关于不同色彩空间的转换方法,但常用的有三种色彩空间:灰度.BRG.HSV(Hue-Saturation-Value) 灰度 - 灰度色彩空间是通过去除彩 ...

  4. SaToken学习笔记-02

    SaToken学习笔记-02 如果排版有问题,请点击:传送门 常用的登录有关的方法 - StpUtil.logout() 作用为:当前会话注销登录 调用此方法,其实做了哪些操作呢,我们来一起看一下源码 ...

  5. Redis:学习笔记-02

    Redis:学习笔记-02 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 4. 事物 Redis 事务本 ...

  6. OGG学习笔记02

    实验环境:源端:192.168.1.30,Oracle 10.2.0.5 单实例目标端:192.168.1.31,Oracle 10.2.0.5 单实例 1.模拟源数据库业务持续运行 2.配置OGG前 ...

  7. 《Master Bitcoin》学习笔记02——比特币的交易模型

    比特币的交易模型 模型基本描述 前面一篇学习笔记01提到了一个交易模型(第三章的内容),在第五章中,除了对这个模型做个详细介绍之外,其实和我上一篇理解的交易模型差不多,一个交易包含输入与输出,比特币是 ...

  8. [Golang学习笔记] 02 命令源码文件

    源码文件的三种类型: 命令源文件:可以直接运行的程序,可以不编译而使用命令“go run”启动.执行. 库源码文件 测试源码文件 面试题:命令源码文件的用途是什么,怎样编写它? 典型回答: 命令源码文 ...

  9. [原创]java WEB学习笔记02:javaWeb开发的目录结构

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  10. 类型和变量(C#学习笔记02)

    类型和变量 [C#类型和变量(原文参考官方教程)]https://docs.microsoft.com/zh-cn/dotnet/csharp/tour-of-csharp/types-and-var ...

随机推荐

  1. SQLSERVER 的 nolock 到底是怎样的无锁?

    一:背景 1. 讲故事 相信绝大部分用 SQLSERVER 作为底层存储的程序员都知道 nolock 关键词,即使当时不知道也会在踩过若干阻塞坑之后果断的加上 nolock,但这玩意有什么注意事项呢? ...

  2. 获取对象的方式-Calendar类的常用成员方法

    获取对象的方式 java.utiL.calendar类:日历类caLendar类是一个抽象类,里边提供了很多操作日历字段的方法(YEAR.MONTH.DAY_OF_MONTH.HOUR )CaLend ...

  3. 【LeetCode字符串#05】基于个人理解的KMP算法图解,以及应用到strStr()函数实现

    KMP算法(用于实现 strStr()) strStr()函数是用来在一个字符串中搜索是否存在另一个字符串的函数,其匹配字符串方式为KMP算法 KMP算法基础理论 假设有如下两个字符串 文本串 aab ...

  4. 我这.NET菜鸟,用它开发RabbitMQ消息队列后,竟被老板一夜提拔为架构师

    [讲故事] 自2022年末推出此工具以来,相关文章已被圈内顶尖的几家.NET头条号转载,而且短短数月,已有超100个团队/个人开发者使用它来操控RabbitMQ消息队列,反响可谓十分火爆.故本次经典重 ...

  5. Fiddler V5.0 英文/汉化 Windows 抓包工具 【12月29日亲测有效】

    前言 Fiddlerr 功能强大的抓包工具,Web调试工具,HTTP协议抓包调试工具.它能够捕获浏览器和程序的所有http/https通信连接,可以针对访问请求,分析请求数据报文.设置断点.调试web ...

  6. Java Day 2

    标识符 凡是变量中需要自己命名的地方都是标识符,例如:包名.类名.变量名等等 标识符的命名规则 1.Java的标识符只能用26个英文字母大小写,0-9的数字,下划线(_),和美元的符号($). 2.标 ...

  7. HTML5----响应式(自适应)网页设计(自动适应屏幕大小)

    HTML5----响应式(自适应)网页设计(自动适应屏幕大小) 现在,很多项目都需要做响应式或者自适应的来适应我们不同屏幕尺寸的手机,电脑等设备,那么就需要我们在页面上下功夫,但移动端的布局不同于pc ...

  8. 免杀之:MSF后门metasploit-loader免杀

    免杀之:MSF后门metasploit-loader免杀 目录 免杀之:MSF后门metasploit-loader免杀 1 metasploit-loader后门代码 2 在kali中编译metas ...

  9. 一位数左边补0,slice也可以

    以下三种方法都可以返回:"09" 1.n<10 ?'0'+n:''+n 2.('0'+n).slice(-2) 3.(''+n).padStart(2,'0')

  10. Wpf Border圆角 设置不成功

    //错误的用法 这样子是不会出现圆角的,哪怕你把CornerRadius设置到1000 <Border CornerRadius="3" Width="100&qu ...