Python 的 Requests 库

Requests 库是基于 urllib 写的一个 HTTP 网络请求库,对于日常的网络请求都能满足需求,而且简单好用

安装

官网:http://docs.python-requests.org/en/master/

1
pip3 install requests

使用

7 个主要方法

方法 说明
requests.request() 构造一个请求,支撑以下各方法的基础方法
requests.get() 获取网页的数据,对应 HTTP 的 GET
requests.head() 获取网页头信息,对应 HTTP 的 HEAD
requests.post() 向网页提交 POST 请求,对应 HTTP 的 POST
requests.put() 向网页提交 PUT 请求,对应 HTTP 的 PUT
requests.patch() 向网页提交局部修改请求,对应 HTTP 的 PATCH
requests.delete() 向网页提交删除请求,对应 HTTP 的 DELETE

HTTP 协议中 6 种主要请求方式

方法 说明
GET 请求获取 URL 位置的资源
HEAD 请求获取 URL 位置资源的响应消息报告,即获得该资源的头部信息
POST 请求向 URL 位置的资源后附加新的数据
PUT 请求向 URL 位置存储一个资源,覆盖原 URL 位置的资源
PATCH 请求局部更新 URL 位置的资源,即改变该处资源的部分内容
DELETE 请求删除 URL 位置存储的资源

request() 方法

基础方法,像 get() 、post() 等都是从此方法扩展而来

1
requests.request(method, url, **kwargs)
  • method : 请求方式,对应 get / head / post / put / patch / delete / options 7 种
  • url : 拟获取页面的 url 链接
  • **kwargs: 控制访问的参数,均为可选项,共 13 个
**kwargs 控制访问的参数

params:字典或字节序列,作为参数增加到 url 中

1
2
3
4
5
6
7
8
kv = {'key1': 'value1', 'key2': 'value2'}
r = requests.request('GET', "http://httpbin.org/get", params=kv)
print(r.url) # http://httpbin.org/get?key1=value1&key2=value2

# 还可以将一个列表作为值传入
kv = {'key1': 'value1', 'key2': ['value2', 'value3']}
r = requests.request('GET', "http://httpbin.org/get", params=kv)
print(r.url) # http://httpbin.org/get?key1=value1&key2=value2&key2=value3

data :字典、字节序列或文件对象,作为 Request 的内容

1
2
3
4
5
6
7
8
kv = {'key1': 'value1', 'key2': 'value2'}
r = requests.request('POST', "http://httpbin.org/post", data=kv)
body = "文本内容"
r = requests.request('POST', "http://httpbin.org/post", data=body)

# 表单中多个元素使用同一 key 的时候, 可以使用元组
kv = (('key1', 'value1'), ('key1', 'value2'))
r = requests.request('POST', "http://httpbin.org/post", data=kv)

json:JSON 格式的数据,作为 Request 的内容,对应 Content-Type: application/json

1
2
3
4
5
6
kv = {'key1': 'value1'}
r = requests.request('POST', 'http://httpbin.org/post', json=kv)

# 也可以用 data 实现, 需事先 import json
kv = {'key1': 'value1'}
r = requests.request('POST', 'http://httpbin.org/post', data=json.dumps(kv))

headers:字典,HTTP 定制头

1
2
3
4
headers = {'user-agent': 'my-app/0.0.1'}
r = requests.request('GET', 'https://api.github.com/some/endpoint', headers=headers)
print(r.request.headers)
# {'user-agent': 'my-app/0.0.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

cookies:字典或 CookieJar,Request 中的 cookie

1
2
3
4
5
6
7
8
9
10
11
12
13
14
url = 'http://httpbin.org/cookies'
cookies = dict(cookies_are='working')
r = requests.request('GET', url, cookies=cookies)
print(r.text) # {"cookies": {"cookies_are": "working"}}

# 也可以通过 RequestsCookieJar 设置
cookieJar = requests.cookies.RequestsCookieJar()
cookieJar.set('tasty_cookie', 'yum', domain='httpbin.org', path='/cookies')
cookieJar.set('gross_cookie', 'blech', domain='httpbin.org', path='/elsewhere')
cookieJar.set('token', '1111111111111111111')
url = 'http://httpbin.org/cookies'
r = requests.request('GET', url, cookies=cookieJar)
print(r.text)
# {"cookies": { "tasty_cookie": "yum", "token": "1111111111111111111"}}

auth:元组,支持 HTTP 认证功能,对应 headers 中的 Authorization 字段,Requests 提供两个常用的认证类:HTTPBasicAuthHTTPDigestAuth ,也可以通过自定义类,但必须继承自 AuthBase

1
2
3
4
5
6
7
8
from requests.auth import HTTPBasicAuth

url = "https://api.github.com/repos/requests/requests/issues/482/comments"
body = json.dumps({"body": "Sounds great! I'll get right on it!"})
auth = HTTPBasicAuth('fake@example.com', 'not_a_real_password')
r = requests.post(url=url, data=body, auth=auth)

