Python Requests库简明使用教程

Requests是一常用的http请求库,它使用python语言编写,可以方便地发送http请求,以及方便地处理响应结果。

一、安装

1.1 使用pip进行安装

要安装requests,最方便快捷的方法是使用pip进行安装。

pip install requests

如果还没有安装pip,这个链接 Properly Installing Python 详细介绍了在各种平台下如何安装python以及setuptools,pip,virtualenv等常用的python工具,可以参考其中的步骤来进行安装。如果是在Windows平台下使用requests,也可以参考 《Windows下安装Django》 中有关 pip 安装的介绍来安装pip。

1.2 使用源代码安装

可以在github上下载最新的requests的源代码

git clone git://github.com/kennethreitz/requests.git

下载成功后,使用以下命令进行安装

python setup.py install

二、使用

2.1 发送http请求

为了使用requests,需要首先将requests库import进来:

1
import requests

然后,可以使用requests来发送http请求,例如发送get请求:

1
r = requests.get('http://httpbin.org/ip')

执行此行代码,获得一个Response对象r,从r可以获取http请求的响应结果。

如果要发送post请求,则

1
r = requests.post('http://httpbin.org/post', data={'name': 'leo'})

2.2 构造url

我们常常将http请求的参数以url的query string的形式进行发送,传统的做法是我们使用拼凑的方式构造这个url。例如我们需要构造以下这个url:

http://httpbin.org/get?key1=value1&key2=value2

使用reqeuets,你可以方便地构造这个url,而不用手工拼凑。你只需要将这些参数和值构造一个字典,然后将这个字典传给params参数即可:

1
2
3
d = {'key1': 'value1', 'key2': 'value2'}
r = requests.get('http://httpbin.org/get', params=d)
print r.url

输出

http://httpbin.org/get?key2=value2&key1=value1

你可以看到,key1和key2这两个参数已被正确附加到url的query string中。

2.3 HTTP响应正文

一个http响应的格式通常如下:

响应行
响应报头
响应正文

下面是请求 http://httpbin.org/ip 的http响应结果:

HTTP/1.1 200 OK
Server: nginx
Date: Thu, 07 Jul 2016 02:53:49 GMT
Content-Type: application/json
Content-Length: 31
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
[空行]
{
“origin”: “43.230.90.94”
}

注意,响应正文与响应头部之间有一空行间隔。Requests已将http响应封装成Response对象,从Response对象可获取响应正文的内容。

2.3.1 响应正文文本

使用Response.text,可以获取响应的正文文本内容。

1
2
r = requests.get('http://httpbin.org/ip')
print r.text

输出

{
“origin”: “218.107.63.234”
}

Requests会自动对响应正文进行解码:如果Response.encoding为空,那么requests会猜测响应的编码方式,然后进行解码。如果你可以确定响应的编码方式,也可以先对Response.encoding进行设置,然后再通过Response.text获取响应正文。

2.3.2 二进制响应正文

使用Response.content可以获取响应正文的二进制字节内容。

1
2
3
4
5
6
7
from PIL import Image
from StringIO import StringIO

r = requests.get('http://img.blog.csdn.net/20150719230252020')
image = Image.open(StringIO(r.content))
print image.size # 输出(680, 510)
image.show() # Windows平台下可以打开图像

上面的代码使用Response.content构造了一幅图像,然后输出其尺寸并打开该图像。

2.3.3 Json响应正文

如果响应正文是一json串,可以使用Response.json()方法对响应正文进行json decode操作,并返回一个字典。

1
2
3
4
r = requests.get('http://httpbin.org/ip')
d = r.json()
print d
print d['origin']

输出:

{u’origin’: u’43.230.90.94’}
u’43.230.90.94’

如果响应正文不是一个json串,则会报错。

2.4 响应状态

Response对象status_code属性标识http请求响应的状态码:

1
2
r = requests.get('http://httpbin.org/get')
print r.status_code

