使用 urllib2 进行 POST 调用而不是 GET
Posted
技术标签:
【中文标题】使用 urllib2 进行 POST 调用而不是 GET【英文标题】:Making a POST call instead of GET using urllib2 【发布时间】:2011-09-14 23:09:13 【问题描述】:关于 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)。
【问题讨论】:
顺便说一句,服务器应该返回 405。 @IgnacioVazquez-Abrams 这个文档说 405 不适合 GET 和 HEAD 请求...developer.mozilla.org/en-US/docs/Web/HTTP/… 【参考方案1】:requests 模块可以减轻您的痛苦。
url = 'http://myserver/post_service'
data = dict(name='joe', age='10')
r = requests.post(url, data=data, allow_redirects=True)
print r.content
【讨论】:
OP 询问“使用 urllib2”? 虽然可行,但 OP 说想使用 urllib2 而不是 requests,这是一个 3rd 方库。使用 3rd 方库可能会有所帮助,但也会使代码不可移植,这可能是 OP 最初关心的问题。 确实,这对我的情况绝对没用。 一句话:Poratbility
一个非常有趣的单词选择【参考方案2】:
分阶段进行,并修改对象,如下所示:
# 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
这种方式允许您扩展为发出PUT
、DELETE
、HEAD
和OPTIONS
请求,只需替换方法的值,甚至将其包装在一个函数中。根据您要执行的操作,您可能还需要不同的 HTTP 处理程序,例如用于多文件上传。
【讨论】:
这读起来太可怕了;很难找到代码。 我认为查看详细方式很有用,也许不是大多数情况,但有时需要调整一些特殊的东西。【参考方案3】:阅读urllib Missing Manual。下面是一个简单的 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 请求;这应该。我怀疑您的服务器正在重定向或行为异常。
【讨论】:
谢谢@Rob,我尝试了你的建议,但也没有用。原来我在 URL 中遗漏了一个斜杠。 @Akim 没问题。好想法@Gregg :) 您也可以将数据传递给 GET 请求,urllib2.urlopen 无法从这个上下文中知道您想要什么,这就是原因。 刚刚测试过这个,效果很好。谢谢@RobCowie!【参考方案4】:试试这个:
url = 'http://myserver/post_service'
data = urllib.urlencode('name' : 'joe',
'age' : '10')
req = urllib2.Request(url=url,data=data)
content = urllib2.urlopen(req).read()
print content
【讨论】:
【参考方案5】:这可能之前已经回答过:Python URLLib / URLLib2 POST。
您的服务器可能正在执行从 http://myserver/post_service
到 http://myserver/post_service/
的 302 重定向。执行 302 重定向时,请求从 POST 变为 GET(请参阅Issue 1401)。尝试将url
更改为http://myserver/post_service/
。
【讨论】:
是的!我在 URL 中缺少一个斜杠。我正在投票并标记为已接受。谢谢!!【参考方案6】:如果您提供数据参数(就像您正在做的那样),它应该发送 POST:
来自文档: “提供数据参数时,HTTP 请求将是 POST 而不是 GET”
所以.. 添加一些调试输出以查看客户端发生了什么。
你可以修改你的代码,然后再试一次:
import urllib
import urllib2
url = 'http://myserver/post_service'
opener = urllib2.build_opener(urllib2.HTTPHandler(debuglevel=1))
data = urllib.urlencode('name' : 'joe',
'age' : '10')
content = opener.open(url, data=data).read()
【讨论】:
【参考方案7】:url="https://myserver/post_service"
data["name"] = "joe"
data["age"] = "20"
data_encoded = urllib2.urlencode(data)
print urllib2.urlopen(url + "?" + data_encoded).read()
这可能会有所帮助
【讨论】:
这是一个 GET 请求,而不是一个 POST以上是关于使用 urllib2 进行 POST 调用而不是 GET的主要内容,如果未能解决你的问题,请参考以下文章
将类型切换为 POST 而不是 GET 后 JSON 调用不起作用
verilog中,对一个模块的多次调用,比如前一个调用还没有结束的情况下,就再次调用,后者是不是会覆盖前者?
如何将 emacs 设置为在 verilog 模式下使用 3 个空格而不是制表符?