在python中将域名转换为idn

时间:2010-09-21 12:41:52

标签: python unicode

我有很长的域名列表,我需要生成一些报告。该列表包含一些IDN域,虽然我知道如何在命令行中在python中转换它们:

>>> domain = u"pfarmerü.com"
>>> domain
u'pfarmer\xfc.com'
>>> domain.encode("idna")
'xn--pfarmer-t2a.com'
>>> 

我正在努力让它与一个从文本文件中读取数据的小脚本一起工作。

#!/usr/bin/python

import sys

infile = open(sys.argv[1])

for line in infile:
    print line,
    domain = unicode(line.strip())
    print type(domain)
    print "IDN:", domain.encode("idna")
    print

我得到以下输出:

$ ./idn.py ./test 
pfarmer.com
<type 'unicode'>
IDN: pfarmer.com

pfarmerü.com
Traceback (most recent call last):
  File "./idn.py", line 9, in <module>
    domain = unicode(line.strip())
UnicodeDecodeError: 'ascii' codec can't decode byte 0xfc in position 7: ordinal not in range(128)

我也尝试过:

#!/usr/bin/python

import sys
import codecs

infile = codecs.open(sys.argv[1], "r", "utf8")

for line in infile:
    print line,
    domain = line.strip()
    print type(domain)
    print "IDN:", domain.encode("idna")
    print

哪位给了我:

$ ./idn.py ./test       
Traceback (most recent call last):
  File "./idn.py", line 8, in <module>
    for line in infile:
  File "/usr/lib/python2.6/codecs.py", line 679, in next
    return self.reader.next()
  File "/usr/lib/python2.6/codecs.py", line 610, in next
    line = self.readline()
  File "/usr/lib/python2.6/codecs.py", line 525, in readline
    data = self.read(readsize, firstline=True)
  File "/usr/lib/python2.6/codecs.py", line 472, in read
    newchars, decodedbytes = self.decode(data, self.errors)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-5: unsupported Unicode code range

这是我的测试数据文件:

pfarmer.com
pfarmerü.com

我非常清楚我现在需要了解unicode。

谢谢,

彼得

2 个答案:

答案 0 :(得分:14)

您需要知道您保存的文件编码。这可能是'utf-8'(非Unicode)或'iso-8859-1'或'cp1252'等。

然后你可以做(​​假设'utf-8'):


infile = open(sys.argv[1])

for line in infile:
    print line,
    domain = line.strip().decode('utf-8')
    print type(domain)
    print "IDN:", domain.encode("idna")
    print

使用decode将编码字符串转换为unicode。将unicode转换为encode的字符串。如果你试图对已编码的东西进行编码,python会首先尝试解码,默认编解码器'ascii'对于非ASCII值失败。

答案 1 :(得分:2)

你的第一个例子很好,除了:

domain = unicode(line.strip())

您必须在此处指定特定编码:unicode(line.strip(), 'utf-8')。否则,您将获得默认编码,安全性为7位ASCII,因此出错。或者你可以拼写它line.strip().decode('utf-8'),就像在knitti的例子中一样;两种语法之间的行为没有区别。

但是,根据错误判断“无法解码字节0xfc”,我认为您实际上并未将test文件保存为UTF-8。据推测,这就是为什么原则上看起来也不错的第二个例子失败了。

相反,它是ISO-8859-1或非常相似的Windows代码页1252.如果它来自西方Windows盒子上的文本编辑器,它肯定会是后者;现在,Linux机器默认使用UTF-8。确保将文件保存为UTF-8,或使用编码'cp1252'读取文件。