requests构建HTTP请求

543 阅读4分钟

首先我们回顾一下,http协议的包结构:

image.png

1.构建请求行

请求行里我们需要输入的内容是:方法名和URL

例1.各种http方法的调用例子:

`import requests

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

print(r.content)

r = requests.post('httbin.org/post',data = {'key':'value'})

print(r.content)

r = requests.put('httpbin.org/put',data = {'key':'value'})

print(r.content)

r = requests.delete('httpbon.org/delete')

print(r.content)

r = requests.head('httpbin.org/get')

print(r.content)

r = requests.options('httpbin.org/get')

print(r.content)`

这里可以看到,requests库在你引入之后,直接用"requestes.方法名",就可以发出对应方法的HTTP请求。而每个方法对应的参数,第一个参数固定是请求头里的url,之后的参数则各有不同。

这里只有get方法的一个参数是实际在请求行里生效的,他会被添加到url里,其他的参数都是在请求体(body)或请求头(header)里生效。

例2.get方法里的param参数的例子

`import requests

payload = {'key1':'value1','key2':'value2'}

r = requests.get("httpbin.org/get",params…)

print(r.url)`

最后屏幕上会打出来httpbin.org/get?key1=va… 这就是这个get请求发出来的真正的url,

我们也可以直接在url参数里这样写:httpbin.org/get?key1=va… 这样写就不需要param这个参数了。实际工作中,我们可以根据实际情况选择要不要param参数。

2.构建请求体

请求体这里我们需要输入的内容是:body数据

这个数据可能是json,也可能是字典,也可能是别的数据类型,比如一个字符串,一段xml,现在最流行的数据类型可能就是json和字典。

字典之前我们学过了,那么python中json是什么?

json是一种字符串,它定义的内容就是“键值对”,和字典很类似。

例3,json字符串和字典之间的类型转换,这里用了json这个标准库

import json
dict_a = {"k1":"v1","k2":"v2"}
#把字典转换成json字符串
x = json.dumps(dict_a)
print(x)
print(type(x))
#把json字符串转换成字典
y = json.loads(x)
print(y)
print(type(y))

了解json这个特殊的数据类型之后,我们不禁要问,请求体里的数据我们怎样在requests的这个方法调用输入呢?

答案是通过例1里我们试过的requests提供的http方法来传入。

例1中post和put方法后我们用的data参数是传递字典作为请求数据。此外,还可以使用json参数来传递json字符串作为请求体数据。

这里提一下,我们怎么知道requests的每个方法都有哪些参数呢?

以post方法为例,在pycharm中可以这么操作:

按住ctrl键,然后点击具体方法名,见下图

image.png 然后,就会跳转到这个页面

例4.requests中对于post方法的定义

def post(url,data=None,json=None,**kwargs):
    r**Sends a POST request.
    
    :param url:URL for the new:class:'Request'object.
    :param data:(optional)Ditionary(will be form-encoded),bytes,or file-like object to send in the bodt of the:class:'Request'.
    : param json:(optional) json data to send in the body of the:class:'Request'.
: param \*\* kwargs: Optional arguments that "request"takes.
: return:: class:'Response <Response>' object
: rtype:requests.Response
"""
return request('post',url,data=data,json=json,**kwargs)

这里的docstring 文档告诉我们,post方法接受的参数有url,data(可选),json(可选),此外还接受**kwargs,这个表示接受任意的requests支持的关键字参数,但是文档上没写还有哪些关键字参数是requests支持的,好在我们一般也不需要用到这个参数。

post的两个可选参数 data和json的区别是什么呢?

1.用data参数时发送的data是一个字典,而json则是一个字符串。 2.那我发送数据应该发送data还是json?

看接口文档中的要求,也可以通过抓包来分析,或者你两种都可以试试。

3.构建请求头

请求头里我们可以输入的内容非常多

例5.看一个headers的例子

import requests r=requests.get(http://www.qq.com)
print(r.headers)

运行这段程序后我们可以看到qq 服务器给我们返回的响应里的header内容:

"Date:'Sun,21 Oct 2018 03:04:45 GMT''Content-Type''text/html;charset=GB2312,'Transfer-Encoding:'chunked",'Connection':'keep-alive','Server:
‘squid/3.5.24"Vary:"Accept-Encoding,Accept-Encoding,Accept-Encoding',Expires''Sun,21 Oct 2018 03:05:46 GMT''Cache-Control:'max-age=60,
‘Content-Encoding:'gzip'"X-Cache':"HIT from shanghai.qq.com}

可以看到这里包含了Date、content-type、编码信息、connection类型、服务器信息、超时时间等等许多内容。 requests的headers 是一个字典的子类<class'requests.structures.CaselnsensitiveDict'>,我们可以往里面放各种服务器端需要的key和value。 例6.往header请求头里放数据的例子

url='https://api.github.com/some/endpoint'
headers={user-agent:'my-app/0.0.1}
r=requests.get(url,headers=headers)

这里放了一个user-agent,值为my-app/0.0.1

有的接口里我们会在这里放 username 和password,或者username 和api_token(token就是一个替代密码的令牌。)有时也会在header里存放一个auth 字典,里面包含了登录需要的用户名密码信息。

这一块内容较为复杂,我们在实际工作中,应该以接口文档或抓下来的包为准来构建自己的http请求。也正因为实际工作中,开发可以自己定义想要的请求头内容和请求体内容,我们往往要求开发在提供文档的同时,提供成功的请求和响应的例子,以便用脚本来模拟这些请求。