URL 编码 Unicode 字符的正确方法是什么?

我知道非标准的% uxxxx 方案,但这似乎不是一个明智的选择,因为该方案已被 W3C 拒绝。

一些有趣的例子:

心形角色。 如果我在浏览器中输入以下内容:

http://www.google.com/search?q=♥

然后复制粘贴,我看到这个 URL

http://www.google.com/search?q=%E2%99%A5

看起来像是 Firefox (或 Safari)在做这件事。

urllib.quote_plus(x.encode("latin-1"))
'%E2%99%A5'

which makes sense, except for things that can't be encoded in Latin-1, like the triple dot character.

如果我输入 URL

http://www.google.com/search?q=…

然后复制粘贴,我得到

http://www.google.com/search?q=%E2%80%A6

回来。这似乎是做的结果

urllib.quote_plus(x.encode("utf-8"))

这就说得通了,因为... 不能用拉丁文编码。

But then its not clear to me how the browser knows whether to decode with UTF-8 or Latin-1.

由于这似乎是模棱两可的:

In [67]: u"…".encode('utf-8').decode('latin-1')
Out[67]: u'\xc3\xa2\xc2\x80\xc2\xa6'

工作,所以我不知道浏览器如何计算出是否解码与 UTF-8或拉丁文 -1。

怎样处理我需要处理的特殊人物才是正确的呢?

118923 次浏览

我总是用 UTF-8编码:

The generic URI syntax mandates that new URI schemes that provide for the representation of character data in a URI must, in effect, represent characters from the unreserved set without translation, and should convert all other characters to bytes according to UTF-8, and then percent-encode those values. This requirement was introduced in January 2005 with the publication of RFC 3986. URI schemes introduced before this date are not affected.

似乎是因为过去有其他被接受的 URL 编码方法,浏览器尝试了几种方法来解码一个 URI,但是如果你是那个进行编码的人,你应该使用 UTF-8。

第一个问题是你需要什么?UTF-8编码在使用廉价编辑器创建文本和支持多种语言之间是一个很好的折衷方案。关于浏览器识别编码,响应(来自 web 服务器)应该告诉浏览器编码。尽管如此,大多数浏览器还是会尝试猜测,因为在许多情况下,这要么是缺失的,要么是错误的。他们通过读取一定数量的结果流来猜测是否存在不适合默认编码的字符。目前所有浏览器(?我没有检查这个,但它非常接近真)使用 utf-8作为默认值。

因此,使用 utf-8,除非您有令人信服的理由使用众多其他编码模式之一。

一般规则似乎是,浏览器根据表单所来自的页面的内容类型对表单响应进行编码。这是一种猜测,如果服务器向我们发送“ text/xml; charset = iso-8859-1”,那么它们希望得到相同格式的响应。

如果您只是在 URL 栏中输入一个 URL,那么浏览器没有基本页面可以处理,因此只能进行猜测。因此在这种情况下,它似乎一直在执行 utf-8(因为两个输入都产生了三个八位组形式的值)。

可悲的事实是,AFAIK 对于查询字符串或 URL 中的任何字符应该被解释为什么字符集没有标准。至少在查询字符串中的值的情况下,没有理由假设它们必须 对应于字符。

It's a known problem that you have to tell your server framework which character set you expect the query string to be encoded as--- for instance, in Tomcat, you have to call request.setEncoding() (or some similar method) before you call any of the request.getParameter() methods. The dearth of documentation on this subject probably reflects the lack of awareness of the problem amongst many developers. (I regularly ask Java interviewees what the difference between a Reader and an InputStream is, and regularly get blank looks)

IRI (RFC 3987)是取代 URI/URL (RFC 3986及以前的)标准的最新标准。URI/URL 本身不支持 Unicode (好吧,RFC 3986为未来基于 URI/URL 的协议添加了支持它的条款,但是不更新过去的 RFC)。“% uXXXX”方案是在某些情况下允许使用 Unicode 的非标准扩展,但并非所有人都普遍实现。另一方面,IRI 完全支持 Unicode,并要求在百分比编码之前将文本编码为 UTF-8。

IRI 不能替换 URI,因为在某些上下文(包括 HTTP)中只允许 URI (实际上是 ASCII)。

相反,您指定一个 IRI,它在连接时被转换成一个 URI。