requests模块

一、 request

requests所有功能都能通过requests/api.py中的方法访问。它们分别是:

  • requests.request(method, url, **kwargs)
  • requests.get(url, params=None, **kwargs)
  • requests.options(url, **kwargs)
  • requests.head(url, **kwargs)
  • requests.post(url, data=None, json=None, **kwargs)
  • requests.put(url, data=None, **kwargs)
  • requests.patch(url, data=None, **kwargs)
  • requests.delete(url, **kwargs)

除了requests.request()外,其余7个方法与http协议中的请求方法一一对应。阅读源码后,不难发现,这7个方法其实都是在调用requests.request()方法,所以了解requests.request()方法提供了哪些参数就变得至关重要了。

参数 解释
method 各种方法,比如get、options、head、post、put、patch、delete,当然也支持自定义扩展
url 请求的url
params 请求携带的params
data 请求body中的data
json 请求body中的json格式的data
headers 请求携带的headers
cookies 请求携带的cookies
files 上传文件时使用
auth 身份认证时使用
timeout 设置请求的超时时间,可以设置连接超时和读取超时
allow_redirects 是否允许重定向,默认True,即允许重定向
proxies 设置请求的代理,支持http代理以及socks代理(需要安装第三方库"pip install requests[socks]")
verify 用于https请求时的ssl证书验证,默认是开启的,如果不需要则设置为False即可
stream 是否立即下载响应内容,默认是False,即立即下载响应内容
cert 用于指定本地文件用作客户端证书

那么发送请求时,我们可以根据自身需求去组合上述的参数。
在调用requests.request()方法之后,会返回一个requests.Response对象供大家使用。

参考文档

二、response

response类故名思议,它包含了服务器对http请求的响应。每次调用requests去请求之后,均会返回一个response对象,通过调用该对象,可以查看具体的响应信息。 示例如下:

import requests
mycookie = '' # 将上图中的cookie对应部分复制过来,以字符串形式传入mycookie变量
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
           'cookie': mycookie}
r = requests.get('https://www.zhihu.com/', headers = headers)
r.status_code # 200,表示请求成功
r.text

此时会打印出响应的状态码和内容。
我们可以根据自身的需求,获取响应中的各种信息,具体内容见下表:

属性或属性方法 解释
r.status_code 响应的http状态码,比如404和200
r.headers 响应头,可单独取出某个字段的值,比如(r.headers)['content-type']
r.raw 原始响应,表示urllib3.response.HTTPResponse对象。使用raw时,要求在请求时设置“stream=True”
r.url 请求的最终地址
r.encoding 要解码的r.text的编码方式
r.history 请求的历史记录,可以用于查看重定向信息,以列表形式展示,排序方式是从最旧到最新的请求
r.reason 响应状态的描述,比如 "Not Found" or "OK"
r.cookies 服务器发回的cookies,RequestsCookieJar类型
r.elapsed 从发送请求到响应到达之间经过的时间量,可以用于测试响应速度。比如r.elapsed.microseconds表示响应到达需要多少微秒
r.request PreparedRequest对象,可以用于查看发送请求时的信息,比如r.request.headers查看请求头
r.ok 检查”status_code“的值,如果小于400,则返回True,如果不小于400,则返回False
r.is_redirect 判断是否重定向,返回True or False
r.is_permanent_redirect 判断是否永久重定向,返回True or False
r.next 返回重定向链中下一个请求的PreparedRequest对象
r.apparent_encoding 用chardet库判断出的编码方式
r.content 响应的内容,byte类型
r.text 响应的内容,unicode类型
r.links 响应的解析头链接

response类除了上述属性和属性方法外,还提供了一些其他方法。

  • 较为常用的r.json()方法,用于将响应解析成json格式。
    是将json格式的字符串转化为python对象
    (用r.text是个json字符串,用json模块中的json.loads转化为字典对象)
  • 应对stream时的iter_content()iter_line()方法,避免响应内容过大占用大量内存。
1、r.status_code # 提取请求状态码

这是HTTP状态码,表示请求的响应状态。由三位数字组成,这三位数中最重要的是第一位数字
a、2开头的表示请求成功最常见的是200,这是最好的结果,请求没有任何问题
b、 3开头表示重定向,即你请求的URL可能是无效的,自动转而去请求了另外一个URL
c、4开头表示客户端错误,即我们这里发的是错的。比如常见的404表示链接是无效的
d、5开头表示服务器错误,即那边接收时发生了错误

2、r.text,r.content

r.text : 网页源代码字符型
r.content: 网页源代码bytes型=二进制形式
他们之间的相互转化是通过编码与解码完成的,

3、两种编码

r.encoding: r.text解码时使用的编码
r.apparent_encoding:是网页真实的编码方式、应该使用的编码

import requests
url='http://www.zhihu.com/api/v4/people/b4471a5431e1f53a96fa06c5e721afd5'
ua = 'Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11'
headers = {'User-Agent':ua}
r = requests.get(url,headers = headers)
print(r.text)

