Python:打开一个带重音的URL

Python: open a URL with accent

在 Python 2.7 中,我想打开一个包含重音符号的 URL(link 本身 ,而不是要转到的页面它指向)。如果我使用以下内容:

#!/usr/bin/env Python
# -*- coding: utf-8 -*-

import urllib2


test = "https://www.notifymydevice.com/push?ApiKey=K6HGFJJCCQE04G29OHSRBIXI&PushTitle=Les%20accents%20:%20éèçà&PushText=Messages%20éèçà&"

urllib2.urlopen(test)

我的口音变成了乱码(Ã、¨、© 等,而不是我期望的 éèà)。

我已经搜索过这类问题,所以我尝试使用 urllib2.urlopen(test.encode('utf-8')) 但是 Python 在这种情况下会抛出错误:

File "test.py", line 10, in urllib2.urlopen(test.encode('utf8')) UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 98: ordinal not in range(128)

在字符串前加上 u。我在 repl 中使用 this

尝试没有错误
import urllib
test = u'https://www.notifymydevice.com/push?ApiKey=K6HGFJJCCQE04G29OHSRBIXI&PushTitle=Les%20accents%20:%20éèçà&PushText=Messages%20éèçà&'
urllib.urlopen(test.encode("UTF-8"))

u 前缀用于 unicode strings

如果您在 str 上调用 encode,Python 必须先将其解码为 unicode,以便它可以将该 Unicode 编码为 UTF-8。为了解码它,它必须猜测你使用的是什么编码,因为你没有告诉它。所以它猜测 'ascii'(实际上,它猜测 sys.getdefaultencoding() 所说的任何内容,但通常是 'ascii'),但失败了。

好歹这里有两个可能的问题,有不同的解决方法。因此,在尝试修复它之前,您需要弄清楚自己拥有的是哪一个。


尝试打印出字符串的各个字节——或者,更简单地说,repr:

print repr(test)
  • 如果 é 显示为 \xc3\xa9,则为 UTF-8。
  • 如果它显示为 \xe9,则它是 Latin-1(或 cp1252 或其他与 Latin-1 兼容的东西)。
  • 如果它显示为其他内容,则它是不同的字符集,您必须找出是哪个字符集。

如果您提供 Python Latin-1 源并告诉它它是 UTF-8,它不会抱怨,但这意味着您将在您认为的位置发送 Latin-1 字节'重新发送 UTF-8 字符,你会到处都是 mojibake。

解决方法是在文本编辑器中将源代码保存为 UTF-8。


如果它已经 UTF-8,那么问题是服务器不期望 URL 是 UTF-8。

URL 标准不强制要求(%-编码)非 ASCII 字节有任何特定含义;任何服务器都可以对它们做任何想做的事。而且,如果您正在与处理诸如 cp1252 之类的字节的服务器通信,但您发送的是 UTF-8,那么您将得到 mojibake。

如果您控制服务器,则解决此问题的方法是重新配置服务器以处理 UTF-8,或者如果您不控制,则以服务器需要的字符集发送字符串。