如何发送POST请求?

329

我在网上找到了这个脚本:

import httplib, urllib
params = urllib.urlencode({'number': 12524, 'type': 'issue', 'action': 'show'})
headers = {"Content-type": "application/x-www-form-urlencoded",
            "Accept": "text/plain"}
conn = httplib.HTTPConnection("bugs.python.org")
conn.request("POST", "", params, headers)
response = conn.getresponse()
print response.status, response.reason
302 Found
data = response.read()
data
'Redirecting to <a href="http://bugs.python.org/issue12524">http://bugs.python.org/issue12524</a>'
conn.close()

但我不明白如何在PHP中使用它,也不知道params变量中的所有内容是什么,以及如何使用它。请问能否帮我一下,让我尝试让它工作起来?


1
无论服务器端有什么,POST请求就是POST请求。 - Ondra Žižka
8
这会发送一个POST请求,然后服务器会回复你的POST请求,并返回302(重定向)头文件。实际上出了什么问题? - ddinchev
1
这个脚本看起来不兼容Python3.2。 - jdi
Python3的等效代码可能是:http://pastebin.com/Rx4yfknM - jdi
1
我建议您安装Firefox的“Live HTTP Header”插件,然后在Firefox中打开您的URL,并在“Live HTTP Header”插件中查看URL的“请求/响应”,那么您就会了解代码中的“参数和标头”是如何工作的。 - RanRag
我喜欢原文中“我不明白如何在PHP中使用它”和“我正在使用Python 3.2”这两个陈述的结合。=D - undefined
7个回答

487

如果你真的想使用Python处理HTTP,我强烈推荐Requests: HTTP for Humans。适用于你问题的POST快速入门如下:

>>> import requests
>>> r = requests.post("http://bugs.python.org", data={'number': '12524', 'type': 'issue', 'action': 'show'})
>>> print(r.status_code, r.reason)
200 OK
>>> print(r.text[:300] + '...')

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>
Issue 12524: change httplib docs POST example - Python tracker

</title>
<link rel="shortcut i...
>>> 

我无法得到与您上面相同的结果。我在页面上写了另一个问题编号,然后运行脚本,但是我无法在结果中看到问题编号。 - Efe Büyük
2
如何获取JSON结果? - Yohanim
30
如果您需要发送一个JSON对象,应该这样做:json={'number': 12524...而不是data=... - Seraf
7
为什么答案说“如果你真的想要使用 Python 处理 HTTP”?处理 HTTP 请求是个坏主意吗?如果是,为什么?有人可以解释一下吗? - Jan Pisl
我认为他们是想澄清背景,因为楼主问了一些关于PHP的问题。 - undefined
显示剩余2条评论

188
这是一个没有任何外部pip依赖的解决方案,但只适用于Python 3+(Python 2不适用):
from urllib.parse import urlencode
from urllib.request import Request, urlopen

url = 'https://httpbin.org/post' # Set destination URL here
post_fields = {'foo': 'bar'}     # Set POST fields here

request = Request(url, urlencode(post_fields).encode())
with urlopen(request) as response:
    json = response.read().decode()
print(json)

示例输出:

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "foo": "bar"
  }, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "7", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "Python-urllib/3.3"
  }, 
  "json": null, 
  "origin": "127.0.0.1", 
  "url": "https://httpbin.org/post"
}

39
你无法使用 urllib 来进行 POST 请求(只能用于 GET 请求),相反尝试使用 requests 模块,例如:

示例 1.0:

import requests

base_url="www.server.com"
final_url="/{0}/friendly/{1}/url".format(base_url,any_value_here)

payload = {'number': 2, 'value': 1}
response = requests.post(final_url, data=payload)

print(response.text) #TEXT/HTML
print(response.status_code, response.reason) #HTTP

例子 1.2:

>>> import requests

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

>>> r = requests.post("http://httpbin.org/post", data=payload)
>>> print(r.text)
{
  ...
  "form": {
    "key2": "value2",
    "key1": "value1"
  },
  ...
}

例子 1.3:

>>> import json

>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, data=json.dumps(payload))

6
谢谢。data=json.dumps(payload) 是我使用案例的关键。 - Aram
用“json”替换“data”也可以解决问题。 - avicoder

22

使用requests库通过访问REST API端点来进行GET、POST、PUT或DELETE操作。在url中传递REST API端点URL,在data中传递负载(字典),在headers中传递标头/元数据。

import requests, json

url = "bugs.python.org"

payload = {"number": 12524, 
           "type": "issue", 
           "action": "show"}

header = {"Content-type": "application/x-www-form-urlencoded",
          "Accept": "text/plain"} 

response_decoded_json = requests.post(url, data=payload, headers=header)
response_json = response_decoded_json.json()
 
print(response_json)

3
这段代码存在缩进和头参数名称的问题。 - xilopaint
4
"headers"参数错误,而且这里没有任何JSON。我们应该使用json.dumps(pauload) - Arash Hatami
感谢 @xilopaint 和 ArashHatami 指出语法错误。现已更正。 - Pranzell

6

您的数据字典包含表单输入字段的名称,您只需保留其值以查找结果。 表单视图 标题配置浏览器以检索您声明的数据类型。 使用 requests 库发送 POST 很容易:

import requests

url = "https://bugs.python.org"
data = {'@number': 12524, '@type': 'issue', '@action': 'show'}
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept":"text/plain"}
response = requests.post(url, data=data, headers=headers)

print(response.text)

关于Request对象的更多信息:https://requests.readthedocs.io/en/master/api/


3

如果您不想使用像requests这样需要安装的模块,而且您的使用场景非常基本,那么您可以使用urllib2

urllib2.urlopen(url, body)

请查看此处 https://docs.python.org/2/library/urllib2.html 中的urllib2文档。

2
您可以使用请求库进行POST请求。 如果负载中有JSON字符串,则可以使用json.dumps(payload),这是负载的预期形式。

    import requests, json
    url = "http://bugs.python.org/test"
    payload={
        "data1":1234,'data2':'test'
    }
    headers = {
        'Content-Type': 'application/json'
    }
    response = requests.post(url, headers=headers, data=json.dumps(payload))
    print(response.text , response.status_code)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接