2010-09-21 27 views
5

Tôi có một danh sách dài các tên miền mà tôi cần để tạo một số báo cáo. Danh sách này chứa một số tên miền IDN và mặc dù tôi biết cách chuyển đổi chúng trong python trên dòng lệnh:Chuyển đổi tên miền thành idn trong python

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

Tôi đang cố gắng làm cho nó hoạt động với một tập lệnh nhỏ đọc dữ liệu từ tệp văn bản.

#!/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 

tôi nhận được kết quả như sau:

$ ./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) 

Tôi cũng đã cố gắng:

#!/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 

nào đã cho tôi:

$ ./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 

Đây là tập tin dữ liệu thử nghiệm của tôi:

pfarmer.com 
pfarmerü.com 

Tôi rất ý thức về nhu cầu của mình để hiểu unicode ngay bây giờ.

Cảm ơn,

Peter

Trả lời

13

bạn cần biết trong đó mã hóa tập tin bạn đã lưu. Điều này sẽ giống như 'utf-8' (không phải là Unicode) hoặc 'iso-8859-1' hoặc 'cp1252' hoặc giống nhau.

Sau đó, bạn có thể làm (giả '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 

Chuyển đổi mã hóa chuỗi Unicode với decode. Chuyển đổi unicode thành chuỗi với encode. Nếu bạn cố gắng mã hóa một cái gì đó đã được mã hóa, python sẽ cố gắng giải mã đầu tiên, với codec mặc định 'ascii' không thành công cho các giá trị không phải ASCII.

2

ví dụ đầu tiên của bạn là tốt, ngoại trừ:

domain = unicode(line.strip()) 

bạn phải chỉ định một mã hóa đặc biệt ở đây: unicode(line.strip(), 'utf-8'). Nếu không, bạn sẽ nhận được mã hóa mặc định cho sự an toàn là ASCII 7 bit, do đó có lỗi. Hoặc bạn có thể đánh vần nó line.strip().decode('utf-8') như trong ví dụ của knitti; không có sự khác biệt về hành vi giữa hai cú pháp.

Tuy nhiên, đánh giá bởi lỗi “không thể giải mã byte 0xfc”, tôi nghĩ bạn chưa thực sự lưu tệp test dưới dạng UTF-8. Có lẽ đây là lý do tại sao ví dụ thứ hai, cũng có vẻ OK về nguyên tắc, không thành công.

Thay vào đó là ISO-8859-1 hoặc trang mã Windows rất giống 1252. Nếu nó đến từ trình soạn thảo văn bản trên hộp Windows phía Tây, nó chắc chắn sẽ là sau; Các máy Linux sử dụng UTF-8 theo mặc định thay thế ngày nay. Hãy đảm bảo lưu tệp của bạn dưới dạng UTF-8 hoặc đọc tệp bằng cách sử dụng mã hóa 'cp1252' thay thế.

Các vấn đề liên quan