【问题标题】:Python url encode/decode - Convert % escaped hexadecimal digits into stringPython url 编码/解码 - 将 % 转义的十六进制数字转换为字符串
【发布时间】:2016-08-24 03:23:34
【问题描述】:

例如,如果我有一个编码字符串为:

url='locality=Norwood&address=138+The+Parade&region=SA&country=AU&name=Pav%C3%A9+cafe&postalCode=5067'

name 参数包含字符 %C3%A9,实际上暗示字符 é。

因此,我希望输出为:

new_url='locality=Norwood&address=138+The+Parade&region=SA&country=AU&name=Pavé+cafe&postalCode=5067'

我在 Python 终端上尝试了以下步骤:

>>> import urllib2
>>> url='locality=Norwood&address=138+The+Parade&region=SA&country=AU&name=Pav%C3%A9+cafe&postalCode=5067'
>>> new_url=urllib2.unquote(url).decode('utf8')
>>> print new_url
locality=Norwood&address=138+The+Parade&region=SA&country=AU&name=Pavé+cafe&postalCode=5067
>>>

但是,当我在 Python 脚本 中尝试相同的操作并以 myscript.py 运行时,我得到以下堆栈跟踪:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 88: ordinal not in range(128)

我使用的是Python 2.6.6,由于工作原因无法切换到其他版本。

我该如何克服这个错误?

非常感谢任何帮助。提前致谢!

######################################################

编辑

我意识到我得到了上述预期的输出。

但是,我想将new_url中的参数转换成字典如下。这样做时,我无法在我的名称参数中保留特殊字符“é”。

print new_url
params_list = new_url.split("&")
print(params_list)
params_dict={}
for p in params_list:
   temp = p.split("=")
   params_dict[temp[0]] = temp[1]
print(params_dict)

输出:

new_url

locality=Norwood&address=138+The+Parade&region=SA&country=AU&name=Pavé+cafe&postalCode=5067

params_list

[u'locality=Norwood', u'address=138+The+Parade', u'region=SA', u'country=AU', u'name=Pav\xe9+cafe', u'postalCode =5067']

params_dict

{u'name': u'Pav\xe9+cafe', u'locality': u'Norwood', u'country': u'AU', u'region': u'SA', u'地址': u'138+The+Parade', u'邮编': u'5067'}

基本上...名称现在是“Pav\xe9+cafe”,而不是必需的“Pavé”。

我怎样才能在我的 params_dict 中仍然保留相同的特殊字符?

【问题讨论】:

  • 我无法重现您的错误。您确定在终端和脚本中使用相同的代码吗?
  • @machineyearning 你是对的。请检查我的编辑是否存在实际问题。

标签: python python-2.6 python-unicode


【解决方案1】:

这实际上是由于__repr____str__ 之间的差异造成的。打印 unicode 字符串时,使用 __str__ 并导致您在打印 new_url 时看到的 é。但是,当打印列表或字典时,将使用__repr__,它对列表和字典中的每个对象使用__repr__。如果您单独打印这些项目,它们会按照您的需要打印。

# -*- coding: utf-8 -*-
new_url = u'name=Pavé+cafe&postalCode=5067'
print(new_url)  # name=Pavé+cafe&postalCode=5067

params_list = [s for s in new_url.split("&")]
print(params_list)  # [u'name=Pav\xe9+cafe', u'postalCode=5067']
print(params_list[0])  # name=Pavé+cafe
print(params_list[1])  # postalCode=5067

params_dict = {}
for p in params_list:
    temp = p.split("=")
    params_dict[temp[0]] = temp[1]
print(params_dict)  # {u'postalCode': u'5067', u'name': u'Pav\xe9+cafe'}
print(params_dict.values()[0])  # 5067
print(params_dict.values()[1])  # Pavé+cafe

打印列表和字典的一种方法是获取它们的字符串表示形式,然后使用unicode-escape对其进行解码:

print(str(params_list).decode('unicode-escape'))  # [u'name=Pavé+cafe', u'postalCode=5067']
print(str(params_dict).decode('unicode-escape'))  # {u'postalCode': u'5067', u'name': u'Pavé+cafe'}

注意:这只是 Python 2 中的一个问题。Python 3 会按照您的预期打印字符。此外,您可能需要查看 urlparse 来解析您的 URL,而不是手动进行。

import urlparse
new_url = u'name=Pavé+cafe&postalCode=5067'
print dict(urlparse.parse_qsl(new_url))  # {u'postalCode': u'5067', u'name': u'Pav\xe9 cafe'}

【讨论】:

  • 我认为添加 Python 已经具有解析查询字符串的函数也很有用:docs.python.org/3/library/…
  • OP 使用的是 Python 2.6,但我会从那里添加相关库。
  • @Karin 感谢您提供有关 reprstr 的信息。理想情况下,我需要返回字典并将其保存到文件中,而不是打印。我试过了 - 但文件仍然包含“Pav\xe9+cafe”而不是“Pavé+cafe”。而且我真的不想指定要使用 params_dict.values()[0]、params_dict.values()[1] 等保存的字典值,因为我想将整个字典保存在一个文件中......
  • 更新了答案以包含一种以所需格式打印出列表和字典的方法。
猜你喜欢
  • 1970-01-01
  • 2014-03-10
  • 1970-01-01
  • 2015-01-06
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
  • 2016-09-08
  • 1970-01-01
相关资源
最近更新 更多