接口测试:使用Requests库发送POST请求详解

POST请求用于向服务器提交数据,比如提交一个表单新建一个用户、或修改一个用户信息等操作。

对于POST请求,我们可以通过浏览器开发者工具或者其他外部工具来进行抓包,得到请求的URL、请求头(request headers)以及请求的表单data信息,这三样恰恰是我们用Requests库模拟POST请求时需要的。

关于请求头的配置和GET请求是一样的,都是定义headers属性即可。

而关于POST请求提交的参数,是和GET请求是不一样的。

post请求四种传送正文方式:

(1)请求正文是application/x-www-form-urlencoded。
(2)请求正文是multipart/form-data。
(3)请求正文是raw。
(4)请求正文是binary。

这四种提交数据的方式,是在请求头Content-Type属性中来定义。

1、请求正文是application/x-www-form-urlencoded

Reqeusts支持以application/x-www-form-urlencoded数据格式发送POST请求(标准的POST请求数据格式,默认),只需要将请求的参数构造成一个字典,然后传给requests.post()的data参数即可。

示例:

 
  1. """

  2. 1.学习目标

  3.     必须掌握requests库发送post请求方法

  4. 2.HTTP协议中post请求参数类型

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

  6.     根据不同的请求参数类型分为如下几种:

  7.         x-www-form-data-urlencoded

  8.         raw_json格式

  9.         form-data

  10.         binary

  11. 3.json格式

  12.     # 1.导入requests库

  13.     # 2.明确请求地址

  14.     # 3.明确请求参数

  15.         data = {key:value}  字典格式

  16.     # 4.发送请求

  17.         requests.post(url=url,json=data)

  18. 4.需求

  19.     通过访问http://httpbin.org/post接口,验证post参数类型

  20. """

  21. # 1.导入requests库

  22. import requests

  23. import json

  24. # 2.明确请求地址

  25. url = "http://httpbin.org/post"

  26. # 3.明确请求参数

  27. data = {

  28.     "dep_id": "T01",

  29.     "dep_name": "Test学院",

  30.     "master_name": "Test-Master",

  31.     "slogan": "Here is Slogan"

  32. }

  33. # 4.发送请求

  34. response = requests.post(url=url, data=data)

  35. # 将python对象转换为json字符串(格式化返回数据)

  36. result = json.dumps(response.json(), indent=2, ensure_ascii=False)

  37. # print(type(result))  # 字符串类型

  38. print(result)

  39. """

  40. 返回结果:

  41. {

  42.   "args": {},

  43.   "data": "",

  44.   "files": {},

  45.   ****************主要看这里

  46.   "form": {

  47.     "dep_id": "T01",

  48.     "dep_name": "Test学院",

  49.     "master_name": "Test-Master",

  50.     "slogan": "Here is Slogan"

  51.   },

  52.   ***********************

  53.   "headers": {

  54.     "Accept": "*/*",

  55.     "Accept-Encoding": "gzip, deflate",

  56.     "Content-Length": "88",

  57.     *****************主要看这里

  58.     "Content-Type": "application/x-www-form-urlencoded",

  59.     *****************

  60.     "Host": "httpbin.org",

  61.     "User-Agent": "python-requests/2.18.4",

  62.     "X-Amzn-Trace-Id": "Root=1-5ff401e3-1553596b7788e77e275c4772"

  63.   },

  64.   "json": null,

  65.   "origin": "106.35.9.12",

  66.   "url": "http://httpbin.org/post"

  67. }

  68. """

说明:

  • 发送的请求中,form属性接收了参数。
  • 在请求头中,Content-Type属性为application/x-www-form-urlencoded
  • 使用application/x-www-form-urlencoded格式发送数据,requests.post(url=url,
  • data=data)方法中一定要使用data变量来接收参数。
  • 换句话说数据格式是字典格式,使用data变量来接收,会默认发送application/x-www-form-urlencoded数据格式的POST请求。(也可以在请求头中明确一下Content-Type属性,但没必要。)

