Python requests 库的使用攻略

正文索引 [隐藏]

一、简单的 HTTP 请求与响应解析

基本请求方法

import requests
url = "https://*******"
para = {'key': ***}
r = requests.get(url, params=para) # GET 请求、url 传参,响应内容存在 r 里面
r = requests.post(url, data=para) # POST 请求,响应内容存在 r 里面
r = requests.put(url, data=para)
r = requests.delete(url)
r = requests.head(url)
r = requests.options(url)

响应解析

假设已将响应存在了 r 里面

  • r.url:返回类型 str,返回 url

  • r.headers:返回类型 dict,返回 HTTP 响应报头

    1565937488771

  • r.status_code: 返回类型 int,返回响应状态码

    1565938839031

    另外,还可以使用 r.raise_of_status 来进行报错,如果怎测到响应码为 4XX, 5XX,就会自动捕捉到 HTTPError 的 exception

  • r.cookies:返回类型 RequestsCookieJar,使用方法和 dict 一样,直接取值就行

    1565939121729

  • r.encoding:返回类型 str,返回网页编码方式

    1565937502609

  • r.history:返回类型 list,返回建立完整请求前发送的其他请求(每有一个就 append 到列表后面,最最常见的是 301 重定向

url = r'http://nightmroning.site'
r = requests.get(url)
print(r.history)
print(type(r.history))

1565939963642

  • r.text:返回类型 str,返回响应内容的源码,根据 r.encoding 编码

    1565937521974

  • r.content:返回类型 bytes,返回响应的二进制流

    1565937547718

  • r.json:返回类型 dict,返回被解析的 json 数据(如果有)

  • r.raw:返回类型 urllib3.response.HTTPResponse 类型,返回原始数据

    • 读取可以这么读:r.raw.read(10)

    • 要想用这个,必须在发送请求时将参数 stream 置为 True

    r = requests.get('https://api.github.com/events', stream=True)

二、请求的精细定制

定制请求头

headers = {'user-agent': 'my-app/0.0.1'}
r = requests.get(url, headers=headers)

方法:直接传 dict 到请求的 header 参数即可(但是自定义的 header 优先级低于原生的 header)

POST 文件

假设有个 html 表单:

<input type="file" name="images" multiple="true" required="true"/>

上传多张图片的话:

url = 'https://httpbin.org/post'
multiple_files = [
        ('images', ('foo.png', open('foo.png', 'rb'), 'image/png')),
        ('images', ('bar.png', open('bar.png', 'rb'), 'image/png'))]
r = requests.post(url, files=multiple_files)
r.text

POST JSON 数据

# 方法一, 手动 json 编码
import json
url = 'http://*******'
payload = {'data1':'1'}

r = request.post(url, data=jsqon.dumps(payload))

# 方法二,自动 json 编码
url = 'http://*******'
payload = {'data1':'1'}

r = request.post(url, json=payload)

请求加 Cookies

cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies)

精细控制 301 重定向

使用 GET, OPTIONS, POST, PUT, PATCH, DELETE 方法的时候,如果没有声明,收到 301 会自动重定向,如果想要关闭重定向,可以将 allow_redirects 参数设为 False

url = 'http://nightmorning.site'
r = requests.get(url, allow_redirects=False)
print(r.history)
print(r.text)

1565940127779

如果使用 HEAD 方法,默认不自动重定向,如果要用可以将 allow_redirects 参数设为 True

设置 Timeout

这个是指等待一定时间内如果服务器没有响应那就停止继续等待,这是防止服务器一直不吭声导致程序一直挂起用的,直接设置 timeout 参数就好,单位是秒

r = requests.get(url, timeout=0.001)

如果真的发生 timeout 了,就会 raise 一个 Timeout exception,注意适用 try...catch... 捕捉

三、Session 的保持

如果想要进行类似浏览器的操作,保持一个 session,就需要用到 Session 这个类,这么做由于不用重建 TCP 三次握手,将极大提高请求发送效率,并且将会自动设置 cookies。

基本操作

使用起来和直接 requests 没什么两样,返回的还是响应

s = requests.Session()
url = r'http://nightmroning.site'
r = s.get(url)
print(r.text)

不过有个有趣的用法,这个类可以适用 context managers,也就是 with...as... 语法

with requests.Session() as s:
    s.get('https://nightmorning.site')

区分默认参数和请求级参数

会话默认参数就是指,每次 session 的请求都将带有这个参数,请求级参数指参数仅在本次请求生效

# x-test 为会话默认参数,x-test2 为请求参数
s = requests.Session()
s.auth = ('user', 'pass')
s.headers.update({'x-test': 'true'})
s.get('https://httpbin.org/headers', headers={'x-test2': 'true'})

四、SSL 认证

服务端 SSL 认证

用于在使用 HTTPS 时确认证书,默认情况时对服务端的证书检验是开启的,直接用就行,不用操心

requests.get('https://github.com')

检验失败 raise 一个 requests.exceptions.SSLError

当然也可以手动指定信任的 CA:

# 方法1
requests.get('https://github.com', verify='/path/to/certfile')

# 方法2
s = requests.Session()
s.verify = '/path/to/certfile'

如果要使用什么代理扫描器懒得指定证书,还可以直接忽略调 SSL 证书检验:

requests.get('https://github.com', verify=False)

客户端 SSL 认证

这个没啥说的,提供自己的 SSL 证书给服务器:

# 方法1
requests.get('https://kennethreitz.org', cert=('/path/client.cert', '/path/client.key'))

# 方法2
s = requests.Session()
s.cert = '/path/client.cert'

五、骚气的 hook 系统

这个是可以自定义忘整套处理过程中 DIY 自己的函数内容,目前能用的钩子只有 response,啥意思呢,就是一旦成功获取响应的时候,立刻执行用户自己定义的代码,可以用来输出日志信息,非常好用且帅气:

# 自定义回调函数,
def print_url(r, *args, **kwargs):
    print(r.url)
r = requests.get('https://nightmorning.site', hooks={'response': print_url})
# 一旦收到响应,立刻输出收到响应的 url 

六、代理

http 代理

import requests
proxies = {
  'http': 'http://10.10.1.10:3128',
  'https': 'http://10.10.1.10:1080',
}
requests.get('http://example.org', proxies=proxies)

测试的话就用 burpsuite 好啦,不过走 https 的时候可以直接把 SSL 认证关了,这样就不用管证书的问题了:

import requests
url = 'https://www.baidu.com'

User_Agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0'
proxies = {'http' : 'http://127.0.0.1:8080', 'https': 'https://127.0.0.1:8080'}

headers = {'User-Agent': User_Agent}

with requests.Session() as s:
    r = s.get(url, headers=headers, proxies=proxies, verify=False)

喏,成功抓到包:

1565959312443

SOCKS

用这个得额外下一个依赖

pip install requests[socks]

然后写法就和 http 代理差不多了

proxies = {
    'http': 'socks5://user:pass@host:port',
    'https': 'socks5://user:pass@host:port'
}

参考阅读:Requests官方文档