接口测试 新人问问。。python+requests 的问题,求大佬帮忙。。

千千 · 2018年05月03日 · 最后由 chen 回复于 2018年05月04日 · 4927 次阅读

开发给的接口是这样的,有 headers 的数据,用 python 不知道为啥一直报错,用 postman 可以正常调用

请问传入 headers 怎么传入?

import requests
import json
import urllib
import urllib2

url = "http://ivt3.hschefu.com:9199/login"

# headers = {'content-type': 'application/json'}
data1 = {'password': '12345678','username': 'xiangjin'}
para = json.dumps(data1)
print(para)
header1 ={'app': 'string','gps': 'string','os': 'string','token': 'string','ver': 'string'}
# print(header1)
# header2 = json.dumps(header1)
# print(header2)
# headers = {}
# headers= json.dumps(headers)
r = requests.post(url,data=para,headers= header1)


print(r.text)

最佳回复
共收到 24 条回复 时间 点赞
仅楼主可见

是提交是数据里面有个叫 header 的。。。
不是你请求的 headers

ETlogic 回复

亲。。。我把数据全部放在 data1 里面 还是不行呢。。。。

千千 #23 · 2018年05月03日 Author
凯蒂 回复

亲把那个 headers 写进去了。。然后吧 body 里面的 header 的数据全部装进 data 了。。可是还是报错。。

requests.post(url,data=para,headers= header1)

这里的 headers 对应的是 http 请求头部(header),即 http 协议中的一个特殊部分。和你在 http body 里面的 json 的 header 字段值不是同一个概念。而你的 http body 一直都是缺少了 header 这个 json 字段的。

遇到这类问题,推荐你用一个通用的解决方法:抓包。先抓到 Postman 发出的正确包,然后再抓 requests 发出的包,比对这两个包的差异,改你的脚本直至两者抓包结果一致。

PS:从 postman 截图来看,有 3 个 http header 字段,但你 python 脚本里没配,可以从这个方面尝试去看看?

千千 #21 · 2018年05月03日 Author

我也觉得。。有两个字段的东西。。但是又不能合在一起写进 data。。。全部写进去又报错。。
那 3 个 headers 有两个是之前调试的。。实际只有一个这个

postman 直接可以导出 Python 代码,导出来看看缺少些什么

千千 #19 · 2018年05月03日 Author
雨夜狂奔 回复

POSTMAN 提取 python 是这样滴。。。

我照着样子修改了下代码。。还是调不通。。。

注意一下 header1 要加上 Content-t
Type:application/json 键值对,postman 可以是因为你的 postman 数据选择为 json 的时候,已经自动帮你添加了。

data1 还是要转成 json 字符串

你 json.dump 了么
r = requests.post(url,data=json.dump(para),headers= header1)

你传的是 json 数据,所以只需要改一个地方就可以了,r = requests.post(url, json=para, headers=headers)

千千 #14 · 2018年05月04日 Author

正确代码是这样的。。请问为什么 data 写法要写/在里面呢

import requests

url = "http://ivt3.hschefu.com:9199/login"

payload = "{\"data\": {\"password\": \"12345678\",\"username\": \"xiangjin\"}}"
headers = {
    'Content-Type': "application/json",
    }

response = requests.request("POST", url, data=payload, headers=headers)
r = requests.post(url,data=payload,headers= headers)

print(response.text)
print(r.text)

千千 #15 · 2018年05月04日 Author
hellohell 回复

导出 python 代码是这样的。。。运行到 python 可以成功执行

请问为什么要写数据格式要写/,然后 data 要用两个{}呢。。。。

匿名 #14 · 2018年05月04日
千千 回复

你注意看 payload = "{\"data\": {\"password\": \"12345678\",\"username\": \"xiangjin\"}}" 这是字符串,而你使用的是字典类型,是不一样的,如果按照你的代码,只需要把 data= 改成 json=, 或者 r = requests.post(url,data=json.dump(para),headers= header1) 这样也是可以的,要把你的 para 数据 dump 一下

千千 #10 · 2018年05月04日 Author

亲改成你说的那样还是不行呢

#coding=utf-8
import requests
import json
import urllib
import urllib2

url = "http://ivt3.hschefu.com:9199/login"

headers = {
    'Content-Type': "application/json",
    'Cache-Control': "no-cache",
    'Postman-Token': "2075beff-527a-4eb4-a5f1-45de3d3ecab1"
    }
data1 = {"password": "12345678","username": "xiangjin"}
para = json.dumps(data1)
print(para)

r = requests.post(url,data=json.dumps(para),headers= headers)


print(r.text)
千千 回复

你的 data1 写错了啊
data1 = {"data":{"password": "12345678","username": "xiangjin"}}

两个问题

  1. 既然你用例 requests 为啥还要 import urllib,import urllib2
  2. r = requests.post(url,json=data,headers= headers), data=你 postman body 中所有的数据

你这是在考验大家的眼力吗😂

其实我也比较懵逼

看了看帖子,开始有一个地方没太想通,requests 在 post 提交 json 的时候不是该

requests.post(url,json='xxx',header={'Content-Type': "application/json"}

怎么

requests.post(url,data='xxx',header={'Content-Type': "application/json"}

也可以?当然 data 和 json 的实参类型不一样;

然后我做了个实验

  1. 去 github 上 clone requests 模块代码,clone 到 Download 目录;

  2. 去 requests-master/requests/adapters.py 第 435 行添加了print request.body
    ta 就变成了这样

if not chunked:
    print request.body  # 这是我添加的
    resp = conn.urlopen(
        method=request.method,
        url=url,
        body=request.body,
        headers=request.headers,
        redirect=False,
        assert_same_host=False,
        preload_content=False,
        decode_content=False,
        retries=self.max_retries,
        timeout=timeout
    )

3.然后写了代码

import sys,os
sys.path[0:0]=[os.path.expanduser('~/Downloads/requests-master/')]
print sys.path[0]

import requests
print requests.__file__


url = "http://ivt3.hschefu.com:9199/login"
headers = {
    'Content-Type': "application/json",
    }

# 第一种方式
requests.request("POST", url, json={"data":
                                      {"password": "12345678",
                                       "username": "xiangjin"}
                                    },
                              headers=headers)

# 第二种方式
payload = "{\"data\": {\"password\": \"12345678\",\"username\": \"xiangjin\"}}"
requests.request("POST", url, data=payload,
                              headers=headers)

# 第三种方式
requests.request("POST", url, data=payload)

输出是

/Users/yeap/Downloads/requests-master/
/Users/yeap/Downloads/requests-master/requests/__init__.pyc
{"data": {"username": "xiangjin", "password": "12345678"}}
{"data": {"password": "12345678","username": "xiangjin"}}
{"data": {"password": "12345678","username": "xiangjin"}}

所以基本断定这三种写法的效果是一样的,当然我推荐第一种;

至今仍看不懂 requests,我不会 py


然后连 charles 代理,一样的请求,只是第三种没有 headers 字段;

  1. 你的参数 dump 了两次,dump 一次就够了
  2. data1 改为: data1 = {"data":{"password": "12345678","username": "xiangjin"}}
23楼 已删除

哎~~~用 requests 的 json 参数本身就会在 header 里加上 {'Content-Type': "application/json"} ,而且 body 里明显是 json 那就用 json 参数啊。data 参数是传 form data 用的。

千千 关闭了讨论 05月04日 18:18
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册