使用urllib2发起POST请求而非GET请求

61 投票
7 回答
196724 浏览
提问于 2025-04-16 19:33

网上有很多关于urllib2和POST请求的资料,但我遇到了一个问题。

我想向一个服务发送一个简单的POST请求:

url = 'http://myserver/post_service'
data = urllib.urlencode({'name' : 'joe',
                         'age'  : '10'})
content = urllib2.urlopen(url=url, data=data).read()
print content

我查看了服务器的日志,发现它显示我在进行GET请求,而我其实是把数据传给urlopen的。

这个库抛出了一个404错误(未找到),这对于GET请求来说是正确的,但POST请求处理得很好(我也在尝试通过HTML表单发送POST请求)。

7 个回答

11

可以看看这个urllib 缺失手册,里面有很多有用的信息。这里有一个简单的POST请求的例子。

url = 'http://myserver/post_service'
data = urllib.urlencode({'name' : 'joe', 'age'  : '10'})
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
print response.read()

正如@Michael Kent所建议的,可以考虑使用requests库,它非常好用。

编辑:不过,我不太明白为什么把数据传给urlopen()却没有产生POST请求;理论上应该会。我怀疑是你的服务器在重定向,或者出现了其他问题。

49

分步骤来做,并且修改对象,像这样:

# make a string with the request type in it:
method = "POST"
# create a handler. you can specify different handlers here (file uploads etc)
# but we go for the default
handler = urllib2.HTTPHandler()
# create an openerdirector instance
opener = urllib2.build_opener(handler)
# build a request
data = urllib.urlencode(dictionary_of_POST_fields_or_None)
request = urllib2.Request(url, data=data)
# add any other information you want
request.add_header("Content-Type",'application/json')
# overload the get method function with a small anonymous function...
request.get_method = lambda: method
# try it; don't forget to catch the result
try:
    connection = opener.open(request)
except urllib2.HTTPError,e:
    connection = e

# check. Substitute with appropriate HTTP code.
if connection.code == 200:
    data = connection.read()
else:
    # handle the error case. connection.read() will still contain data
    # if any was returned, but it probably won't be of any use

这样做可以让你轻松扩展到其他请求,比如 PUTDELETEHEADOPTIONS,只需要替换方法的值,或者把它封装成一个函数。根据你想要实现的功能,你可能还需要不同的HTTP处理器,比如用于多文件上传的处理器。

48

这个问题可能之前有人回答过:Python URLLib / URLLib2 POST.

你的服务器可能正在把请求从 http://myserver/post_service 重定向到 http://myserver/post_service/。当发生302重定向时,请求的类型会从POST变成GET(详细信息可以查看 问题1401)。你可以试着把 url 改成 http://myserver/post_service/

撰写回答