Преобразование доменных имен в IDN в Python - PullRequest
5 голосов
/ 21 сентября 2010

У меня длинный список доменных имен, по которым мне нужно составить несколько отчетов.Список содержит несколько доменов 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 ]

14 голосов
/ 21 сентября 2010

вам нужно знать, в какой кодировке был сохранен ваш файл.Это может быть что-то вроде '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

Преобразование закодированных строк в Unicode с decode.Преобразовать Юникод в строку с encode.Если вы попытаетесь закодировать что-то, что уже закодировано, python попытается декодировать первым, используя кодек по умолчанию «ascii», который не работает для не-ASCII-значений.

2 голосов
/ 21 сентября 2010

Ваш первый пример в порядке, за исключением того, что:

domain = unicode(line.strip())

Вы должны указать конкретную кодировку здесь: unicode(line.strip(), 'utf-8'). В противном случае вы получите кодировку по умолчанию, которая для безопасности является 7-битной ASCII, отсюда и ошибка. В качестве альтернативы вы можете записать это line.strip().decode('utf-8'), как в примере Книтти; нет различий в поведении между двумя синтаксисами.

Однако, судя по ошибке «невозможно декодировать байт 0xfc», я думаю, что вы на самом деле не сохранили файл test как UTF-8. Предположительно, именно поэтому второй пример, который в принципе тоже выглядит нормально, не работает.

Вместо этого это ISO-8859-1 или очень похожая кодовая страница Windows 1252. Если она пришла из текстового редактора в западной коробке Windows, она, безусловно, будет последней; Машины Linux используют UTF-8 по умолчанию вместо этого в настоящее время. Обязательно сохраните файл как UTF-8 или прочитайте файл, используя вместо этого кодировку 'cp1252'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...