擅长:python、mysql、java
<p>严格地说,uri不能包含非ASCII字符;您所拥有的是一个<a href="http://en.wikipedia.org/wiki/Internationalized_Resource_Identifier">IRI</a>。</p>
<p>要将IRI转换为纯ASCII URI,请执行以下操作:</p>
<ul>
<li><p>地址主机名部分的非ASCII字符必须使用基于<a href="http://en.wikipedia.org/wiki/Punycode">Punycode</a>的IDNA算法进行编码;</p></li>
<li><p>根据Ignacio的回答,路径中的非ASCII字符以及地址的大多数其他部分必须使用UTF-8和%编码。</p></li>
</ul>
<p>所以:</p>
<pre><code>import re, urlparse
def urlEncodeNonAscii(b):
return re.sub('[\x80-\xFF]', lambda c: '%%%02x' % ord(c.group(0)), b)
def iriToUri(iri):
parts= urlparse.urlparse(iri)
return urlparse.urlunparse(
part.encode('idna') if parti==1 else urlEncodeNonAscii(part.encode('utf-8'))
for parti, part in enumerate(parts)
)
>>> iriToUri(u'http://www.a\u0131b.com/a\u0131b')
'http://www.xn--ab-hpa.com/a%c4%b1b'
</code></pre>
<p>(从技术上讲,在一般情况下,这仍然不够好,因为<code>urlparse</code>没有拆分主机名上的任何<code>user:pass@</code>前缀或<code>:port</code>后缀。只有主机名部分应该是IDNA编码的。在构建URL时,使用普通的<code>urllib.quote</code>和<code>.encode('idna')</code>编码要比分离IRI容易得多。)</p>