10

我正在尝试在 Python 脚本中进行一些自动化操作,但遇到了问题。我正在尝试对服务器进行 POST。

url = 'http://www.example.com'
params = {'arg0': 'value', 'arg1': '+value'}

f = urllib.urlopen(url, urllib.urlencode(params))
print f.read()

我已经对等效的浏览器操作进行了wireshark 捕获,其中第二个参数arg1作为 传递+value,但是当我使用Python 执行此操作时,它+会更改为%2B,即

Line-based text data: application/x-www-form-urlencoded
arg0=value&arg1=%2Bvalue

什么时候应该:

Line-based text data: application/x-www-form-urlencoded
arg0=value&arg1=+value

我也使用了 Requests 模块,它似乎做同样的事情。

url = 'http://www.example.com'
params = {'arg0': 'value', 'arg1': '+value'}

f = requests.post(url, params)

当您遇到与“+”相关的问题时,Google 不是您的朋友,因为它似乎是其他很多事情的全部。

4

2 回答 2

11

引用 GET 或 POST 数据时,该+字符是空格的正确编码。因此,文字+字符也需要转义,以免被解码为另一端的空格。请参阅 RFC 2396,第 2.2节,第 3.4 节HTML 规范,第 3.4application/x-www-form-urlencoded

控件名称和值被转义。空格字符被 `+' 替换,然后保留字符被转义,如[RFC1738],第 2.2 节所述。

如果您将数据发布到不将+字符解码为空格而是将此类数据视为文字加号的应用程序,则需要使用urllib.quote函数自己对参数进行编码,并指定+不编码字符:

import urllib
def urlencode_withoutplus(query):
    if hasattr(query, 'items'):
        query = query.items()
    l = []
    for k, v in query:
        k = urllib.quote(str(k), safe=' /+')
        v = urllib.quote(str(v), safe=' /+')
        l.append(k + '=' + v)
    return '&'.join(l)

演示:

>>> urlencode_withoutplus({'arg0': 'value', 'arg1': '+value'})
'arg0=value&arg1=+value'

使用时requests,可以简单地将上述函数的结果作为data值传入,但这种情况下需要手动设置内容类型:

requests.post(url, urlencode_withoutplus(query),
    headers={'Content-Type': 'application/x-www-form-urlencoded'})
于 2012-09-21T09:45:15.210 回答
5
urllib2.quote(' ')     # '%20'
urllib2.unquote('%20') # ' '

那么为什么不直接取消引用参数部分:

f = urllib.urlopen(url, urllib.unquote(urllib.urlencode(params)))
于 2012-09-21T09:54:14.333 回答