文章目录
一、简介
Requests 是Python的第三方HTTP库。
- 可以用它来完成大部分HTTP协议行为, 例如: HEAD、GET、POST、PUT、PATCH、DELETE等。
- 可以用它来完成大部分浏览器行为, 例如: 登陆、保持状态、登出、302跳转。
- 可以用它来完成一些浏览器不允许的行为, 例如: 跨域、伪造、接口测试。
二、requests对象
requests对象是这个库的最高级抽象, 它把url_encoding、cookie、data、 headers、cookies 统统隐藏起来了。通过这种最简单的方式帮我们把90%的代码工作都节省掉了, 就剩几个标准协议的名称供我们使用(封装到只外露几颗牙齿)。
1) requests 对象常用方法
方法名 | 使用方法 | 说明 |
---|---|---|
get | requests.get() | 获取数据 |
post | requests.post() | 创建数据 |
put | requests.put() | 当数据存在时更新数据, 当数据不存在是创建数据 |
patch | requests.patch() | 更新数据 |
delete | requests.delete() | 删除数据 |
2) requests 对象常用属性
方法名 | 使用方法 | 数据类型 | 说明 |
---|---|---|---|
status_code | response.status_code | int | 返回状态 |
content | response.content | bytes | 返回内容 |
headers | response.headers | dict | 返回请求头 |
cookies | response.cookies | RequestsCookieJar | Object |
elapsed | response.elapsed | str | 请求到响应结束总耗时 |
reason | response.reason | str | 当status_code小于400时, 返回OK; 当大于等于400时, 返回错误信息 |
request | response.request | PreparedRequest Object | 发情请求所使用的数据对象 |
3) requests 快速上手
1. 发送请求
# 一开始要导入Requests模块
import requests
# 发送GET请求
url = 'http://www.baidu.com'
r = requests.get(url)
# 获取返回状态
print('\n', r.status_code)
"""
r = requests.get(‘https://github.com/timeline.json’) #GET请求
r = requests.post(“http://httpbin.org/post”) #POST请求
r = requests.put(“http://httpbin.org/put”) #PUT请求
r = requests.delete(“http://httpbin.org/delete”) #DELETE请求
r = requests.head(“http://httpbin.org/get”) #HEAD请求
r = requests.options(“http://httpbin.org/get”) #OPTIONS请求
"""
###################################################################
结果:
200
2. 传递 URL 参数
如果URL 的查询字符串传递某种数据。此时恰好是手工构建 URL,那么数据会以键/值对的形式置于 URL 中,跟在一个问号的后面。例如, httpbin.org/get?key=val。 Requests 允许使用 params 关键字参数,以一个字符串字典来提供这些参数。
import requests
# 将字典传入
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload)
print(r.url)
# 将列表作为值传入
payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
r = requests.get('http://httpbin.org/get', params=payload)
print(r.url)
###################################################################
结果:
http://httpbin.org/get?key1=value1&key2=value2
http://httpbin.org/get?key1=value1&key2=value2&key2=value3
3. 响应内容
读取服务器上的内容。Requests 会自动解码来自服务器的内容。大多数 unicode 字符集都能被无缝地解码。
import requests
r = requests.get('https://api.github.com/events')
# Requests会推测其使用的编码格式
# 可以使用 例如: r.encoding = 'ISO-8859-1' 。设置编码格式
print('\n', r.text)
# 二进制响应内容
print('\n', r.content)
# JSON 响应内容 - 需要注意的是JSON解码失败会抛出异常
print('\n', r.json())
# 原始响应内容
print('\n', r.raw)
print(r.raw.read(10))
###################################################################
结果:
[{"id":"10687334418","type":"PullRequestEvent","actor":{"id":36078374,"login":"rubenberna","d.......
b'[{"id":"10687334418","type":"PullRequestEvent","actor":{"id":36078374,"login":"......
[{'id': '10687334418', 'type': 'PullRequestEvent', 'actor': {'id': 36078374, ......
<urllib3.response.HTTPResponse object at 0x1199719b0>
b''
4. 定制请求头
如果想对HTTP标头添加到一个请求,只是在传递dict的 headers参数。
import requests
url = 'https://api.github.com/some/endpoint'
headers = {'user-agent': 'my-app/0.0.1'}
r = requests.get(url, headers=headers)
print('\n', r.text)
###################################################################
结果:
{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}
import requests
import json
data = {'some': 'data'}
headers = {'content-type': 'application/json',
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:22.0) Gecko/20100101 Firefox/22.0'}
r = requests.post('https://api.github.com/some/endpoint', data=data, headers=headers)
print('\n', r.text)
###################################################################
结果:
{
"message": "Not Found",
"documentation_url": "https://developer.github.com/v3"
}
5. POST请求
如果想要发送一些表单编码的数据,就像HTML表单一样。为此,只需将字典传递给data参数即可。提出请求后,数据字典将自动进行表单编码。
import requests
import json
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("https://httpbin.org/post", data=payload)
print('\n', r.text)
# 想发送未经格式编码的数据。如果输入string而不是dict,则该数据将直接过帐。
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))
print('\n', r.text)
# 除了dict自己编码外,还可以使用json参数直接传递它,它将被自动编码
# 需要注意的是:json如果传递了data或参数,则将忽略该参数files
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
r = requests.post(url, json=payload)
print('\n', r.text)
###################################################################
结果:
{
"args": {},
"data": "",
"files": {},
"form": {
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "23",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"json": null,
"origin": "221.224.52.170, 221.224.52.170",
"url": "https://httpbin.org/post"
}
{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}
{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}
6. 上传文件
import requests
url = 'https://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)
print('\n', r.text)
# 可以显式设置文件名,content_type和标头:
url = 'https://httpbin.org/post'
files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
r = requests.post(url, files=files)
print('\n', r.text)
# 也可以发送字符串作为文件接收:
url = 'https://httpbin.org/post'
files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}
r = requests.post(url, files=files)
print('\n', r.text)
###################################################################
结果:
{
"args": {},
"data": "",
"files": {
...
"User-Agent": "python-requests/2.22.0"
},
"json": null,
"origin": "221.224.52.170, 221.224.52.170",
"url": "https://httpbin.org/post"
}
{
"args": {},
"data": "",
"files": {
...
"User-Agent": "python-requests/2.22.0"
},
"json": null,
"origin": "221.224.52.170, 221.224.52.170",
"url": "https://httpbin.org/post"
}
{
"args": {},
"data": "",
"files": {
...
"User-Agent": "python-requests/2.22.0"
},
"json": null,
"origin": "221.224.52.170, 221.224.52.170",
"url": "https://httpbin.org/post"
}
7. 响应状态码和响应头
import requests
# 响应状态码
r = requests.get('https://httpbin.org/get')
print('\n', r.status_code)
# 查看响应状态是否正确 true or false
print('\n', r.status_code == requests.codes.ok)
# Response.raise_for_status()获取错误的响应码
bad_r = requests.get('https://httpbin.org/status/404')
print('\n', bad_r.status_code)
# 可以使用Python字典查看服务器的响应标头
r.headers
{
'content-encoding': 'gzip',
'transfer-encoding': 'chunked',
'connection': 'close',
'server': 'nginx/1.0.4',
'x-runtime': '148ms',
'etag': '"e1ca502697e5c9317743dc078f67693f"',
'content-type': 'application/json'
}
# 但是,字典是特殊的:它仅用于HTTP标头。根据 RFC 7230,HTTP标头名称不区分大小写。
# 因此,我们可以使用所需的任何大写字母访问标头:
print('\n', r.headers['Content-Type'])
print('\n', r.headers.get('content-type'))
###################################################################
结果:
200
True
404
application/json
application/json
8. Cookies
import requests
#如果某个响应中包含一些Cookie,可以快速访问它们:
r = requests.get('http://www.google.com.hk/')
print(r.cookies['NID'])
print(tuple(r.cookies))
# 要想发送cookies到服务器
url = 'http://httpbin.org/cookies'
cookies = {'testCookies_1': 'Hello_Python3', 'testCookies_2': 'Hello_Requests'}
# 在Cookie Version 0中规定空格、方括号、圆括号、等于号、逗号、双引号、斜杠、问号、@,冒号,分号等特殊符号都不能作为Cookie的内容。
r = requests.get(url, cookies=cookies)
print(r.json())
###################################################################
结果:
9. 重定向和历史
默认情况下,除了 HEAD, Requests会自动处理所有重定向。可以使用响应对象的 history 方法来追踪重定向。Response.history 是一个:class:Response <requests.Response> 对象的列表,为了完成请求而创建了这些对象。这个对象列表按照从最老到最近的请求进行排序。
import requests
# Github将所有的HTTP请求重定向到HTTPS
r = requests.get('http://github.com')
print('\n', r.url)
print('\n', r.status_code)
print('\n', r.history)
# 如果使用的是GET, OPTIONS, POST, PUT, PATCH 或者 DELETE,,那么可以通过allow_redirects 参数禁用重定向处理
r = requests.get('http://github.com', allow_redirects=False)
print('\n', r.status_code)
print('\n', r.history)
# 如果使用的是HEAD,也可以启用重定向:
r = requests.head('http://github.com', allow_redirects=True)
print('\n', r.url)
print('\n', r.history)
###################################################################
结果:
https://github.com/
200
[<Response [301]>]
301
[]
https://github.com/
[<Response [301]>]
10. 超时
可以使用参数告诉请求在指定的秒数后停止等待响应timeout。几乎所有生产代码都应在几乎所有请求中使用此参数。否则,可能会导致程序无限期挂起。
注意的时:timeout不是整个响应下载的时间限制;相反,如果服务器timeout几秒钟未发出响应(更确切地说,如果几秒钟内未在基础套接字上接收到任何字节),则会引发异常timeout。如果未明确指定超时,则请求不会超时。
import requests
requests.get('https://github.com/', timeout=0.001)
###################################################################
结果:
Traceback (most recent call last):
.....
raise ConnectTimeout(e, request=request)
requests.exceptions.ConnectTimeout: HTTPSConnectionPool(host='github.com', port=443): Max retries exceeded with url: /
11. 错误和异常
- 如果出现网络问题(例如DNS故障,连接被拒绝等),请求将引发ConnectionError异常。
- Response.raise_for_status()HTTPError如果HTTP请求返回的状态码失败,则会引发。
- 如果请求超时,Timeout则会引发异常。
- 如果请求超过配置的最大重定向数, TooManyRedirects则会引发异常。
请求显式引发的所有异常都继承自 requests.exceptions.RequestException。
requests.exceptions的官方文档:https://docs.python-requests.org//en/master/_modules/requests/exceptions/#RequestException
12. 异常处理
异常捕获:让本该报错的代码不报错知道某段代码会出现异常,但是又没有办法避免,同时又不希望出现异常的时候程序崩溃,这个时候就可以通过异常捕获来让程序不崩溃,并且自行处理异常
异常捕获的语法
try:
代码段1
except:
代码段2
....
except:
代码段
其他语句
具体的异常处理方法可以查看菜鸟教程:https://www.runoob.com/python/python-exceptions.html
4) requests 高级用法
三、RequestsCookieJar 对象
RequestsCookieJar 对象是一个cookie集合体, 它包含多个cookie数据内容.
RequestsCookieJar 对象是对python 的 cookielib.CookieJar 库进行二次封装的一个对象.
1) RequestsCookieJar 对象常用方法
方法名 | 使用方法 | 数据类型 | 说明 |
---|---|---|---|
get | response.cookies.get() | str | 获取一个cookie值 |
keys | response.cookies.keys() | list | 获取所有cookie的name |
values | response.cookies.values() | list 获取所有cookie的name对应的value | |
get_dict | response.cookies.get_dict() | dict | 获取一个完整的cookie键值字典 |
set_cookie | RequestsCookieJar().set_cookie() | 写入一个cookie |
四、PreparedRequest 对象
PreparedRequest 对象是针对get、post、put、patch、delete请求提供的参数进行加工处理, 以确保目标服务器能正常识别这些数据
1) RequestsCookieJar 对象流程
步骤 | 对象 | 说明 |
---|---|---|
1 | PreparedRequest().prepare_method() | 将method字符串转换成大写, 并保存有效的 method |
2 | PreparedRequest().prepare_url() | 检查url的 scheme(http |
3 | PreparedRequest().prepare_headers() | 检查headers的合法性 和 保存有效的headers |
4 | PreparedRequest().prepare_body() | 检查body的合法性 和 保存有效的body |
5 | PreparedRequest().prepare_content_length() | 计算出body的数据长度(Content-Length) 和 保存该值 |
6 | PreparedRequest().prepare_auth() | 检查是否提供认证数据(auth; 账号密码) 和 保存该值 |
7 | PreparedRequest().prepare_cookies() | 检查cookie的合法性 和 保存cookie |
五、Session 对象
Session 是一个线程安全的连接池, 它的作用是维护一个cookie集合, 帮你保留你所有请求痕迹(即所有服务器set-cookie的数据), 通过这种方式可以让你无间断地进行数据交互(而不是每个请求都需要单独认证一次!).
Session 的使用方法跟requests基本保持一致, 同时支持多线程并发请求, 因为它是线程安全的连接池(会话池).
from requests import sessions
session = sessions.Session()
response = session.get("https://www.baidu.com/s?wd=python")
# or
# requests = sessions.Session()
# response = requests.get("https://www.baidu.com/s", params={"wd": "python"})
print(u"请求的URL: ", response.request.url)
print(u"请求的参数(GET方法专属): ", response.request.path_url)
print(u"请求的Method: ", response.request.method)
print(u"请求的头: ", response.request.headers)
print(u"响应状态码: ", response.status_code)
print(u"响应头: ", response.headers)
print(u"响应内容: ", response.content)
print(u"请求所带的cookie和响应所返回的cookie集合: ", response.cookies)
print(u"总共耗时: ", response.elapsed)