2、请求正文是raw

RAW的原意就是“未经加工”。换句话说RAW方式使用的是纯字符串的数据上传方式,所以在发送POST请求之前,可能需要手工的把一些JSON格式的数据转换成字符串的(加两单引号),在进行提交。

RAW数据格式的POST请求有两种:

  • 一种是xml格式文本(text/xml)。
  • 一种是json格式文本(application/json)。

(1)json格式文本(application/json)

 
  1. # 1.导入requests库

  2. import requests

  3. import json

  4. # 2.明确请求地址

  5. url = "http://httpbin.org/post"

  6. # 3.明确请求参数

  7. data = {

  8.     "data": [

  9.         {

  10.             "dep_id": "T01",

  11.             "dep_name": "Test学院",

  12.             "master_name": "Test-Master",

  13.             "slogan": "Here is Slogan"

  14.         }

  15.     ]

  16. }

  17. # headers = {"Content-Type": "application/json"}

  18. # 4.发送请求

  19. response = requests.post(url=url, json=data)

  20. print(response)  # <Response [200]>

  21. print(response.text)

  22. """

  23. 返回结果:

  24. {

  25.   "args": {}, 

  26.   "data": "{\"data\": [{\"dep_id\": \"T01\", \"dep_name\": \"Test\\u5b66\\u9662\", \"master_name\": \"Test-Master\", \"slogan\": \"Here is Slogan\"}]}", 

  27.   "files": {}, 

  28.   "form": {}, 

  29.   "headers": {

  30.     "Accept": "*/*", 

  31.     "Accept-Encoding": "gzip, deflate", 

  32.     "Content-Length": "119", 

  33.     **************************主要看这里

  34.     "Content-Type": "application/json", 

  35.     **************************

  36.     "Host": "httpbin.org", 

  37.     "User-Agent": "python-requests/2.18.4", 

  38.     "X-Amzn-Trace-Id": "Root=1-5ff40a9d-6a6f19d272ba4c1b40ff7bbb"

  39.   }, 

  40.     **************************主要看这里

  41.   "json": {

  42.     "data": [

  43.       {

  44.         "dep_id": "T01", 

  45.         "dep_name": "Test\u5b66\u9662", 

  46.         "master_name": "Test-Master", 

  47.         "slogan": "Here is Slogan"

  48.       }

  49.     ]

  50.   }, 

  51.     **************************

  52.   "origin": "106.35.9.12", 

  53.   "url": "http://httpbin.org/post"

  54. }

  55. """

说明:

  • 发送的请求中,json属性接收了参数。
  • 在请求头中,Content-Type属性为application/json。
  • 使用application/json格式发送数据,requests.post(url=url,
  • json=data)方法中一定要使用json变量来接收参数。
  • 换句话说数据格式是Json格式,使用json变量来接收,Requests会默认发送application/json数据格式的POST请求。(也可以在请求头中明确一下Content-Type属性,但没必要。)

注意:

  • 这里我们可以发现Requests模拟post请求时,请求头格式为application/x-www-form-urlencoded与application/json的主要差别在于请求主体的构造格式(前者是键值对,后者是JSON串),前者直接用字典传入,后者用json.dumps()函数将字典转为JSON串即可。
  • 也就是说在有需要的时候json模块下的dumps函数可以将dict转换为str。

