为什么 Url 解码不将 + 转换为 space?

Why doesn't Url Decode convert + to space?

为什么 + 没有转换为空格:

>>> import urllib
>>> url = 'Q=Who+am+I%3F'
>>> urllib.unquote(url)
'Q=Who+am+I?'
>>>

有两种变体; urllib.unqoute()urllib.unquote_plus()。使用后者:

>>> import urllib
>>> url = 'Q=Who+am+I%3F'
>>> urllib.unquote_plus(url)
'Q=Who am I?'

那是因为 URL 引用有两种变体;一个用于 URL 路径段,一个用于 URL 查询参数;后者使用 不同的规范 。见 Wikipedia:

When data that has been entered into HTML forms is submitted, the form field names and values are encoded and sent to the server in an HTTP request message using method GET or POST, or, historically, via email. The encoding used by default is based on a very early version of the general URI percent-encoding rules, with a number of modifications such as newline normalization and replacing spaces with "+" instead of "%20".

所以 forms 在 GET 或 POST 请求中使用 application/x-www-form-urlencoded mime 类型使用稍微不同的规则,其中空格被编码为 +,但是当在 URL 中编码字符时,使用 %20。解码时,您需要选择正确的变体。您有表单数据(来自 URL 的查询部分),因此您需要使用 unquote_plus().

现在,如果您要解析查询字符串,您可能需要使用 urlparse.parse_qs() or urlparse.parse_qsl() 函数;这些不仅会使用正确的 unquote*() 函数,还会将参数解析为字典或键值对列表:

>>> import urlparse
>>> urlparse.parse_qs(url)
{'Q': ['Who am I?']}
>>> urlparse.parse_qsl(url)
[('Q', 'Who am I?')]