标签为空或过长 - python urllib2
我遇到了一个奇怪的情况:
我在用curl命令请求网址,像这样:
def check_urlstatus(url):
h = httplib2.Http()
try:
resp = h.request("http://" + url, 'HEAD')
if int(resp[0]['status']) < 400:
return 'ok'
else:
return 'bad'
except httplib2.ServerNotFoundError:
return 'bad'
如果我用这个来测试:
if check_urlstatus('.f.de') == "bad": #<--- error happening here
#..
#..
它显示的是:
UnicodeError: label empty or too long
我这里到底出了什么问题呢?
补充说明:这是我用idna时的错误追踪信息。我猜,它试图通过.
来分割输入,而在这种情况下,第一个部分是空的,也就是在第一个.
之前的位置。
1 个回答
23
问题在于你的网址没有按照IDNA
规则正确编码,这些规则规定了国际化域名是如何转换的:
域名在ASCII和非ASCII形式之间的转换是通过一些叫做ToASCII和ToUnicode的算法来完成的。这些算法不是对整个域名进行处理,而是对每个部分(标签)单独处理。比如说,如果域名是www.example.com,那么这些部分就是www、example和com。ToASCII或ToUnicode会分别对这三个部分进行处理。
这两个算法的具体细节比较复杂,详细内容在RFC 3490中有说明。下面是它们功能的概述。
ToASCII会保持任何ASCII标签不变,但如果标签不适合域名系统,它就会失败。如果标签中包含至少一个非ASCII字符,ToASCII会使用Nameprep算法,这个算法会把标签转换为小写并进行其他标准化处理,然后再用Punycode将结果转换为ASCII,最后在前面加上四个字符的字符串“xn--”。这个四个字符的字符串叫做ASCII兼容编码(ACE)前缀,用来区分Punycode编码的标签和普通的ASCII标签。ToASCII算法可能会以多种方式失败;例如,最终的字符串可能会超过DNS名称的63个字符限制。如果ToASCII失败的标签,就不能用于国际化域名。
在你的情况下,一个''(空白)不是有效的域名字符,所以你会得到这个结果:
>>> '.f.de'.encode('idna')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/encodings/idna.py", line 164, in encode
result.append(ToASCII(label))
File "/usr/lib/python2.6/encodings/idna.py", line 73, in ToASCII
raise UnicodeError("label empty or too long")
UnicodeError: label empty or too long
如果你把域名改成'a.f.de',就应该不会再出现这个异常了。