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


107

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

一些有趣的例子:

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

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

然后复制并粘贴它,我看到这个网址

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

这似乎使Firefox(或Safari)正在执行此操作。

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

这很有意义,除了不能用Latin-1编码的东西(例如三点字符)。

如果我输入网址

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

到我的浏览器,然后复制并粘贴,我得到

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

背部。这似乎是这样做的结果

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

这很有意义,因为…无法使用Latin-1进行编码。

但是对于我来说,这还不清楚,浏览器如何知道是使用UTF-8还是Latin-1进行解码。

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

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

可以,所以我不知道浏览器如何确定是使用UTF-8还是Latin-1对其进行解码。

使用我需要处理的特殊字符正确的做法是什么?


19
您的两个示例均编码为UTF-8。肯定不是Latin-1,因为它有3个字节长...
Jakob Borg 2010年

2
%E2%99%A5是UTF-8中“黑心套装”的字节值的十六进制。那颗黑心不属于Latin-1字符集的一部分
Hawkeye Parker

要可靠地确切了解浏览器的编码方式和编码(以及许多其他有用的信息),请使用大多数现代浏览器内置的开发人员工具,或获取免费的HTTP调试器(例如Fiddler)
Hawkeye Parker 2015年

Answers:


65

我将始终以UTF-8编码。在Wikipedia页面上有关百分比编码的内容

通用URI语法规定,提供URI中字符数据表示形式的新URI方案实际上必须表示未经保留的字符集而不进行转换,并且应根据UTF-8将所有其他字符转换为字节,然后对这些值进行百分比编码。RFC 3986于2005年1月引入了此要求。在此日期之前引入的URI方案不受影响。

好像因为过去有其他接受URL编码的方法,浏览器尝试了几种解码URI的方法,但是如果您是进行URL编码的一种,则应使用UTF-8。


8
还应使用UTF-8,因为它是新的IRI标准(RFC 3987,tools.ietf.org / html / rfc3986)所取代的唯一编码,该编码取代了旧的URL标准。
雷米·勒博

3
如果其他人像我一样感到惊讶,@ RemyLebeau的评论中的文本提到RFC3987,但链接指向旧规范3896。正确的URL显然是tools.ietf.org/html/rfc3987
Tripleee

是的,对此感到抱歉。URI由RFC 3986定义,IRI由RFC 3987定义。–
Remy Lebeau

10

一般规则似乎是浏览器根据提供表单的页面的内容类型对表单响应进行编码。这是一种猜测,如果服务器向我们发送“ text / xml; charset = iso-8859-1”,则他们期望响应以相同的格式返回。

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

可悲的事实是AFAIK对于将查询字符串中的值设置为字符或URL中的任何字符都没有解释为标准。至少在查询字符串中有值的情况下,没有理由假设它们必须这样做与字符相对应。

这是一个众所周知的问题,你一定要告诉字符集,你期望它的查询字符串编码为---例如,在Tomcat中,你必须调用request.setEncoding()(或类似的方法),你的服务器架构之前,您调用任何request.getParameter()方法。有关此主题的文档不足可能反映了许多开发人员对此问题的意识不足。(我经常问Java受访者,Reader和InputStream有什么区别,并经常出现空白)


6
RFC 3987(tools.ietf.org/html/rfc3986)定义了一种标准编码-编码不允许以其他方式未经编码的字符时,必须使用UTF-8。
雷米·勒博

8

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


我希望看到协议的更新,以便URL完全支持unicode,而不仅仅是通过百分比编码。
Mathieu J.

1
IRI允许使用未编码的Unicode字符,除非在少数情况下必须对保留字符进行编码。
雷米·勒博2015年

6

IRI不会替代URI,因为在某些情况下(包括HTTP),仅允许URI(有效地是ASCII)。

相反,您可以指定一个IRI,并在网络上连接时将其转换为URI。


0

第一个问题是您的需求是什么?在获取使用廉价编辑器创建的文本和支持多种语言之间,UTF-8编码是一个很好的折衷方案。关于浏览器识别编码,响应(来自Web服务器)应告知浏览器编码。仍然大多数浏览器都会尝试猜测,因为在很多情况下这都是丢失或错误的。他们通过读取一些结果流来进行猜测,以查看是否存在不适合默认编码的字符。当前,所有浏览器(?我都没有检查这个,但是非常接近true)使用utf-8作为默认值。

因此,除非您有充分的理由使用许多其他编码方案之一,否则请使用utf-8。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.