Requests模块:
Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTTP 测试需求。Requests 的哲学是以 PEP 20 的习语为中心开发的,所以它比 urllib 更加Pythoner。更重要的是它支持 Python3!
1.安装:
pip install requests
2.Requests 简便的API意味着所有HTTP请求类型都支持:
1 r = requests.put("http://httpbin.org/put") 2 r = requests.delete("http://httpbin.org/delete") 3 r = requests.head("http://httpbin.org/get") 4 r = requests.options("http://httpbin.org/get")
3.传递URL参数:
①: >>> payload = {'key1': 'value1', 'key2': 'value2'} >>> r = requests.get("http://httpbin.org/get", params=payload) >>> print(r.url) 输出:http://httpbin.org/get?key2=value2&key1=value1 #通过打印输出该 URL,你能看到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&key2=value3
4.编码:
你可以找出 Requests 使用了什么编码,并且能够使用 r.encoding 属性来改变它
resopnse = requests.get("http://www.baidu.com")
>>> r.encoding
'ISO-8859-1'
>>> r.encoding = 'utf-8'
5.解析JSON:
Requests 中也有一个内置的 JSON 解码器,助你处理 JSON 数据:
>>> r = requests.get('https://github.com/timeline.json')
>>> r.json()
{'message': 'Hello there, wayfaring stranger. If you’re reading this then you probably didn’t see our blog post a couple of years back announcing that this。。。
注意:如果 JSON 解码失败, r.json() 就会抛出一个异常。例如,响应内容是 401 (Unauthorized),尝试访问 r.json() 将会抛出 ValueError: No JSON object could be decoded 异常。需要注意的是,成功调用 r.json() 并**不**意味着响应的成功。有的服务器会在失败的响应中包含一个 JSON 对象(比如 HTTP 500 的错误细节)。这种 JSON 会被解码返回。要检查请求是否成功,请使用 r.raise_for_status() 或者检查 r.status_code 是否和你的期望相同。
6.获取http响应码/响应状态:
>>> r = requests.get('https://github.com/timeline.json')
>>> r.status_code
410 #响应码
7.请求头定制:
如果你想为请求添加 HTTP 头部,只要简单地传递一个 dict 给 headers 参数就可以了。
1 url = 'https://api.github.com/some/endpoint' 2 headers = {'user-agent': 'my-app/0.0.1'} 3 r = requests.get(url, headers=headers)
8.更加复杂的 POST 请求:
1 payload = {'key1': 'value1', 'key2': 'value2'} 2 r = requests.post("http://httpbin.org/post", data=payload) 3 print(r.text)
输出: { ... "form": { "key2": "value2", "key1": "value1" }, ... }
你还可以为 data 参数传入一个元组列表。在表单中多个元素使用同一 key 的时候,这种方式尤其有效:
>>> payload = (('key1', 'value1'), ('key1', 'value2'))
>>> r = requests.post('http://httpbin.org/post', data=payload)
>>> print(r.text)
{
...
"form": {
"key1": [
"value1",
"value2"
]
},
...
}
很多时候你想要发送的数据并非编码为表单形式的。如果你传递一个 string 而不是一个 dict,那么数据会被直接发布出去。
>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, data=json.dumps(payload))
9.获取响应头:
r = requests.get("http://www.xxx.com")
>>> r.headers
{
'content-encoding': 'gzip',
'transfer-encoding': 'chunked',
'connection': 'close',
'server': 'nginx/1.0.4',
'x-runtime': '148ms',
'etag': '"e1ca502697e5c9317743dc078f67693f"',
'content-type': 'application/json'
>>>r.headers['content-encoding']
>>>r.headers.get('content-encoding') #这种方法不会报错
10.Cookies:
如果某个响应中包含一些 cookie,你可以快速访问它们:
1 url = 'http://example.com/some/cookie/setting/url' 2 r = requests.get(url) 3 r.cookies['example_cookie_name'] 4 输出:'example_cookie_value'
要想发送你的cookies到服务器,可以使用 cookies 参数:
1 url = 'http://httpbin.org/cookies' 2 cookies = dict(cookies_are='working') 3 r = requests.get(url, cookies=cookies) 4 r.text 5 输出:'{"cookies": {"cookies_are": "working"}}'
11.超时:
你可以告诉 requests 在经过以 timeout 参数设定的秒数时间之后停止等待响应。基本上所有的生产代码都应该使用这一参数。
如果不使用,你的程序可能会永远失去响应:
>>> requests.get('http://github.com', timeout=0.001)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)
注意:timeout 仅对连接过程有效,与响应体的下载无关。 timeout 并不是整个下载响应的时间限制,而是如果服务器在timeout 秒内没有应答,将会引发一个异常(更精确地说,是在 timeout 秒内没有从基础套接字上接收到任何字节的数据时)If no timeout is specified explicitly, requests do not time out.
12.错误与异常:
①遇到网络问题(如:DNS 查询失败、拒绝连接等)时,Requests 会抛出一个 ConnectionError 异常。
②如果 HTTP 请求返回了不成功的状态码, Response.raise_for_status() 会抛出一个 HTTPError 异常。
③若请求超时,则抛出一个 Timeout 异常。
④若请求超过了设定的最大重定向次数,则会抛出一个 TooManyRedirects 异常。
⑤所有Requests显式抛出的异常都继承自 requests.exceptions.RequestException 。
Requests的Cookies文档
这里有一篇关于cookie和session详解的文章挺不错的!
13.Session会话对象:
在以上的请求中,每次请求其实都相当于发起了一个新的请求。也就是相当于我们每个请求都用了不同的浏览器单独打开的效果。也就是它并不是指的一个会话,即使请求的是同一个网址。比如:
import requests
requests.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = requests.get("http://httpbin.org/cookies")
print(r.text)
结果是:
{
"cookies": {}
}
很明显,这不在一个会话中,无法获取 cookies,那么在一些站点中,我们需要保持一个持久的会话怎么办呢?就像用一个浏览器逛淘宝一样,在不同的选项卡之间跳转,这样其实就是建立了一个长久会话。
解决方案如下:
import requests
s = requests.Session()
s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get("http://httpbin.org/cookies")
print(r.text)
在这里我们请求了两次,一次是设置 cookies,一次是获得 cookies
运行结果:
{
"cookies": {
"sessioncookie": "123456789"
}
}
发现可以成功获取到 cookies 了,这就是建立一个会话到作用。体会一下。
那么既然会话是一个全局的变量,那么我们肯定可以用来全局的配置了。
import requests
s = requests.Session()
s.headers.update({'x-test': 'true'})
r = s.get('http://httpbin.org/headers', headers={'x-test2': 'true'})
print r.text
通过 s.headers.update 方法设置了 headers 的变量。然后我们又在请求中设置了一个 headers,那么会出现什么结果?
很简单,两个变量都传送过去了。
运行结果:
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1",
"X-Test": "true",
"X-Test2": "true"
}
}
如果get方法传的headers 同样也是 x-test 呢?
r = s.get('http://httpbin.org/headers', headers={'x-test': 'true'})
1
r = s.get('http://httpbin.org/headers', headers={'x-test': 'true'})
它会覆盖掉全局的配置
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1",
"X-Test": "true"
}
}
那如果不想要全局配置中的一个变量了呢?很简单,设置为 None 即可
r = s.get('http://httpbin.org/headers', headers={'x-test': None})
运行结果:
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1"
}
}
Requests的Session文档
14.代理:
如果需要使用代理,你可以通过为任意请求方法提供 proxies 参数来配置单个请求
import requests
proxies = {
"https": "http://41.118.132.69:4433"
}
r = requests.post("http://httpbin.org/post", proxies=proxies)
print r.text
也可以通过环境变量 HTTP_PROXY 和 HTTPS_PROXY 来配置代理
export HTTP_PROXY="http://10.10.1.10:3128"
export HTTPS_PROXY="http://10.10.1.10:1080"
简单实例:
1 import requests 2 3 html = requests.get("https://www.baidu.comindex.php?tn=monline_3_dg") 4 print(html.text) #返回的是Unicode型的数据。 5 print(html.content) #返回的是bytes型也就是二进制的数据。 6 print(html.status_code) #返回http状态码 7 print(html.cookies) #返回cookie 8 print(html.headers) #返回http头信息 9 print(html.url) #返回请求的url地址
附:
①Requests的text和content的区别:
resp.text返回的是Unicode型的数据。
resp.content返回的是bytes型也就是二进制的数据。
也就是说,如果你想取文本,可以通过r.text。
如果想取图片,文件,则可以通过r.content。
②编码问题:
不论使用urllib还是使用requests库经常会遇到中文编码错误的问题,我就经常遇到,因为python安装在windows平台上,cmd的默认编码为GBK,所以在cmd中显示中文时会经常提示gbk编码错误,后来找到了贴在,完美的解决了该问题,下面我分享给大家:
UnicodeEncodeError: 'gbk' codec can't encode character 'xbb' in position 0: illegal multibyte sequence
在cmd中我们输出data.read()时,中文乱码,大部分时候是因为print函数,其实print()函数的局限就是Python默认编码的局限,因为系统是win7的,python的默认编码不是'utf-8',改一下python的默认编码成'utf-8'就行了,sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8') #改变标准输出的默认编码
可以看到该语句修改了python的默认编码为utf8,并赋予了我们的stdout输出,使得python的输出默认编码为utf8,但是当我们在cmd中输出还是中文乱码,这是cmd的锅,cmd不能很好地兼容utf8,而IDLE就可以,甚至在IDLE下运行,连“改变标准输出的默认编码”都不用,因为它默认就是utf8。如果一定要在cmd下运行,那就改一下编码,比如我换成“gb18030”,就能正常显示了:
import io
import sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030') #改变标准输出的默认编码
data.decode('utf8')完美解决。