(2)xml格式文本(text/xml)
 

 
  1. # 1.导入requests库

  2. import requests

  3. import json

  4. # 2.明确请求地址

  5. url = "http://httpbin.org/post"

  6. # 3.明确请求参数

  7. data = '<sites>' \

  8.             '<site>' \

  9.                 '<name>菜鸟教程</name>' \

  10.                 '<url>www.runoob.com</url>' \

  11.             '</site>' \

  12.             '<site>' \

  13.                 '<name>Google</name>' \

  14.                 '<url>www.google.com</url>' \

  15.             '</site>' \

  16.        '</sites>'

  17. #  requests.post方法中适用json变量来接收数据,

  18. # 默认是"Content-Type": "application/json", 

  19. # 这里我们需要重新声明一下Content-Type属性。

  20. headers = {'Content-type': 'text/xml'}

  21. # 4.发送请求

  22. # 如果数据用data变量来接收会报错。

  23. response = requests.post(url=url, json=data, headers=headers)

  24. print(response)  # <Response [200]>

  25. # print(response.text)

  26. # 将python对象转换为json字符串(格式化返回数据)

  27. result = json.dumps(response.json(), indent=2, ensure_ascii=False)

  28. # print(type(result))  # 字符串类型

  29. print(result)

  30. """

  31. 返回结果:

  32. {

  33.   "args": {},

  34.   "data": "\"<sites><site><name>\\u83dc\\u9e1f\\u6559\\u7a0b</name><url>www.runoob.com</url></site><site><name>Google</name><url>www.google.com</url></site></sites>\"",

  35.   "files": {},

  36.   "form": {},

  37.   "headers": {

  38.     "Accept": "*/*",

  39.     "Accept-Encoding": "gzip, deflate",

  40.     "Content-Length": "149",

  41.     **************************主要看这里

  42.     "Content-Type": "text/xml",

  43.     **************************

  44.     "Host": "httpbin.org",

  45.     "User-Agent": "python-requests/2.18.4",

  46.     "X-Amzn-Trace-Id": "Root=1-5ff40fa5-21a79b532b1ccf6d20173fd7"

  47.   },

  48.   **************************主要看这里

  49.   "json": "<sites><site><name>菜鸟教程</name><url>www.runoob.com</url></site><site><name>Google</name><url>www.google.com</url></site></sites>",

  50.     **************************

  51.   "origin": "106.35.9.12",

  52.   "url": "http://httpbin.org/post"

  53. }

  54. """

说明:

  • text/xml格式相对用的少。
  • xml也可以作为一个文件来传输。
  • 需要重新声明请求头中Content-Type属性。
  • 其他和application/json一样。

提示:其实raw格式数据可以上传text、json、xml、html等纯字符的文本。

3、正文是binary

使用binary格式的正文发送POST请求,是直接使用二进制流进行数据传输,多用于上传单个图片或图片。

也可以用于把请求的参数放入一个文件中,进行数据的提交。

示例如下:

 
  1. """

  2. 1.学习目标

  3.     掌握requests发送post请求

  4. 2.HTTP协议中post请求参数类型

  5.     x-www-form-data-urlencoded

  6.     raw_json格式

  7.     form-data

  8.     binary

  9. 3.binary格式

  10.     # 1.明确请求地址

  11.     # 2.明确请求参数

  12.         data = {"files":open("文件名","rb")}  字典格式

  13.     # 3.发送请求

  14.         requests.post(url= url,files=data)

  15. 4.需求

  16.     http://httpbin.org/post

  17. """

  18. # 1.导入requests

  19. import requests

  20. # 2.请求地址

  21. url = "http://httpbin.org/post"

  22. # 3.请求参数

  23. # 读取文件中的数据作为参数进行提交。

  24. # key位置要写files,是规范

  25. # 也可以写其他的名字,不规范

  26. data = {"files": open("test.txt", "rb")}

  27. # 4.发送请求

  28. response = requests.post(url=url, files=data)

  29. print(response.text)

  30. """

  31. 请求结果如下:

  32. {

  33.   "args": {}, 

  34.   "data": "", 

  35.   **************************主要看这里

  36.   "files": {

  37.     "files": "username=\u5927\u5c0f\u59d0\r\npassword=test123456\r\nage=18"

  38.   }, 

  39.   **************************

  40.   "form": {}, 

  41.   "headers": {

  42.     "Accept": "*/*", 

  43.     "Accept-Encoding": "gzip, deflate", 

  44.     "Content-Length": "192", 

  45.     **************************主要看这里

  46.     "Content-Type": "multipart/form-data; boundary=351e0b73ea144694a9e9fdd1e10d2486", 

  47.     **************************

  48.     "Host": "httpbin.org", 

  49.     "User-Agent": "python-requests/2.18.4", 

  50.     "X-Amzn-Trace-Id": "Root=1-5ff499ea-7ad42c4e6f056b44347b3c26"

  51.   }, 

  52.   "json": null, 

  53.   "origin": "106.35.9.12", 

  54.   "url": "http://httpbin.org/post"

  55. }

  56. """

