如何使用Python urlopen获取非ascii url?

我需要从具有非ASCII字符的URL中获取数据,但是urllib2.urlopen拒绝打开资源并引发:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u0131' in position 26: ordinal not in range(128)

我知道URL不符合标准,但我没有机会改变它。

使用Python访问包含非ASCII字符的URL指向的资源的方法是什么?

编辑:换句话说,可以/如何urlopen打开一个URL,如:

http://example.org/Ñöñ-ÅŞÇİİ/
最佳答案
严格来说,URI不能包含非ASCII字符;你在那里有一个IRI

将IRI转换为纯ASCII URI:

>地址的主机名部分中的非ASCII字符必须使用基于Punycode的IDNA算法进行编码;
>路径中的非ASCII字符,并且地址的大部分其他部分必须使用UTF-8和%-encoding进行编码,按Ignacio的答案。

所以:

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'

(从技术上讲,在一般情况下这仍然不够好,因为urlparse不会将任何用户分开:在主机名上使用pass @ prefix或:port suffix,只有主机名部分应该是IDNA编码的,使用普通的urllib.quote和.encode(‘idna’)在构建URL时,不必将IRI拉开。)

转载注明原文:如何使用Python urlopen获取非ascii url? - 代码日志