Requests库的基本使用

Requests库是在urllib3库的基础上更层次的抽象封装,使用起来更加简单,代码量也会更少。

快速安装

pip install requests

快速编写示例

最好的学习就是从实践中锻炼学习,立刻动起小手!从这些简单示例开始练习。

访问HTTP协议页面

Python
1
2
3
4
5
6
7
8
9
#!/usr/bin/env python3

import requests

url = 'https://www.baidu.com'
resp = requests.get(url)
print(resp.status_code)
if resp.status_code == 200:
    print(resp.text)

GET-参数查询信息

下面是两个GET方法参数查询示例,其中第二个示例的seen_list是一个列表,这对于参数名相同并且包含多个值的设置是非常方便的。

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import requests as req

payload1 = {
    'name': 'Peter',
    'age': 23
}
payload2 = {
    'name': 'Peter',
    'seen_list': [1,2,3,4,5,6]
}
url = 'https://httpbin.org/get'

resp = req.get(url, params=payload1)
print(resp.url)

resp = req.get(url, params=payload2)
print(resp.url)

执行结果:

$ python ./method_get.py
https://httpbin.org/get?name=Peter&age=23
https://httpbin.org/get?name=Peter&seen_list=1&seen_list=2&seen_list=3&seen_list=4&seen_list=5&seen_list=6

POST-提交web表单

POST方法通常用于页面登录提交表单,因为POST提交参数值不会体现在URL中,相对更加安全,由于URL地址长度是有限制的,GET方法无法携带大量数据内容,POST方法就没有限制。

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import requests as req

payload = {
    'name': 'Peter',
    'age': 23
}
url = 'https://httpbin.org/post'

resp = req.post(url, data=payload)
print(resp.text)

执行结果:

$ python ./method_post.py
{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "age": "18",
    "name": "Peter"
  },
  "headers": {
    "Accept-Encoding": "identity",
    "Content-Length": "214",
    "Content-Type": "multipart/form-data; boundary=281e3c05a41e5ec834f98cf2b673113a",
    "Host": "httpbin.org",
    "X-Amzn-Trace-Id": "Root=1-5f0c0f9d-f490eb9ad301417e59f7b6a2"
  },
  "json": null,
  "origin": "127.0.0.1",
  "url": "https://httpbin.org/post"
}

可以看到form表单中有了我们POST提交的数据了。

POST-发送JSON数据

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import requests as req

payload = {
    'name': 'Peter',
    'age': 23
}
url = 'https://httpbin.org/post'

resp = req.post(url, json=payload)
print(resp.text)

执行结果:

$ python ./method_post_json.py
{
  "args": {},
  "data": "{\"name\": \"Peter\", \"age\": 23}",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Content-Length": "28",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "python-requests/2.24.0",
    "X-Amzn-Trace-Id": "Root=1-5f0c1120-a6c6b65c1eb9dbdc18e21420"
  },
  "json": {
    "age": 23,
    "name": "Peter"
  },
  "origin": "127.0.0.1",
  "url": "https://httpbin.org/post"
}

我们可以看到 headers中多了"Content-Type": "application/json"字段,省去了urllib3设置headers的部分了。

使用stream流模式下载二进制文件

Python
1
2
3
4
5
6
7
8
9
import requests as req

url = 'https://docs.oracle.com/javase/specs/jls/se14/jls14.pdf'

filename = url.split('/')[-1]

with req.get(url,stream=True) as r:
    with open(filename,'wb') as f:
        f.write(r.content)

当在请求中将stream设为True后,Requests无法将连接自动释放回连接池,需要读取完所有数据或者手动调用Requests.close

下载一个图片示例

Python
1
2
3
4
5
import requests as req

resp = req.get('http://www.baidu.com/favicon.ico')
with open('favicon.ico', 'wb') as f:
    f.write(resp.content)

设置超时timeout

超时判断分为两种: Connect建立连接超时 和 Read读取数据超时