print(r.encoding) # 'ISO-8859-1'
print(r.apparent_encoding) # 'utf-8'
#接下来我们就可以利用这个编码配合r.text来获取正确文本了
print(r.text.encode('ISO-8859-1').decode('utf-8'))
#更通用的做法是下面两种
print(r.content.decode(r.apparent_encoding))
print(r.text.encode(r.encoding).decode(r.apparent_encoding))

参考资料

三、session

http协议本身是无状态的,为了让请求之间保持状态,有了session和cookie机制。requests也提供了相应的方法去操纵它们。

requests中的session对象能够让我们跨http请求保持某些参数,即让同一个session对象发送的请求头携带某个指定的参数。当然,最常见的应用是它可以让cookie保持在后续的一串请求中。

下面,通过官方文档中的示例来了解如何使用它。

import requests

s = requests.Session()
# 第一步:发送一个请求,用于设置请求中的cookies
# tips: http://httpbin.org能够用于测试http请求和响应
s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
# 第二步:再发送一个请求,用于查看当前请求中的cookies
r = s.get("http://httpbin.org/cookies")
print(r.text)


{
  "cookies": {
    "sessioncookie": "123456789"
  }
}

从结果中我们可以看出,第二次请求已经携带上了第一次请求所设置的cookie,即通过session达到了保持cookie的目的。示例中创建了一个requests.Session()对象,通过该对象来进行http请求操作,该操作基本类似于requests.request()
由于session让请求之间具有了连贯性,那么,就有了跨请求参数和非跨请求参数的区别。即有时我想让所有请求均带有某个参数,而有时我只是想让单独的一条请求带上临时的参数。通过下面的例子来了解如何使用。

import requests

s = requests.Session()
s.headers.update({'x-test': 'true'})
# both 'x-test' and 'x-test2' are sent
r1 = s.get('http://httpbin.org/headers', headers={'x-test2': 'true'})
print(r1.text)
# 'x-test' is sent
r2 = s.get('http://httpbin.org/headers')
print(r2.text)

# r1.text
{
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.22.0", 
    "X-Amzn-Trace-Id": "Root=1-5e91656f-b99f14a4d6f47f9e55a90bb4", 
    "X-Test": "true", 
    "X-Test2": "true"
  }
}
# r2.text
{
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.22.0", 
    "X-Amzn-Trace-Id": "Root=1-5e91656f-e9741db4c2ca2fd6e0628396", 
    "X-Test": "true"
  }
}

从结果中我们可以得出两条结论:

  • session可以为请求方法提供缺省数据,比如第一次请求中的{'x-test': 'true'}就是缺省数据,此时的缺省数据就是跨请求参数。
  • 方法级别的参数不会被跨请求保持,比如第二次请求时,没有携带headers={'x-test2': 'true'},返回的结果中也没有{'x-test2': 'true'},说明该参数没有在第一次请求后被保持住。

参考资料

四、cookie

cookie并不陌生,与session一样,能够让http请求前后保持状态。与session不同之处,在于cookie数据仅保存于客户端。requests也提供了相应到方法去处理cookie。
我们知道了requests中的session对象能够在请求之间保持cookie,它极大地方便了我们去使用cookie。当我们想设置方法级别中的请求时,可以如下面示例一样操作

import requests

s = requests.session()
# 第一步:发送一个请求,用于设置请求中的cookies
cookies = dict(cookies_are1='cookie1')
# tips: http://httpbin.org能够用于测试http请求和响应
r1 = s.get(url='http://httpbin.org/cookies', cookies=cookies)
print(r1.text)
# 第二步:发送一个请求,用于再次设置请求中的cookies
cookies = dict(cookies_are2='cookie2')
r2 = s.get(url='http://httpbin.org/cookies', cookies=cookies)
print(r2.text)

# r1.text
{
  "cookies": {
    "cookies_are1": "cookie1"
  }
}
# t2.text
{
  "cookies": {
    "cookies_are2": "cookie2"
  }
}

从结果中可以看出,该方法让cookie只作用了单个请求,因为方法级别的参数不会被跨请求保持,这是requests中session对象的机制,这里不再赘述。那么,如果我们想跨请求保持cookie呢?这里依旧可以应用session对象的跨请求机制,方法如下:

import requests

s = requests.session()
s.cookies.update({'cookies_are1': 'cookie1'})
r1 = s.get(url='http://httpbin.org/cookies')
print(r1.text)

s.cookies.update({'cookies_are2': 'cookie2'})
r2 = s.get(url='http://httpbin.org/cookies')
print(r2.text)
# r1.text
{
  "cookies": {
    "cookies_are1": "cookie1"
  }
}
# r2.text
{
  "cookies": {
    "cookies_are1": "cookie1",
    "cookies_are2": "cookie2"
  }
}

值得一提的是,除了直接用字典去赋值cookie之外,requests还提供了RequestsCookieJar对象供我们使用,它的行为类似字典,但接口更为完整,适合跨域名跨路径使用。来看一个官方文档中的示例。

import requests

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/elsewhere'
r = requests.get(url, cookies=jar)
print(r.text)

{
  "cookies": {
    "tasty_cookie": "yum"
  }
}

从结果中,可以看出我们利用RequestsCookieJar对象,达到了根据不同请求路径,发送不同cookie的效果,进一步增加了操作cookie的灵活性。

参考文档

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容