标签为空或过长 - python urllib2

15 投票
1 回答
20490 浏览
提问于 2025-04-18 15:48

我遇到了一个奇怪的情况:

我在用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',就应该不会再出现这个异常了。

撰写回答