【问题标题】:Making a POST call instead of GET using urllib2使用 urllib2 进行 POST 调用而不是 GET
【发布时间】: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)。

【问题讨论】:

标签: python urllib2 urllib


【解决方案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

这种方式允许您扩展为发出PUTDELETEHEADOPTIONS 请求,只需替换方法的值,甚至将其包装在一个函数中。根据您要执行的操作,您可能还需要不同的 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_servicehttp://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
      猜你喜欢
      • 2011-08-04
      • 2010-09-07
      • 1970-01-01
      • 2016-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多