python+requests
【requests发送请求引言】
使用 Requests 发送网络请求非常简单。
一开始要导入 Requests 模块:
>>import requests
然后,尝试获取某个网页。本例子中,我们来获取 Github 的公共时间线:
>>> r = requests.get('https://api.github.com/events')
>>> print (r)
<Response [200]>
现在,我们有一个名为 r
的 Response
对象。
我们可以从这个对象中获取所有我们想要的信息。
Requests 简便的 API 意味着所有 HTTP 请求类型都是显而易见的。
例如,你可以这样发送一个 HTTP POST 请求:
>> r = requests.post('http://httpbin.org/post', data = {'key':'value'})
漂亮,对吧?那么其他 HTTP 请求类型:PUT,DELETE,HEAD 以及 OPTIONS 又是如何的呢?都是一样的简单:
>> r = requests.put('http://httpbin.org/put', data = {'key':'value'})
>>> r = requests.delete('http://httpbin.org/delete')
>>> r = requests.head('http://httpbin.org/get')
>>> r = requests.options('http://httpbin.org/get')
都很不错吧,但这也仅是 Requests 的冰山一角呢。
一、【响应内容】
>>> import requests
>>> r = requests.get('https://api.github.com/events')
#1.响应状态码
>>> r.status_code
200
#2.为方便引用,Requests还附带了一个内置的状态码查询对象
>>> r.status_code == requests.codes.ok
True
#3.文本响应内容
>>> r.text
u'[{"repository":{"open_issues":0,"url":"https://github.com/...
#4.JSON 响应内容
Requests 中也有一个内置的 JSON 解码器,助你处理 JSON 数据
>>> r.json()
[{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...
#5.原始响应内容(极少使用)
>>> r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>
>>> r.raw.read(10)
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'
#6. 响应头
我们可以查看以一个 Python 字典形式展示的服务器响应头
>>> r.headers
{
'content-encoding': 'gzip',
'transfer-encoding': 'chunked',
'server': 'nginx/1.0.4',
'content-type': 'application/json'
}
#7.也使用任意大写形式来访问这些响应头字段
>>> r.headers['Content-Type']
'application/json'
>>> r.headers.get('content-type')
'application/json'
#8.访问响应字段中的cookies
>>> r.cookies['example_cookie_name']
'example_cookie_value'
#9.发送你的cookies到服务器,可以使用 cookies 参数:
>>> url = 'http://httpbin.org/cookies'
>>> cookies = dict(cookies_are='working')
>>> r = requests.get(url, cookies=cookies)
>>> r.text
'{"cookies": {"cookies_are": "working"}}'
二、【发送请求】
1.普通的请求(如上所示)
r = requests.get('https://api.github.com/events')
2.传递 URL 参数的请求
Requests 允许你使用 params 关键字参数,以一个字符串字典来提供这些参数
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.get("http://httpbin.org/get", params=payload)
通过打印输出该 URL,你能看到 URL 已被正确编码:
>>> print(r.url)
http://httpbin.org/get?key2=value2&key1=value1
2.1还可以将一个列表作为值传入:
payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
定制请求头headers
如果你想为请求添加 HTTP 头部,只要简单地传递一个 dict 给 headers 参数就可以了
>>> url = 'https://api.github.com/some/endpoint'
>>> headers = {'user-agent': 'my-app/0.0.1'}
>>> r = requests.get(url, headers=headers)
>>> r.url
'https://api.github.com/some/endpoint'
3.post请求
通常,你想要发送一些编码为表单形式的数据——非常像一个 HTML 表单。要实现这个,只需简单地传递一个字典给 data 参数。你的数据字典在发出请求时会自动编码为表单形式:
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.post("http://httpbin.org/post", data=payload)
>>> 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,那么数据会被直接发布出去。
例如,Github API v3 接受编码为 JSON 的 POST/PATCH 数据:
>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}
>>> r = requests.post(url, data=json.dumps(payload))
此处除了可以自行对 dict 进行编码,你还可以使用 json 参数直接传递,然后它就会被自动编码。这是 2.4.2 版的新加功能:
>>> r = requests.post(url, json=payload)
POST一个多部分编码文件
>>> url = 'http://httpbin.org/post'
>>> files = {'file': open('report.xls', 'rb')}
>>> r = requests.post(url, files=files)
>>> r.text
{
...
"files": {
"file": "<censored...binary...data>"
},
...
}
你可以显式地设置文件名,文件类型和请求头
>>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
你也可以发送作为文件来接收的字符串
>>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}
【拓展】
参考链接
发送POST请求
一个http请求包括三个部分,为别为请求行,请求报头,消息主体,类似以下这样:
请求行
请求报头
消息主体
HTTP协议规定post提交的数据必须放在消息主体中,但是协议并没有规定必须使用什么编码方式。服务端通过是根据请求头中的Content-Type字段来获知请求中的消息主体是用何种方式进行编码,再对消息主体进行解析。具体的编码方式包括:
- application/x-www-form-urlencoded
最常见post提交数据的方式,以form表单形式提交数据。 - application/json
以json串提交数据。 - multipart/form-data
一般使用来上传文件。
2.7.1 以form形式发送post请求
Reqeusts支持以form表单形式发送post请求,只需要将请求的参数构造成一个字典,然后传给requests.post()的data
参数即可。
url = 'http://httpbin.org/post'
d = {'key1': 'value1', 'key2': 'value2'}
r = requests.post(url, data=d)
print r.text
输出:
{
“args”: {},
“data”: “”,
“files”: {},
“form”: {
“key1”: “value1”,
“key2”: “value2”
},
“headers”: {
……
“Content-Type”: “application/x-www-form-urlencoded”,
……
},
“json”: null,
……
}
可以看到,请求头中的Content-Type字段已设置为application/x-www-form-urlencoded,且d = {'key1': 'value1', 'key2': 'value2'}
以form表单的形式提交到服务端,服务端返回的form字段即是提交的数据。
2.7.2 以json形式发送post请求
可以将一json串传给requests.post()的data参数,
url = 'http://httpbin.org/post'
s = json.dumps({'key1': 'value1', 'key2': 'value2'})
r = requests.post(url, data=s)
print r.text
输出:
{
“args”: {},
“data”: “{\”key2\”: \”value2\”, \”key1\”: \”value1\”}”,
“files”: {},
“form”: {},
“headers”: {
……
“Content-Type”: “application/json”,
……
},
“json”: {
“key1”: “value1”,
“key2”: “value2”
},
……
}
可以看到,请求头的Content-Type设置为application/json,并将s
这个json串提交到服务端中。
2.7.3 以multipart形式发送post请求
Requests也支持以multipart形式发送post请求,只需将一文件传给requests.post()的files
参数即可。
url = 'http://httpbin.org/post'
files = {'file': open('report.txt', 'rb')}
r = requests.post(url, files=files)
print r.text
输出:
{
“args”: {},
“data”: “”,
“files”: {
“file”: “Hello world!”
},
“form”: {},
“headers”: {……
“Content-Type”: “multipart/form-data; boundary=467e443f4c3d403c8559e2ebd009bf4a”,
……
},
“json”: null,
……
}
文本文件report.txt的内容只有一行:Hello world!,从请求的响应结果可以看到数据已上传到服务端中。
2.8 Cookie设置
使用requests,可以轻松获取响应的cookies,和设置请求的cookies。
2.8.1 获取响应的cookies
r.cookies
是响应cookies的字典,通过r.cookies
可访问响应带上的cookies。
r = requests.get(url)
print r.cookies['example_cookie_name']
2.8.2 发送带cookies的请求
url = 'http://httpbin.org/cookies'
cookies = {'cookies_are': 'working'}
r = requests.get(url, cookies=cookies)
print r.text
输出:
{
“cookies”: {
“cookies_are”: “working”
}
}
2.9 请求的超时设置
Requests允许对一个http请求设置超时的时间,只需要在requests.get()或者requests.post()方法的timeout
参数设置一个值(单位为秒)即可。
url = 'http://httpbin.org/get'
r = requests.get(url, timeout=0.001)
将会抛出一个超时异常:
raise ConnectTimeout(e, request=request)
requests.exceptions.ConnectTimeout: HTTPConnectionPool(host=’httpbin.org’, port=80): Max retries exceeded with url: /get (Caused by ConnectTimeoutError(
2.10 异常
在发送http请求时,由于各种原因,requests可能会请求失败而抛出异常。常见的异常包括:
- ConnectionError
由于网络原因,无法建立连接。 - HTTPError
如果响应的状态码不为200,Response.raise_for_status()
会抛出HTTPError 异常。 - Timeout
超时异常。 - TooManyRedirects
若请求超过了设定的最大重定向次数,则会抛出一个 TooManyRedirects 异常。
所有requests抛出的异常都继承自 requests.exceptions.RequestException
类。