使用POST和urllib2访问Web API

6 投票
3 回答
22937 浏览
提问于 2025-04-16 07:09

我正在尝试使用POST方法访问一个网络API。我可以用GET方法成功访问,但API的拥有者告诉我,某些功能只有在使用POST时才能正常工作。不幸的是,我似乎无法让POST方法正常工作。

这是用GET方法可以成功的代码:

API_URL = "http://example.com/api/"

def call_api(method, **kwargs):
    url = API_URL + method
    if kwargs:
        url += '?' + urllib.urlencode(kwargs)
    req = urllib2.Request(url)
    auth = 'Basic ' + base64.urlsafe_b64encode("%s:%s" % (USER, PASS))
    req.add_header('Authorization', auth)
    return urllib2.urlopen(req)

这是用POST方法不成功的代码(导致HTTP 400错误):

API_URL = "http://example.com/api/"

def call_api(method, **kwargs):
    url = API_URL + method
    data=''
    if kwargs:
        data=urllib.urlencode(kwargs)
    req = urllib2.Request(url, data)
    auth = 'Basic ' + base64.urlsafe_b64encode("%s:%s" % (USER, PASS))
    req.add_header('Authorization', auth)
    return urllib2.urlopen(req)

有没有人能看出POST代码中有什么根本性的错误?我之前从来没有做过POST调用,但我读过的资料似乎都表明我的代码是合理的。如果我使用POST,关于授权的add_header部分是不是有其他的写法?

3 个回答

1

我也遇到过同样的问题。我想用HTTP的POST方法发送数据,但在用dir(req)查看后,发现有个叫get_method的东西,但没有set_method。然后我还发现有个属性叫data,所以我试了试这个:

>>> req.data={"todototry":"123456"}
>>> req.get_method()
'POST'
>>>

谢谢@Sneeu。

2

正如@sneeu上面提到的,把要发送的数据添加到请求中,就把请求从GET变成了POST。

不过,这里还是假设API期望在POST的内容中接收到的是表单编码的数据。我最近接触的很多API其实期待的是其他格式的数据(最常见的是XML或JSON)。

你能确认一下那个API希望接收到什么样的数据吗?

10

使用 urllib2 时,你需要把数据放到 POST 请求的主体里面:

def call_api(method, **kwargs):
    url = API_URL + method
    req = urllib2.Request(url)

    if kwargs:
        req.add_data(urllib.urlencode(kwargs))

    auth = 'Basic ' + base64.urlsafe_b64encode("%s:%s" % (USER, PASS))
    req.add_header('Authorization', auth)

    # req.get_method() -> 'POST'

    return urllib2.urlopen(req)

撰写回答