Requests 唯一的一个非转基因的 Python HTTP 库,人类可以安全享用。

Requests 允许你发送纯天然,植物饲养的 HTTP/1.1 请求,无需手工劳动。你不需要手动为 URL 添加查询字串,也不需要对 POST 数据进行表单编码。Keep-alive 和 HTTP 连接池的功能是 100% 自动化的,一切动力都来自于根植在 Requests 内部的 urllib3。           ——来自官方文档

我主要参考官方文档,所以先把官方文档贴出来:

1. 安装Requests库

既然是Python的库,那么就可以通过 pip 来进行安装。运行以下指令:

pip install requests

即可安装Requests库。

如果你没有且不愿意安装pip的话,可以去这里 来找到安装方法。(使用pip不好吗)

2. Requests库的基本请求

Requests库中提供了所有的HTTP请求方式,如:

r = requests.get("http://httpbin.org/get")
r = requests.post("http://httpbin.org/post")
r = requests.put("http://httpbin.org/put")
r = requests.delete("http://httpbin.org/delete")
r = requests.head("http://httpbin.org/get")
r = requests.options("http://httpbin.org/get")

2.1 引例

下面是一个小例子:

import requests

r = requests.get('https://blog.domineto.top')
print (type(r)) 
print (r.status_code) 
print (r.encoding) 
print (r.text) 
print (r.cookies) 

以上代码我们请求了本站点的网址,然后打印出了返回结果的类型,状态码,编码方式,Cookies等内容。

运行结果

<class 'requests.models.Response'>
200
UTF-8
//因为text太长了所以后面两个就不写出来了

2.2 基本GET请求

GET请求是我们GET请求是我们最常用的方式。我们通过URL获得 web application 中的信息就是GET方式获取的。

Requests库中进行GET请求也是很方便的:

r = requests.get("http://httpbin.org/get")

这样,我们有一个名为 r 的 Response 对象。我们可以从这个对象中获取所有我们想要的信息。

传递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)

运行结果

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


可以看到,我们传递的参数已经被正确地编码了。

添加Header

如果想添加 headers,可以传 headers 参数:

import requests
 
payload = {'key1': 'value1', 'key2': 'value2'}
headers = {'content-type': 'application/json'}
r = requests.get("http://httpbin.org/get", params=payload, headers=headers)
print r.url

通过headers参数可以增加请求头中的headers信息

2.3 基本POST请求

对于 POST 请求来说,我们一般需要为它增加一些参数。那么最基本的传参方法可以利用 data 这个参数。

一般的表单数据

import requests

payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("http://httpbin.org/post", data=payload)
print (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.21.0"
  },
  "json": null,
  "origin": "218.17.40.219, 218.17.40.219",
  "url": "https://httpbin.org/post"
}


由此可见我们成功把参数POST上去了。

JSON数据

有时候我们需要传送的信息不是表单形式的,需要我们传JSON格式的数据过去,所以我们可以用 json.dumps() 方法把表单数据序列化。

import json
import requests

url = 'http://httpbin.org/post'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))
print (r.text)

运行结果

{
  "args": {}, 
  "data": "{\"some\": \"data\"}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "16", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.9.1"
  }, 
  "json": {
    "some": "data"
  },  
  "url": "http://httpbin.org/post"
}


通过上述方法,我们可以POST JSON格式的数据

文件

如果想要上传文件,那么我们可以直接使用 file 参数即可。

首先我们先新建一个 text.txt 的文件,内容写上 “Hello World!”,作为要上传的文件。

import requests

url = 'http://httpbin.org/post'
files = {'file': open('test.txt', 'rb')}
r = requests.post(url, files=files)
print (r.text)

运行结果

{
  "args": {}, 
  "data": "", 
  "files": {
    "file": "Hello World!"
  }, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "156", 
    "Content-Type": "multipart/form-data; boundary=7d8eb5ff99a04c11bb3e862ce78d7000", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.9.1"
  }, 
  "json": null, 
  "url": "http://httpbin.org/post"
}


这样我们便成功完成了一个文件的上传。

3. 响应内容

