特点
- Keep-Alive & 连接池
- 国际化域名和 URL
- 带持久 Cookie 的会话
- 浏览器式的SSL认证
- 自动内容解码
- 基本/摘要式的身份认证
- 优雅的key/value Cookie
- 自动解压
- Unicode 响应体
- HTTP(S) 代理支持
- 文件分块上传
- 流下载
- 连接超时
- 分块请求
- 支持 .netrc
缺点:
- 同步阻塞模式,不支持异步和协程
- 尚不支持HTTP2.0
官方文档:https://requests.readthedocs.io/zh_CN/latest/
安装
通过pip命令安装即可:pip install requests
发送请求
发送GET请求
使用requests发送请求,只要使用request.get(url)方法填入对应的接口地址即可,支持携带URL参数。调用方法返回响应对象,可以通过响应对象的status_code、text、headers等属性,来获取状态码、响应文本和响应头等数据,示例如下。
import requests
res = requests.get('https://httpbin.org/get?name=临渊&age=18')
print('状态码', res.status_code)
print('响应文本', res.text)
print('响应头', res.headers)
URL只支持ASCII(美国标准码),在实际的传输过程中,中文及一些特殊字符需要经过urlencode(URL编码)。如上例中的接口地址会被编码成:
https://httpbin.org/get?name=%E4%B8%B4%E6%B8%8A&age=18
requests在发送请求时会自动进行编码,运行后显示如下。
状态码 200
响应文本 {
"args": {
"age": "18",
"name": "\u4e34\u6e0a"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.18.4"
},
"origin": "111.194.126.253, 111.194.126.253",
"url": "https://httpbin.org/get?name=\u4e34\u6e0a&age=18"
}
响应头 {'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', 'Content-Encoding': 'gzip', 'Content-Type': 'application/json', 'Date': 'Mon, 20 Jan 2020 02:33:47 GMT', 'Referrer-Policy': 'no-referrer-when-downgrade', 'Server': 'nginx', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY', 'X-XSS-Protection': '1; mode=block', 'Content-Length': '222', 'Connection': 'keep-alive'}
使用Params
Params又叫Query Params,即URL参数,如?name=临渊&age=18。如果参数很多,直接写到URL中会比较长,不方便查看和修改。URL参数由多组键值对组成。可以通过字典传给requests请求放到的params参数,即request.get(url, params={}),示例如下。
import requests
res = requests.get('https://httpbin.org/get', params={
'name': '临渊', 'age': '18'})
print('响应文本转为字典', res.json())
由于参数可能较多,一般我们可以使用变量,先把url及参数等数据组装好,然后在传入请求方法中。
res.json()方法实际上是使用了json.loads(res.text)将响应文本尝试以JSON格式转为字典。由于该方法存在异常(比如正常情况下返回JSON格式,500报错时则会返回非JSON格式的报错信息),建议使用try…except处理,修改如下。
import requests
url = 'https://httpbin.org/get'
url_params = {
'name': '临渊', 'age': '18'}
res = requests.get(url, params=url_params)
try:
print('响应文本转为字典', res.json())
except:
print('响应文本', res.text)
url_params是自定义的变量名,一般笔者习惯使用params作为变量名,来表示和请求方法参数params的对应关系。即
params = {
'name': '临渊', 'age': '18'}
res = requests.get(url, params=params)
运行结果如下。
响应文本转为字典 {
'args': {
'age': '18', 'name': '临渊'}, 'headers': {
'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.18.4'}, 'origin': '111.194.126.253, 111.194.126.253', 'url': 'https://httpbin.org/get?name=临渊&age=18'}
使用请求头
请求头是链接和请求数据的一些辅助说明信息,常见的请求头有:
- Accept:客户端能接受的内容类型
- Accept-Charset:浏览器可以接受的字符编码
- Accept-Encoding:浏览器可以支持的压缩编码类型
- Accept-Languge:浏览器可以接受的语言
- Referer:连接来路
- User-Agent:发送请求的客户端信息
- Connection:连接类型(Keepalive保持连接/Close关闭连接)
- X-Requested-With:XMLHttpRequest(是Ajax异步请求)
- Cookie:服务器标记信息
- Cache-Control:缓存机制(no-cache无缓存或max-age=缓存保存时间)
- Expries:缓存过期时间
- Content-Type:内容类型(MIME类型)
- Content-Length:数据长度
请求头项一般不区分大小写。Cookie是请求头的一项(注意为单数形式,不带s)。因此在请求一些需要登录状态的接口时可以手动抓取到Cookie,放到请求头中使用,示例如下。
(1)手动登录后,通过Chrome开发者工具抓取请求正常访问时的请求头信息。

请求头中一般cookie用于验证登录,referer用于防止盗链,user-agent用于反爬。
(2)组装字典格式的请求头并使用
请求头一般有一组组键值对组成,我们同样使用Python中的的字典格式,构造出请求头数据,并传递给请求方法的headers参数即可。
import requests
url = 'https://www.jianshu.com/shakespeare/v2/notes/9d3f991c901a/book'
headers = {
'user-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36',
'referer': 'https://www.jianshu.com/p/9d3f991c901a',
'cookie': '__yadk_uid=ratDswBmN3Kzid42v2gKV2q8veUvOsEd; read_mode=day; default_font=font2; locale=zh-CN; remember_user_token=W1s3NTc1NzIxXSwiJDJhJDExJFRVVTNvMlV6NjJaVTlXZjF0YWFuZi4iLCIxNTc5NTczNDg1Ljk2MzgyODYiXQ%3D%3D--feb4c1d88427a88d7321791daf2d76f7b11ed4b3; _m7e_session_core=d0065296a1834086d0279a548d932927; Hm_lvt_0c0e9d9b1e7d617b3e6842e85b9fb068=1579573487,1579587460,1579591333,1579591335; Hm_lpvt_0c0e9d9b1e7d617b3e6842e85b9fb068=1579601795; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%221697595f5777a9-0a3caa4a8cc382-36667905-1024000-1697595f578430%22%2C%22%24device_id%22%3A%221697595f5777a9-0a3caa4a8cc382-36667905-1024000-1697595f578430%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_utm_source%22%3A%22weixin-friends%22%2C%22%24latest_utm_medium%22%3A%22reader_share%22%2C%22%24latest_utm_campaign%22%3A%22hugo%22%2C%22%24latest_utm_content%22%3A%22note%22%7D%2C%22first_id%22%3A%22%22%7D'
}
res = requests.get(url, headers=headers)
print(res.text)
headers=headders第一个headers是请求方法的固定参数,第二个headers是我们自定义的字典变量(变量也可以使用其他名称),执行后打印信息如下。
{
"notebook_id":26739010,"notebook_name":"Python接口测试","liked_by_user":false}
注:本例中请求头实际并没有登录限制,只需要在请求头添加了
user-agent即可正常使用。
使用Cookies
Cookies可以作为一个整体的字符串放到请求头的Cookie字段中,当Cookies很多并且需要组装时,使用字符串会比较长并难以维护。此时可以将Cookies拆开成一组组键值对,构造为字典格式的数据,传递给请求方法的cookies参数,示例如下。
import requests
url = 'https://www.jianshu.com/shakespeare/v2/notes/9d3f991c901a/book'
headers = {
'user-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36',
'referer': 'https://www.jianshu.com/p/9d3f991c901a',
}
cookies = {
'Hm_lpvt_0c0e9d9b1e7d617b3e6842e85b9fb068': '1579601795',
'Hm_lvt_0c0e9d9b1e7d617b3e6842e85b9fb068': '1579573487,1579587460,1579591333,1579591335',
'__yadk_uid': 'ratDswBmN3Kzid42v2gKV2q8veUvOsEd',
'_m7e_session_core': 'd0065296a1834086d0279a548d932927',
'default_font': 'font2',
'locale': 'zh-CN',
'read_mode': 'day',
'remember_user_token': 'W1s3NTc1NzIxXSwiJDJhJDExJFRVVTNvMlV6NjJaVTlXZjF0YWFuZi4iLCIxNTc5NTczNDg1Ljk2MzgyODYiXQ%3D%3D--feb4c1d88427a88d7321791daf2d76f7b11ed4b3',
'sensorsdata2015jssdkcross': '%7B%22distinct_id%22%3A%221697595f5777a9-0a3caa4a8cc382-36667905-1024000-1697595f578430%22%2C%22%24device_id%22%3A%221697595f5777a9-0a3caa4a8cc382-36667905-1024000-1697595f578430%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%24latest_utm_source%22%3A%22weixin-friends%22%2C%22%24latest_utm_medium%22%3A%22reader_share%22%2C%22%24latest_utm_campaign%22%3A%22hugo%22%2C%22%24latest_utm_content%22%3A%22note%22%7D%2C%22first_id%22%3A%22%22%7D'
}
res = requests.get(url, headers=headers, cookies=cookies)
print(res.text)
注:Cookies中不能拥有非ASCII字符,中文应进行URL编码后使用。
同名参数处理:
假设url中具有同名参数,如name=临渊,age=18,age=30。由于字典中不能存在同名的键,我们可以使用嵌套列表实现。示例如下。
params = [('name','临渊'), ('age', '18'), ('age', '30')]
请求方法中的其他参数,如data、headers等,如果存在同名变量也可以这样处理。
发送POST请求
POST方法和GET方法本质上一样的,都是HTTP请求的一种请求动作。只是通常情况下GET请求不使用请求体数据,而POST使用。既然POST方法会发送请求体数据,就会涉及到数据类型的问题。客户端和服务端商量好,才能正常的解析和通讯。这种数据类型又称为媒体类型,标准称法为MIME(Multipurpose Internet Mail Extensions)类型,即多用途互联网邮件扩展类型。数据类型的声明,一般放在请求头(请求辅助信息)的Content-Type字段中,常见的有以下几种格式。
- application/x-www-form-url-encoded:表单URL编码格式
- multipart/form-data:复合表单格式(支持文件上传,文件二进制
- application/json:JSON格式
- application/xml:XML格式
不同数据类型的请求,数据组装方式也不同,至于什么时候用表单,什么时候用JSON格式要看接口文档或问开发小哥哥,接口在编写时便已确定好了需要使用的的数据(媒体)类型。
发送POST请求使用requests的post方法即可,格式如下。
res = requests.post(url,data={
}, json={
}, files={
})
data、json、files都是可选参数(一般同时只用其中一个)。分别用来将数据按不同格式编码发送。
- data参数接受字典时将数据按普通表单(application/x-www-form-url-encoded)格式发送。
- json参数存在时将字典格式的请求数据按JSON格式(application/json)发送
- files参数将字典格式的请求数据(可以包含打开的文件)按混合表单(multipart/form-data)格式发送。
同时使用三者之一时,会自动在请求头中添加对应的内容类型声明Content-Type:...。
当data参数接受字符串格式的参数是按Raw原始格式发送,不进行编码和添加请求头。当data参数接受文件对象时按binary二进制格式发送。
发送FORM表单格式数据
Form表单指网页中包含输入框、选择框、按钮等组成的一组用户填写及选择的数据。如登录、注册表单。表单是最常用的一种请求数据类型,对应的请求头媒体类型声明:Content-Type:application/x-www-form-urlencoded。
之所以称为urlencoded,是因为,请求体数据,实际会按url编码格式发送,如name=临渊,password=123456实际上会编码为
name=%E4%B8%B4%E6%B8%8A&password=123456作为请求体数据,后台传输。
表单类型的参数同样是由多组键值对组成,我们同样适用字典格式构造请求体数据并传递给请求方法的data参数即可,示例如下。
import requests
url = 'https://httpbin.org/post'
data = {
'name': '临渊', 'password': '123456'}
res = requests.post(url, data=data)
print(res.text)
发送POST请求只要使用requests.post()方法即可,方法中的data=data,第一个data是请求方法的一个固定的关键字参数,后面的data是上面我自定义的变量,即{'name': '临渊', 'password': '123456'},使用其他变量名可以。打印结果如下。
{
"args": {
},
"data": "",
"files": {
},
"form": {
"name": "\u4e34\u6e0a",
"password": "123456"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "39",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.18.4"
},
"json": null,
"origin": "111.194.126.253, 111.194.126.253",
"url": "https://httpbin.org/post"
}
发送时,请求头中会自动添加"Content-Type": "application/x-www-form-urlencoded"。
对于JSON格式的响应数据,我们可以使用res.json()转为字典格式并通过字典取值提取响应字段的变量进行断言。假设我们要断言响应结果的url为"https://httpbin.org/post",form不为空且name和password是我们传的值,示例如下。
res_dict = res.json()
form = res_dict.get('form')
assert "https://httpbin.org/post" == res_dict.get('url')
assert form and "临渊" == form.get('name') and '123456' == form.get('password')
再次运行,结果和上次一致。没有报错即为assert断言通过,断言失败时会报AssertionError。
发送JSON格式数据
JSON格式是一种通用的数据格式,在Python中JSON实际为“符合JSON语法格式的字符串”,本质是str类型。JSON格式和Python的字典一一对应,略有不同,如JSON中的true/false/null对应字典中的True/False/None。我们同样可以使用字典来构造JSON请求的数据,然后传递够请求方法的json参数即可,示例如下。
import requests
url = 'https://httpbin.org/post'
json_data = {
'name': '临渊', 'age': 18, 'on_site': True, 'favorite': None}
res = requests.post(url, json=json_data)
print(res.text)
URL参数和FORM变动格式中的数字实际都是转为字符串格式去发送的,而JSON中可以区分数字格式和字符串格式。如{"age": 18}和{"age":"18"}有可能是不一样的。响应文本打印结果如下。
{
"args": {
},
"data": "{\"name\": \"\\u4e34\\u6e0a\", \"age\": 18, \"on_site\": true, \"favorite\": null}",
"files": {
},
"form": {
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "70",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.18.4"
},
"json": {
"age": 18,
"favorite": null,
"name": "\u4e34\u6e0a",
"on_site": true
},
"origin": "111.194.126.253, 111.194.126.253",
"url": "https://httpbin.org/post"
}
发送时,请求头中会自动添加"Content-Type": "application/json"。
细心的同学会发现,FORM表单格式发送的数据会出现在响应的form字段中,JSON格式的却出现在data字段中。这是因为JSON和XML等格式一样属于Raw(原始格式),即原样发送。但是在实际发送时仍要确保请求数据都转为ASCII(美国标准码)来传输。因此中文参数“临渊”在传输是会按utf-8编码转换为“\u4e34\u6e0a”。由于JSON格式中只能使用双引号,响应中data参数是一个JSON格式的字符串,需要使用转义字符“\”。
发送XML格式的数据
上例提到XML和JSON都属于Raw格式的数据,XML和JSON在Python中实际都是不同格式的文本字符串。我们将字符串传递给请求方法的data参数即可原样发送,即data参数有以下3重作用:
- data = {} 或 [(,), (,)]:接受一个字典或嵌套列表格式的数据,会按表单Url编码格式
- data = ‘’:接受一个字符串或bytes二进制字符串,会原样发送(需要手动添加请求头,如果存在中文需要手动编码)
- data = open(’…’, ‘rb’):接受一个文件对象,按binary格式流式上传。
发送XML格式的数据只要将XML格式的多行字符串传递给请求方法的data参数即可,示例如下。
import requests
url = 'https://httpbin.org/post'
xml_data = '''
<xml>
<name>临渊</name>
<age>12</name>
</xml>
'''
headers = {'Content-Type': 'application/xml'}
res = requests.post(url, data=xml_data.encode('utf-8'), headers=headers)
print(res.text)
由于xml_data数据中存在非ASCII码,需要将数据按utf-8格式编码为bytes二进制字符串发送。由于使用Raw格式发送数据时不会自动添加请求头,因此一般要手动在请求头中添加内容类型声明,并将构造的字典类型的请求头变量,传递给请求方法的关键字参数headers。响应结果如下。
{
"args": {
},
"data": "\n<xml>\n <name>\u4e34\u6e0a</name>\n <age>12</name>\n</xml>\n",
"files": {
},
"form": {
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "57",
"Content-Type": "application/xml",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.18.4"
},
"json": null,
"origin": "111.194.126.253, 111.194.126.253",
"url": "https://httpbin.org/post"
}
Raw格式的数据都会记录在该接口响应数据的data字段中。
Raw格式的请求(Text、JavaScript、JSON、XML、HTML等)都可以按这种方式发送。JSON请求自然也可以按原始方式发送,示例如下。
import requests
url = 'https://httpbin.org/post'
json_data_str = '''
{
"name": "临渊",
"age": 18,
"on_site": true,
"favorite": null
}
'''
headers = {'Content-Type': 'application/json'}
res = requests.post(url, data=json_data_str.encode('utf-8'), headers=headers)
print(res.text)
注意以上的json_data_str须是符合JSON格式的字符串,包括必须使用双引号,应该使用小写的true,无值应该是null,由于字符串中存在中文,同样要手动进行encode编码,同时要手动添加请求头指定内容类型。
为方便构造请求数据,也可以先构造一个字典格式的请求数据,再使用json.dumps(),将字典格式的数据转为JSON字符串发送,示例如下。
import requests
import json
url = 'https://httpbin.org/post'
json_data = {
'name': '临渊',
'age':

本文详细介绍了Python的Requests库,包括其特点、安装、发送GET和POST请求、设置请求头、Cookies、JSON与XML数据的发送、文件上传、SSL证书验证、代理设置、超时处理、会话管理等。内容涵盖各种请求参数的使用方法和注意事项,适合Python网络请求初学者和进阶者阅读。
最低0.47元/天 解锁文章
3616

被折叠的 条评论
为什么被折叠?



