Python相当于curls--form:创建包含数据的多部分表单数据post请求;表格「;参数

Python相当于curls--form:创建包含数据的多部分表单数据post请求;表格「;参数,python,post,curl,python-requests,multipartform-data,Python,Post,Curl,Python Requests,Multipartform Data,我正在寻找与此curl命令等效的python: curl --referer "https://myreferer" --insecure --form "myparam=1234" https://myurl 这将导致以下请求(取自httpbin.org/post): 如您所见,数据“myparam”以“form”参数的形式传递 我试图通过pythonsrequests模块构建这样一个请求,最终得到了以下代码: import requests payload={'myparam':'123

我正在寻找与此curl命令等效的python:

 curl --referer "https://myreferer" --insecure --form "myparam=1234" https://myurl
这将导致以下请求(取自httpbin.org/post):

如您所见,数据“myparam”以“form”参数的形式传递

我试图通过pythons
requests
模块构建这样一个请求,最终得到了以下代码:

import requests
payload={'myparam':'1234'}
url="http://httpbin.org/post"
headers={'User-Agent': 'Mozilla 5.0','referer':'https://myreferer'}
r = requests.post(url, files=payload, headers=headers,verify=False)
但是请求库将数据放在“files”参数中。因此,生成的请求如下所示:

{
  "args": {}, 
  "data": "", 
  "files": {
    "pws": "1234"
  }, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "143", 
    "Content-Type": "multipart/form-data; boundary=a878ad29e28d47ffb00e0631319ed0e2", 
    "Host": "httpbin.org", 
    "Referer": "https://myreferer", 
    "User-Agent": "Mozilla 5.0", 
    "X-Request-Id": "60f5d65e-789a-47fe-bba3-dab88f9bbb65"
...
因此,数据被传递到错误的位置,即在“files”参数中,这使得Apache出现“501 Not Implemented”响应

有人能建议如何在Python中执行这样的请求吗?(我知道我可以将curl作为一个子流程调用,但由于我想执行许多这样的请求,所以我希望有一个纯python的解决方案(希望性能更好)

而且,正如您可能已经注意到的,我还需要接受一个自签名证书并发送一个referer头

如果有人能提出一个简单的方法来解决这个问题,我会很高兴

谢谢

编辑:我已经尝试使用requests.post命令的“data”-param,但这会导致不同的内容类型标题(application/x-www-form-urlencoded)。请注意curl请求的content-type头

编辑:我可能需要的是通过requests.post命令的headers参数简单地发送正确的内容类型header、multipart/form数据。但我还必须计算“边界”——多部分/表单数据头字符串的一部分。我想一定有比手动构造标题和计算边界更简单的方法。

对于
文件
使用
类文件对象
会产生
多部分/表单数据
内容类型 让我们准备好通话所需的一切,从“常规”材料开始:

强制
请求
使用“多部分/表单数据”的诀窍是至少给它一个类似 反对

buff
现在是我们可以作为
files
参数的值传入的类似文件的对象

>>> req = requests.post(url, data=data, headers=headers, stream=True, files=buff)
>>> print req.text
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "myparam": "1234"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "130", 
    "Content-Type": "multipart/form-data; boundary=0b3bbec1f5c844a1b7377aacfe701f02", 
    "Host": "httpbin.org", 
    "Referer": "https://myreferer", 
    "User-Agent": "Mozilla 5.0", 
    "X-Request-Id": "988a0467-1c32-45aa-a75c-fba5aa8d632e"
  }, 
  "json": null, 
  "origin": "85.160.45.204", 
  "url": "http://httpbin.org/post"
}
如果要使用自签名证书与https进行通信,请使用
verify=False

>>> req = requests.post(url, data=data, headers=headers, stream=True, files=buff, verify=False)
请求的帮助。request
还注意到,
verify
的值可能是“CA_BUNDLE path”,因此 可以显式确保服务器正在使用您期望的自签名证书。但是
我从未尝试过这种方法。

不幸的是,如果您不想将数据作为文件发送,则必须使用第三方库--。一旦您
pip安装请求toolbelt
,您就可以执行以下操作

from requests_toolbelt import MultipartEncoder
import requests

payload = MultipartEncoder({'myparam': '1234'})
r = requests.post(url, data=payload, headers={'Content-Type': payload.content_type})
当然,您也可以设置其他标题,这只是根据您的需要使用toolbelt的一个简单示例

如果要验证证书,可以将带有完整路径的字符串传递到PEM文件,例如

r = requests.get('https://somesite.com', verify='/Users/mhelwig/certificate.pem')

不,这不是解决方案,因为它会导致不同的内容类型标题。我已经试过了,也许我应该提一下。我将编辑我的帖子。@MichaelHelwig检查我修改的答案。现在它使用
multipart/formdata
内容类型。诀窍是传入一些类似文件的对象。考虑到这是未记录的(我可以保证是无意的)行为,我不会依赖它,因为它很可能会在未来的请求发布中中断。如果它真的坏了,错误报告可能会被认为是无效的。这也是一个有效的工作答案,谢谢!我不知道请求工具带,它似乎对这类东西很有帮助。@sigmavirus24如我的回答所示,你可以用空缓冲区欺骗
请求。总之,+1用于指向nice软件包
请求_toolbelt
,以及显示
验证
与*.pem文件路径的使用。
>>> req = requests.post(url, data=data, headers=headers, stream=True, files=buff, verify=False)
from requests_toolbelt import MultipartEncoder
import requests

payload = MultipartEncoder({'myparam': '1234'})
r = requests.post(url, data=payload, headers={'Content-Type': payload.content_type})
r = requests.get('https://somesite.com', verify='/Users/mhelwig/certificate.pem')