3.1 一般响应内容

我们在获得了一个 response 对象后,可以读取响应的内容。以 GitHub 时间线为例:

import requests
r = requests.get('https://api.github.com/events')
r.text

Requests 会自动解码来自服务器的内容。大多数 unicode 字符集都能被无缝地解码。

请求发出后,Requests 会基于 HTTP 头部对响应的编码作出有根据的推测。当我们访问 r.text 之时,Requests 会使用其推测的文本编码。我们可以找出 Requests 使用了什么编码,并且能够使用 r.encoding 属性来改变它:

r.encoding
#结果:'utf-8'

r.encoding = 'ISO-8859-1'

如果我们改变了编码,每当我们访问 r.text ,Request 都将会使用 r.encoding 的新值。

3.2 二进制响应内容

如果想以字节的方式访问请求响应体,我们可以使用 r.content 来实现。Requests 会自动解码 gzip 和 deflate 传输编码的响应数据。

3.3 JSON响应内容

Requests库中内置了一个JSON解码器,可以让我们处理JSON数据:

import requests

r = requests.get('https://api.github.com/events')
r.json()

如果 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 是否和你的期望相同。

3.4 原始套接字响应

如果想获取来自服务器的原始套接字响应,可以取得 r.raw 。 不过需要在初始请求中设置 stream=True 。

r = requests.get('https://github.com/timeline.json', stream=True)
r.raw

运行结果

<urllib3.response.HTTPResponse object at 0x000001E6D35CA240>

4. 响应头

我们可以查看以一个 Python 字典形式展示的服务器响应头:

import requests

r = requests.get("https://blog.domineto.top")
r.headers

运行结果

{
    'Server': 'nginx/1.14.2', 
    'Date': 'Tue, 16 Apr 2019 08:52:16 GMT', 
    'Content-Type': 'text/html; charset=UTF-8', 
    'Transfer-Encoding': 'chunked', 
    'Connection': 'keep-alive', 
    'X-Pingback': 'https://blog.domineto.top/action/xmlrpc', 
    'Set-Cookie': '0b1b9504a98c8280d7d85aeaed073bd6latest_time_id=83; path=/', 
    'Content-Encoding': 'gzip'
}

这个字典比较特殊:它是仅为 HTTP 头部而生的。根据 RFC 2616, HTTP 头部是大小写不敏感的。因此,我们可以使用任意大写形式来访问这些响应头字段。

5. Coookies

5.1 获取Cookies

如果网站的响应里面包含了Cookies,我们也可以使用Cookies参数来获取Cookies。

比如我访问我的首页,想查看一下Cookies,可以使用以下语句:

import requests

url = 'https://blog.domineto.top'
r = requests.get(url)
print (r.cookies)

这样就可以拿到网站的Cookies信息了。

5.2 发送Cookies

Cookies变量不仅可以让我们获取Cookies信息,还可以向服务器发送 cookies 信息:

import requests

url = 'http://httpbin.org/cookies'
cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies)
print (r.text)

运行结果

'{"cookies": {"cookies_are": "working"}}'


可以看到我们已经成功向服务器发送了 cookies。

6. 超时配置

可以利用 timeout 变量来配置最大请求时间:

requests.get('http://github.com', timeout=0.001)

注:timeout 仅对连接过程有效,与响应体的下载无关。

也就是说,这个时间只限制请求的时间。即使返回的 response 包含很大内容,下载需要一定时间,也不会去限制。

7. 会话对象

在以上的请求中,每次请求其实都相当于发起了一个新的请求。也就是相当于我们每个请求都用了不同的浏览器单独打开的效果。也就是它并不是指的一个会话,即使请求的是同一个网址。比如:

import requests

requests.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = requests.get("http://httpbin.org/cookies")
print(r.text)

运行结果

{
  "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": {
    "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'})

嗯,它会覆盖掉全局的配置:

运行结果

{
  "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库还是要多用了之后才会有更深的理解,所以很多功能我用过了再总结吧。

最后修改:2019 年 04 月 16 日
如果觉得我的文章对你有用,请随意赞赏