# 以上只是示例,具体要根据 api 提供真实数据

files:字典类型,传输文件

1
2
3
4
5
6
7
8
9
10
11
12
13
url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.request('POST', url, files=files)

# 也可以显式地设置文件名,文件类型和请求头:
url = 'http://httpbin.org/post'
files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
r = requests.request('POST', url, files=files)

# 也可以发送作为文件来接收的字符串:
url = 'http://httpbin.org/post'
files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}
r = requests.request('POST', url, files=files)

timeout:设定超时时间,秒为单位

1
2
3
4
5
r = requests.request('GET', 'https://github.com', timeout=10)
# 如果要分别设置连接超时和读取超时,可以用元组
r = requests.request('GET', 'https://github.com', timeout=(10, 20))
# 也可以让 Request 永远等待
r = requests.request('GET', 'https://github.com', timeout=None)

proxies:字典类型,设定访问代理服务器,可以增加登录认证

1
2
3
4
5
6
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}

requests.request('GET', "http://example.org", proxies=proxies)

allow_redirects:True/False,默认为 True,重定向开关
stream:True/False,默认为 True,获取内容立即下载开关
verify:True/False,默认为 True,认证 SSL 证书开关
cert:本地 SSL 证书路径

get()

1
requests.get(url, params=None, **kwargs)

post()

1
requests.post(url, data=None, json=None, **kwargs)
1
requests.head(url, **kwargs)

put()

1
requests.put(url, data=None, **kwargs)

patch()

1
requests.patch(url, data=None, **kwargs)

delete()

1
requests.delete(url, **kwargs)

以上几个方法都是有 request() 方法演变而来,参数说明也都是一样的,就不一一举例了

Response 对象

包含爬虫返回的内容

1
2
r = requests.get(url)
# 这个 r 就是 Response 对象

几个重要属性

属性 说明
r.status_code HTTP 请求的返回状态,200 表示连接成功,404 表示失败
r.text HTTP 响应内容的字符串形式,即,url 对应的页面内容
r.encoding 从HTTP header 中猜测的响应内容编码方式
r.apparent_encoding 从内容中分析出的响应内容编码方式(备选编码方式)
r.content HTTP响应内容的二进制形式

注意:

  • 如果 header 中不存在 charset,则认为 r.encoding 的编码为 ISO‐8859‐1
  • r.text 根据 r.encoding 显示网页内容
  • r.apparent_encoding 是根据网页内容分析出的编码方式,可以看作是 r.encoding 的备选

能从 Response 对象获取到的其他属性

cookies
1
2
3
4
r = requests.get('https://github.com')
r.cookies # 得到的是一个 RequestsCookieJar 对象
for k, v in r.cookies.items():
print(k, ":", v) // logged_in : no ......
raise_for_status()

如果 r.status_code 不是200,产生异常 requests.HTTPError

1
2
3
4
5
6
7
8
9
10
11
12
13
def getHTMLText(url):
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return "出错了"


if __name__ == '__main__':
url = 'https://github.com'
print(getHTMLText(url))
headers

获取返回的 headers

1
2
r = requests.get("https://github.com")
print(r.headers) # {'Server': 'GitHub.com', 'Date': 'Thu, 18 ...
request

获取到 Request 对象

1
2
r = requests.get("https://github.com")
print(r.request) # <PreparedRequest [GET]>

通过 Request 对象可以得到请求相关信息,比如请求头

1
2
3
r = requests.get("https://github.com")
print(r.request.headers)
# {'User-Agent': 'python-requests/2.19.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

异常

除了刚说的返回时通过 raise_for_status() 来产生 HTTPError 异常外,Requests 库中定义了一些常见异常

异常 说明
requests.ConnectionError 网络连接错误异常,如 DNS 查询失败、拒绝连接等
requests.HTTPError HTTP 错误异常
requests.URLRequired URL 缺失异常
requests.TooManyRedirects 超过最大重定向次数,产生重定向异常
requests.ConnectTimeout 连接远程服务器超时异常
requests.Timeout 请求 URL 超时,产生超时异常

示例

爬取百度搜索结果

1
2
3
4
5
6
7
8
9
10
import requests
kw = "python"
try:
kv = {'wd': kw}
r = requests.get("http://www.baidu.com/s", params=kv)
print(r.request.url) # http://www.baidu.com/s?wd=python
r.raise_for_status()
print(len(r.text)) # 359225
except:
print("爬取失败")

爬取图片并保存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests
import os

url = 'https://cdn.pixabay.com/photo/2018/10/05/09/45/cobweb-3725540_1280.jpg'
path = 'img/'
file = path + url.split('/')[-1]
try:
if not os.path.exists(path):
os.mkdir(path)
if not os.path.exists(file):
r = requests.get(url)
print(r.status_code)
with open(file, 'wb') as f:
f.write(r.content)
f.close()
print('文件保存成功')
else:
print('文件已存在')
except Exception as e:
print(type(e))
print('出错了')