说明:

  • 发送的请求中,files属性接收了参数。
  • 在请求头中,Content-Type属性为multipart/form-data。
  • 使用application/json格式发送数据,requests.post(url=url,
  • files=data)方法中一定要使用files变量来接收参数。
  • 换句话说Requests也支持发送binary数据形式的POST请求,只需将文件传给requests.post()方法的files参数即可。

4、请求正文是multipart/form-data

multipart/form-data数据格式的POST请求,多用于文件上传。

示例1:上传文件

 
  1. """

  2. 1.学习目标

  3.     掌握requests发送post请求

  4. 2.HTTP协议中post请求参数类型

  5.     x-www-form-data-urlencoded

  6.     raw_json格式

  7.     form-data

  8.     binary

  9. 3.form-data格式

  10.     使用files变量来接收数据,默认是使用form-data格式发送POST请求。

  11. 4.需求

  12.     http://httpbin.org/post

  13. """

  14. import requests

  15. files = {'file1': open('logo.png', 'rb')}

  16. response = requests.post('http://127.0.0.1:9999/post', files=files)

  17. print(response.text)

  18. """

  19. 接口返回结果:

  20. {

  21.   "args": {}, 

  22.   "data": "", 

  23.   **************************主要看这里

  24.   "files": {

  25.     "file1": "data:application/octet-stream;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHerOCtwJPHpvQjoYqxmHighE/wO1YuuATgOKt9wGMd653WXlhe2xbcpauJjePjQYuZTOOk032eaYj+GgOQ+E1QCBj4UxtunNUFIjBmm5P05oBjLv99qoKgEpW9PSu1b0tAglXYOr2/uN4rtp6ZZay53n81IAlauN/pRH/2Q=="

  26.   }, 

  27.   **************************

  28.   "form": {}, 

  29.   "headers": {

  30.     "Accept": "*/*", 

  31.     "Accept-Encoding": "gzip, deflate", 

  32.     "Connection": "keep-alive", 

  33.     "Content-Length": "394145", 

  34.     **************************主要看这里

  35.     "Content-Type": "multipart/form-data; boundary=4efea05a2cf34e78a75508a1ebf000ec", 

  36.     **************************

  37.     "Host": "127.0.0.1:9999", 

  38.     "User-Agent": "python-requests/2.18.4"

  39.   }, 

  40.   "json": null, 

  41.   "origin": "127.0.0.1", 

  42.   "url": "http://127.0.0.1:9999/post"

  43. }

  44. """

示例2:上传文件并重命名

我们也可以显式地设置文件名,文件类型和请求头:

import requests
# hangge.png 为图片名称
files = {'file1': ('hangge.png', open('logo.png', 'rb'), 'image/png', {'Expires': '0'})}
response = requests.post('http://127.0.0.1:9999/post', files=files)
print(response.text)

 
  1. """

  2. 接口返回结果:

  3. {

  4.   "args": {}, 

  5.   "data": "", 

  6.   **************************主要看这里

  7.   "files": {

  8.     "file1": "data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyacMkc0Yyc0UAf/Z"

  9.   }, 

  10.   **************************

  11.   "form": {}, 

  12.   "headers": {

  13.     "Accept": "*/*", 

  14.     "Accept-Encoding": "gzip, deflate", 

  15.     "Connection": "keep-alive", 

  16.     "Content-Length": "7063", 

  17.     **************************主要看这里

  18.     "Content-Type": "multipart/form-data; boundary=382e06cba6834118a1f1efd0ea2c45e3", 

  19.     **************************

  20.     "Host": "127.0.0.1:9999", 

  21.     "User-Agent": "python-requests/2.18.4"

  22.   }, 

  23.   "json": null, 

  24.   "origin": "127.0.0.1", 

  25.   "url": "http://127.0.0.1:9999/post"

  26. }

  27. """

