3

假设用户输入了某个资源的地址,我们需要将其翻译为:

<a href="valid URI here">human readable form</a>

HTML4 规范参考RFC 3986,它只允许主机部分中的 ASCII 字母数字字符和破折号,而其他部分中的所有非 ASCII 字符都应进行百分比编码。这就是我想在 href 属性中添加的内容,以使链接在所有浏览器中都能正常工作。IDN 应使用Punycode进行编码。

HTML5 草案是指RFC 3987,它还允许在主机部分中使用百分比编码的 unicode 字符,并在主机和其他部分中使用大量 unicode 子集,而无需对其进行编码。用户可以以任何这些形式输入地址。为了提供人类可读的形式,我需要解码所有可打印的字符。请注意,地址的某些部分可能与有效的 UTF-8 序列不对应,通常在目标站点使用其他字符编码时。

我想得到的一个例子:

<a href="http://xn--80aswg.xn--p1ai/%D0%BF%D1%83%D1%82%D1%8C?%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81">
http://сайт.рф/путь?запрос</a>

是否有任何工具可以解决这些任务?我对 Python 和 JavaScript 库特别感兴趣。

更新:我知道有一种方法可以在 Python 和 JavaScript 中进行百分比和 Punycode(没有适当的规范化,但我可以忍受)编码/解码。整个任务需要更多的工作,并且存在一些陷阱(某些字符应始终编码或从不编码,具体取决于上下文)。我想知道是否有准备好使用库来解决整个问题,因为它似乎很常见并且现代浏览器已经进行了此类转换(尝试http://%D1%81%D0%B0%D0%B9%D1%82.%D1%80%D1%84/ 在 Google Chrome 中输入,它将被替换为http://сайт.рф/,但Host: xn--80aswg.xn--p1ai在 HTTP 请求中使用)。

更新 2:Vinay Sajip指出 Werkzeug 具有正确处理大多数情况的 iri_to_uri 和 uri_to_iri 函数。到目前为止,我只发现了两种失败的情况:百分比编码的主机(很容易修复)和无效的 utf-8 序列(做得好有点棘手,但应该不是问题)。

我仍在寻找 JavaScript 中的库。写起来并不难,但我宁愿避免发明轮子。

4

1 回答 1

2

如果我理解正确,那么您可以使用 Python 中包含的电池:

# -*- coding: utf-8 -*-

import urllib
import urlparse

URL1 = u'http://сайт.рф/путь?запрос'
URL2 = 'http://%D1%81%D0%B0%D0%B9%D1%82.%D1%80%D1%84/'

def to_idn(url):
    parts = list(urlparse.urlparse(url))
    parts[1] = parts[1].encode('idna')
    parts[2:] = [urllib.quote(s.encode('utf-8')) for s in parts[2:]]
    return urlparse.urlunparse(parts)

def from_idn(url):
    return urllib.unquote(url)

print to_idn(URL1)
print from_idn(URL2)
print to_idn(from_idn(URL2).decode('utf-8'))

哪个打印

http://xn--80aswg.xn--p1ai/%D0%BF%D1%83%D1%82%D1%8C?%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81
http://сайт.рф/
http://xn--80aswg.xn--p1ai/

这看起来像你想要的。我不确定你的意思是什么特殊情况 - 也许你可以举一些你所指的陷阱的例子?

更新:我只记得,Werkzeug 在 0.6 及更高版本中具有iri_to_uriuri_to_iri功能(链接指向文档的相关部分)。

进一步更新:抱歉,我没有注意到您正在寻找 JavaScript 实现以及 Python 实现。punycode 的现有公共领域 Javascript 实现在这里。不过,我不能保证。当然,您也可以使用内置的 JavaScript encodeURI/ decodeURIAPI。

于 2010-05-14T15:31:16.993 回答