Python公开课 - Requests高级功能
前言
在上一章节我们对requests库的基本功能进行了介绍,当然request在处理会话,https等方面也非常方便。
文件上传
我们知道 requests 可以模拟提交一些数据。 假如有的网站需要上传文件,我们也可以用它来实现, 这非常简单,示例如下:
import requests
files = {'file ' : open (’favicon.ico’,'rb’)}
r = requests.post(”http://www.xtuz.net”, files=files)
print(r.text)
当然也可以显式地设置文件名,文件类型和请求头:
>>> url = 'http://www.xtuz.net'
>>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
>>> r = requests.post(url, files=files)
>>> r.text
处理Cookies
如果直接使用Python的标准库urllib 处理Cookies,比较复杂,而有了 requests,获取和设置 Cookies 只需一步即可完成。
获取cookies
import requests
r = requests.get('https://www.baidu.com')
print(r.cookies)
for key, value in r.cookies.items():
print(key + '=' + value)
设置cookies
import requests
r = requests.cookies.RequestsCookieJar()
jar.set('abc', 'test')
r = requests.get('http://www.xtuz.net', cookies=jar, headers =headers)
print(r.text)
处理会话
在 requests 中,如果直接利用 get()或 post()等方法的确可以做到模拟网页的请求,但是这实际 上是相当于不同的会话,也就是说相当于你用了两个浏览器打开了不同的页面。 那么对于登录操作来说就没办法模拟了。
别担心,通过requests我们有更简单的解决方法。解决这个问题的主要需要是维持同一个会话。
但是我又不想每次设置 cookies ,那该怎么办呢?这时候就可以通过Session 对象来实现。利用它,我们可以方便地维护一个会话,而且不用担心 cookies 的问题,它会帮我们自动处理好。
它会在同一个 Session 实例发出的所有请求之间保持 cookies。如果你向同一主机发送多个请求,底层的 TCP 连接将会被重用,从而带来显著的性能提升。
import requests
s = requests. Session()
r = s.get('http://www.xtuz.net')
print(r.text)
会话还可以用作上下文管理器:
with requests.Session() as s:
s.get('http://www.xtuz.net')
这样就能确保退出后会话能被关闭,即使发生了异常也一样。
会话通常用于模拟登录成功之后再进行下一步的操作,在平常用得非常广泛,可以用于模拟在一个浏览器中打开同一站点的不同页面。
处理SSL证书验证
requests 还提供了证书验证的功能。 当发送 HTTP 请求的时候,它会检查 SSL 证书。
默认是自动验证,但是通过设置verify参数为False的话,可以取消验证。
大家都知道12306是一个自己颁布的根证书,所以对于它的验证,我们需要通过下面这种方式:
import requests
r = requests.get("https://www.12306.cn", verify=False)
print(r.status_code)
输出:
/usr/lib/python3/dist-packages/urllib3/connectionpool.py:794: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.org/en/latest/security.html
InsecureRequestWarning)
200
可以看到结果返回中建议我们给它指定证书。
我们也可以指定一个本地证书用作客户端证书,这可以是单个文件(包含密钥和证书)或 一个包含两个文件路径的元组:
import requests
response = requests.get("https://www.12306.cn", cert=("/path/server.crt", "/path/key"))
print(response.status_code)
设置代理
如果需要使用代理你可以通过为任意请求方法提供 proxies 参数来配置单个请求:
import requests
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}
requests.get("http://www.xtuz.net", proxies=proxies)
也可以通过环境变量 HTTP_PROXY 和 HTTPS_PROXY 来配置代理。
$ export HTTP_PROXY="http://10.10.1.10:3128"
$ export HTTPS_PROXY="http://10.10.1.10:1080"
$ python
>>> import requests
>>> requests.get("http://www.xtuz.net")
若代理需要使用HTTP Basic Auth,可以使用 http://user:password@host/
语法:
proxies = {
"http": "http://user:pass@10.10.1.10:3128/",
}
除了基本的 HTTP 代理外, requests 还支持 SOCKS 协议的代理
首先,需要安装 socks 这个库:
pip3 install requests[socks]
然后就可以使用 SOCKS 协议代理了,示例如下:
import requests
proxies = { "http": "sockss://user:password@host:port", "https": "sockss://user:password@host:port"}
requests.get("https://www.taobao.com", proxies=proxies)
超时设置
为防止服务器不能及时响应,大部分发至外部服务器的请求都应该带着 timeout 参数。在默认情况下,除非显式指定了 timeout 值,requests 是不会自动进行超时处理的。如果没有 timeout,你的代码可能会挂起若干分钟甚至更长时间。
连接超时指的是在你的客户端实现到远端机器端口的连接时(对应的是connect()
_),Request 会等待的秒数。一个很好的实践方法是把连接超时设为比 3 的倍数略大的一个数值,因为 TCP 数据包重传窗口 (TCP packet retransmission window) 的默认大小是 3。
一旦你的客户端连接到了服务器并且发送了 HTTP 请求,读取超时指的就是客户端等待服务器发送请求的时间。(特定地,它指的是客户端要等待服务器发送字节之间的时间。在 99.9% 的情况下这指的是服务器发送第一个字节之前的时间)。
如果你设置了一个单一的值作为 timeout,如下所示:
r = requests.get("https://github.com", timeout=5)
这一 timeout 值将会用作 connect 和 read 二者的 timeout。
如果要分别制定,就传入一个元组:
r = requests.get('https://github.com', timeout=(3.05, 27))
准备的请求(Prepared Request)
在标准的urllib中,我们可以将请求表示为数据结构,其中各个参数都可以通过一个 Request 对 象来表示。
这在 requests 里同样可以做到,这个数据结构就叫 Prepared Request
from requests import Request, Session
s = Session()
req = Request('GET', url,
data=data,
headers=header
)
prepped = req.prepare()
# do something with prepped.body
# do something with prepped.headers
resp = s.send(prepped,
stream=stream,
verify=verify,
proxies=proxies,
cert=cert,
timeout=timeout
)
print(resp.status_code)
有了 Request 这个对象,就可以将请求当作独立的对象来看待,这样在进行队列调度时会非常方便。
小结
除了以上的高级功能外, Requests还有其他的高级用法,包括事件钩子、阻塞和非阻塞等,我们将会在其他的章节中进行介绍。