示例3:多文件上传

有时我们需要在一个请求中同时发送多个文件,同样使用 files 参数传入一个数组即可:

 
  1. import requests

  2. files = [

  3.         ('file1', ('1.png', open('logo.png', 'rb'), 'image/png')),

  4.         ('file2', ('2.png', open('logo.png', 'rb'), 'image/png'))

  5. ]

  6. response = requests.post('http://127.0.0.1:9999/post', files=files)

  7. print(response.text)

  8. """

  9. 接口返回结果:

  10. {

  11.   "args": {}, 

  12.   "data": "", 

  13.   **************************主要看这里

  14.   "files": {

  15.     "file1": "data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgc3p8zdacMkc0Yyc0UAf/Z", 

  16.     "file2": "data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgc3p8zdacMkc0Yyc0UAf/Z"

  17.   }, 

  18.   **************************

  19.   "form": {}, 

  20.   "headers": {

  21.     "Accept": "*/*", 

  22.     "Accept-Encoding": "gzip, deflate", 

  23.     "Connection": "keep-alive", 

  24.     "Content-Length": "14054", 

  25.     **************************主要看这里

  26.     "Content-Type": "multipart/form-data; boundary=ba662835a2364b069c99ba3ffa56b974", 

  27.     **************************

  28.     "Host": "127.0.0.1:9999", 

  29.     "User-Agent": "python-requests/2.18.4"

  30.   }, 

  31.   "json": null, 

  32.   "origin": "127.0.0.1", 

  33.   "url": "http://127.0.0.1:9999/post"

  34. }

  35. """

示例4:上传时附带其它参数

如果我们需要在上传文件的同时传递一些其它参数,也是可以的:

 
  1. import requests

  2. data = {

  3.     "name": "ABC.com",

  4.     "age": 100

  5. }

  6. files = [

  7.     ('file1', ('1.png', open('logo.png', 'rb'), 'image/png')),

  8.     ('file2', ('2.png', open('logo.png', 'rb'), 'image/png'))

  9. ]

  10. response = requests.post('http://127.0.0.1:9999/post', data=data, files=files)

  11. print(response.text)

  12. """

  13. 接口返回结果:

  14. {

  15.   "args": {}, 

  16.   "data": "", 

  17.   **************************主要看这里

  18.   "files": {

  19.     "file1": "data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDA0Yyc0UAf/Z", 

  20.     "file2": "data:image/png;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDA0Yyc0UAf/Z"

  21.   }, 

  22.   "form": {

  23.     "age": "100", 

  24.     "name": "ABC.com"

  25.   }, 

  26.   **************************

  27.   "headers": {

  28.     "Accept": "*/*", 

  29.     "Accept-Encoding": "gzip, deflate", 

  30.     "Connection": "keep-alive", 

  31.     "Content-Length": "14233", 

  32.     **************************主要看这里

  33.     "Content-Type": "multipart/form-data; boundary=6bdedbde2b48465683ef4e3451f7e015", 

  34.     **************************

  35.     "Host": "127.0.0.1:9999", 

  36.     "User-Agent": "python-requests/2.18.4"

  37.   }, 

  38.   "json": null, 

  39.   "origin": "127.0.0.1", 

  40.   "url": "http://127.0.0.1:9999/post"

  41. }

  42. """

示例5:流式上传文件

有时我们需要上传一个非常大的文件(比如 1G 左右),如果像上面的方式直接使用 Requests 提交,可能会造成内存不足而崩溃。

所以发送大文件时还是建议将请求做成数据流。不过默认下 Requests 不支持流式上传,但有个第三方包 requests-toolbelt是支持的(本质还是 multipart/form-data 上传)