timeout超时时间单位为秒, 参数值可以是下面任意一种:

  • float: 最大超时时间,连接和读数据使用一个。
  • 二元组: (连接超时时间, 读数据超时时间)。
  • None : 一直等到地老天荒,海枯石烂。
Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/usr/bin/env python3

import requests

url = 'https://www.baidu.com'
try:
    resp = requests.get(url, timeout = (0.01,3))
    print(resp.status_code)
    if resp.status_code == 200:
        print(resp.text[:50])
except requests.exceptions.ConnectTimeout as e:
    print('连接超时: ' + str(e))

访问HTTPS协议页面

Requests库也是使用certifi库进行证书验证,默认verifyTrue,如果设置为False也可以访问,但是会出现SSL的Warning警告信息。

Python
1
2
3
4
5
6
7
#!/usr/bin/env python3

import requests as req

url = 'https://httpbin.org/anything'
resp = req.get(url, verify=True)
print(resp.status_code)

使用代理访问

import requests as req

proxies = {
    'http'  : '88.198.201.112:8888',
    'https' : '88.198.201.112:8888'
}

print(f'代理地址:{proxies}')

resp = req.get('https://httpbin.org/ip', proxies = proxies)
print(resp.text)

执行结果:

sh
1
2
3
4
5
$ python proxy_http_get.py
代理地址:{'http': 'http://88.198.201.112:8888', 'https': 'http://88.198.201.112:8888'}
{
  "origin": "88.198.201.112"
}

我们访问的https协议地址,代理生效了。

SOCKS5协议代理的使用

使用前可能需要安装PySocks包才可以使用

sh
1
pip install 'requests[socks]'

设置方法同样简单如下:

Python
1
2
3
4
proxies = {
    'http': 'socks5://user:pass@host:port',
    'https': 'socks5://user:pass@host:port'
}

看看这个示例:

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import requests as req

proxies = {
        'http'  : 'socks5://127.0.0.1:1080',
        'https' : 'socks5://127.0.0.1:1080'
}

print(f'代理地址:{proxies}')

resp = req.get('https://httpbin.org/ip', proxies = proxies)
print(resp.text)

url = 'https://www.google.com'
resp = req.get(url, proxies = proxies)
print(f'返回状态码:{resp.status_code}')

执行结果:

sh
1
2
3
4
5
6
7
$ python ./proxy_socks_get.py
代理地址:{'http': 'socks5://127.0.0.1:1080', 'https': 'socks5://127.0.0.1:1080'}
{
  "origin": "88.198.201.112"
}

返回状态码:200

Session管理

requests库的Session可以为相同网站的多次访问保持cookies信息,例如模拟登录操作后,cookies信息会自动保持,继续访问该网站其他内容时都会使用这个登录账号操作。

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import requests

s = requests.Session()

s.get('https://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get("https://httpbin.org/cookies")

print(r.text)

# '{"cookies": {"sessioncookie": "123456789"}}'

如果使用多个代理IP并发访问同一网站,就不要使用Session(),直接使用get()post()访问,否则多个代理IP都会判定为同一个用户的访问,这样就失去了多代理IP并发的作用了。

编码方式的识别

当你收到一个响应时,Requests 会猜测响应的编码方式,用于在你调用 Response.text 方法时对响应进行解码。Requests 首先在 HTTP 头部检测是否存在指定的编码方式,如果不存在,则会使用 charade [http://pypi.python.org/pypi/charade] 来尝试猜测编码方式(在Request 2.24.0版本中使用的是chardet库了)。

只有当 HTTP 头部不存在明确指定的字符集,并且 Content-Type 头部字段包含 text 值之时, Requests 才不去猜测编码方式。在这种情况下, RFC 2616 [http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7.1] 指定默认字符集必须是 ISO-8859-1 。Requests 遵从这一规范。如果你需要一种不同的编码方式,你可以手动设置 Response.encoding 属性,或使用原始的 Response.content。