如果状态码是40X或者50X,那么可以使用Response.raise_for_status()抛出一下异常:

1
2
r = requests.get('http://httpbin.org/status/404')
print r.status_code

404

响应返回404,故使用以下语句会抛出异常:

1
r.raise_for_status()

Traceback (most recent call last):
raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: NOT FOUND for url:
http://httpbin.org/status/404

如果是返回200,则raise_for_status()并不会抛出异常。

1
2
3
r = requests.get('http://httpbin.org/status/200')
print r.status_code
r.raise_for_status()

2.5 响应的头部

Response对象的headers属性是一个字典,可以获得http响应结果的头部的相关信息:

1
2
r = requests.get('http://httpbin.org/headers')
print r.headers

输出:

{‘Content-Length’: ‘157’, ‘Server’: ‘nginx’, ‘Connection’: ‘keep-alive’, ‘Access-Control-Allow-Credentials’: ‘true’, ‘Date’: ‘Wed, 06 Jul 2016 15:53:36 GMT’, ‘Access-Control-Allow-Origin’: ‘*’, ‘Content-Type’: ‘application/json’}

2.6 定制请求的头部

Requests支持定制http请求的头部。为此,我们只需要构造一个字典,然后传给requests.get()的headers参数即可。

1
2
3
4
url = 'http://httpbin.org/headers'
headers = {'user-agent': 'my-app/0.0.1'}
r = requests.get(url, headers=headers)
print r.text

http://httpbin.org/headers 这个链接可以输出请求的头部,由于我们修改了请求头的user-agent字段,所以会访问这个链接会返回:

{
“headers”: {
“Accept”: “/“,
“Accept-Encoding”: “gzip, deflate”,
“Host”: “httpbin.org”,
“User-Agent”: “my-app/0.0.1”
}
}

2.7 发送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参数即可。

1
2
3
4
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参数,

1
2
3
4
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参数即可。

1
2
3
4
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。

1
2
r = requests.get(url)
print r.cookies['example_cookie_name']

2.8.2 发送带cookies的请求

1
2
3
4
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参数设置一个值(单位为秒)即可。

1
2
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(<requests.packages.urllib3.connection.HTTPConnection object at 0x02A8EFF0>, ‘Connection to httpbin.org timed out. (connect timeout=0.001)’))

2.10 异常

在发送http请求时,由于各种原因,requests可能会请求失败而抛出异常。常见的异常包括:

  • ConnectionError
    由于网络原因,无法建立连接。
  • HTTPError
    如果响应的状态码不为200,Response.raise_for_status()会抛出HTTPError 异常。
  • Timeout
    超时异常。
  • TooManyRedirects
    若请求超过了设定的最大重定向次数,则会抛出一个 TooManyRedirects 异常。

所有requests抛出的异常都继承自 requests.exceptions.RequestException类。

三、小结

从以上介绍可以看到,requests在处理httpy请求和响应时可谓简单而直观,这也印证了requests的开发哲学:

  1. Beautiful is better than ugly.(美丽优于丑陋)
  2. Explicit is better than implicit.(清楚优于含糊)
  3. Simple is better than complex.(简单优于复杂)
  4. Complex is better than complicated.(复杂优于繁琐)
  5. Readability counts.(重要的是可读性)

共勉。

四、参考资料

  1. http://docs.python-requests.org/en/master/
  2. http://docs.python-requests.org/en/latest/user/quickstart/
  3. http://docs.python-requests.org/en/latest/user/install/#install
  4. http://docs.python-guide.org/en/latest/starting/installation/
  5. http://stackoverflow.com/questions/5725430/http-test-server-that-accepts-get-post-calls
  6. http://www.tutorialspoint.com/http/http_responses.htm
  7. http://www.aikaiyuan.com/6324.html
  8. http://cn.python-requests.org/zh_CN/latest/user/quickstart.html
  9. http://www.pythonforbeginners.com/requests/using-requests-in-python