在使用 requests-toolbelt 之前,我们首先通过 pip 进行安装:

  • # cmd命令行终端执行如下命令。
  • pip install requests-toolbelt

示例如下:

 
  1. """

  2. 1.学习目标

  3.     掌握requests发送post请求

  4. 2.HTTP协议中post请求参数类型

  5.     x-www-form-data-urlencoded

  6.     raw_json格式

  7.     form-data

  8.     binary

  9. 3.form-data格式

  10.     # 1.导入requests库,requests_toolbelt库

  11.     # 2.明确请求地址

  12.     # 3.明确请求参数

  13.         data = {}  字典格式

  14.         对请求参数加工(实例化)

  15.         m = MultipartEncoder(fields = data)

  16.     # 4.添加请求头

  17.         headers = {"Content_Type":m.content_type}

  18.     # 5.发送请求

  19.         requests.post(url= url,data=m,headers=headers)

  20. 4.需求

  21.     http://httpbin.org/post

  22. """

  23. # 1.导入requests库

  24. import requests

  25. from requests_toolbelt import MultipartEncoder

  26. # from requests_toolbelt.multipart.encoder import MultipartEncoder

  27. # 2.明确请求地址

  28. url = "http://httpbin.org/post"

  29. # 3.明确请求参数

  30. data = {

  31.     "username": "Jerry",

  32.     "password": "1232456",

  33.     "sex": "男"

  34. }

  35. # requests-toolbelt 还提供了个监视器(MultipartEncoderMonitor),

  36. # 该监视器接受一个回调函数,我们可以在回调中实时跟踪进度。

  37. # from requests_toolbelt import MultipartEncoderMonitor

  38. # def my_callback(monitor):

  39. #     progress = (monitor.bytes_read / monitor.len) * 100

  40. #     print("\r 文件上传进度:%d%%(%d/%d)"

  41. #           % (progress, monitor.bytes_read, monitor.len), end=" ")

  42. # m = MultipartEncoder(

  43. #     fields={'name': 'ABC.com', "age": '100',

  44. #             'file1': ('1.png', open('logo.png', 'rb'), 'image/png'),

  45. #             'file2': ('2.png', open('logo.png', 'rb'), 'image/png')}

  46. # )

  47. # 4.添加请求头和加工请求参数

  48. # 加工请求参数----让每个参数都要带有边界

  49. m = MultipartEncoder(fields=data)

  50. # 添加请求头

  51. headers = {"Content_Type": m.content_type}

  52. # 4.发送请求

  53. response = requests.post(url=url, data=m, headers=headers)

  54. print(response.text)

  55. """

  56. 请求结果:

  57. {

  58.   "args": {}, 

  59.   "data": "", 

  60.   "files": {}, 

  61.   **************************主要看这里

  62.   "form": {    

  63.     "username": "Jerry",

  64.     "password": "1232456",

  65.     "sex": "男"

  66.     }, 

  67.   **************************

  68.   "headers": {

  69.     "Accept": "*/*", 

  70.     "Accept-Encoding": "gzip, deflate", 

  71.     "Content-Length": "192", 

  72.     **************************主要看这里

  73.     "Content-Type": "multipart/form-data; boundary=351e0b73ea144694a9e9fdd1e10d2486", 

  74.     **************************

  75.     "Host": "httpbin.org", 

  76.     "User-Agent": "python-requests/2.18.4", 

  77.     "X-Amzn-Trace-Id": "Root=1-5ff499ea-7ad42c4e6f056b44347b3c26"

  78.   }, 

  79.   "json": null, 

  80.   "origin": "106.35.9.12", 

  81.   "url": "http://httpbin.org/post"

  82. }

  83. """

5、总结Binary和Form-data区别

主要区别在于:

  • Binary只可以上传二进制数据,通常用来上传文件,由于没有键值,所以一次只能上传一个文件,而Form-data可以传多个。
  • Form-data既可以上传文件等二进制数据,也可以上传表单键值对。利用key-value对,可以分别对每个文件进行描述。

 如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值