2008-11-06 31 views
15

Tôi đang viết một số phần mềm xử lý thư bằng Python đang gặp phải các byte lạ trong các trường tiêu đề. Tôi nghi ngờ đây chỉ là thư không đúng định dạng; bản thân thông điệp tự xưng là ascii của chúng tôi, vì vậy tôi không nghĩ rằng có một mã hóa thực sự, nhưng tôi muốn lấy ra một chuỗi unicode xấp xỉ với chuỗi gốc mà không cần ném một số UnicodeDecodeError.Có chức năng thư viện Python nào cố gắng đoán mã hóa ký tự của một số byte không?

Vì vậy, tôi đang tìm một hàm cần có một số str và một số gợi ý tùy chọn và thực hiện gợi ý của nó để trả lại cho tôi unicode. Tôi có thể viết một trong những khóa học, nhưng nếu như một chức năng tồn tại tác giả của nó có lẽ đã suy nghĩ sâu hơn một chút về cách tốt nhất để đi về điều này.

Tôi cũng biết rằng thiết kế của Python thích rõ ràng hơn và thư viện chuẩn được thiết kế để tránh ma thuật ngầm trong giải mã văn bản. Tôi chỉ muốn nói rõ ràng "đi trước và đoán".

Trả lời

12

Theo như tôi có thể nói, thư viện chuẩn không có chức năng, mặc dù không quá khó để viết một hàm như đã đề xuất ở trên. Tôi nghĩ rằng điều tôi đang tìm kiếm là một cách để giải mã một chuỗi và đảm bảo rằng nó sẽ không ném một ngoại lệ. Tham số lỗi cho string.decode thực hiện điều đó.

def decode(s, encodings=('ascii', 'utf8', 'latin1')): 
    for encoding in encodings: 
     try: 
      return s.decode(encoding) 
     except UnicodeDecodeError: 
      pass 
    return s.decode('ascii', 'ignore') 
+1

Bạn có thể bỏ qua trường hợp '' ascii'' ở cuối và chỉ sử dụng 'latin1', vì' latin1' sẽ giải mã tất cả các giá trị 256 byte mà không có lỗi. –

20

Bạn có thể quan tâm đến Universal Encoding Detector.

+0

+1 nhanh hơn tôi 5 giây :-) –

+0

Thực sự hữu ích, cảm ơn. Nhưng không phải trong thư viện chuẩn. – Nick

18

+1 cho mô-đun chardet (được đề xuất bởi @insin).

Nó không có trong thư viện chuẩn, nhưng bạn có thể dễ dàng cài đặt nó với lệnh sau đây:

$ pip install chardet 

Example:

>>> import chardet 
>>> import urllib 
>>> detect = lambda url: chardet.detect(urllib.urlopen(url).read()) 
>>> detect('http://stackoverflow.com') 
{'confidence': 0.85663169917190185, 'encoding': 'ISO-8859-2'}  
>>> detect('https://stackoverflow.com/questions/269060/is-there-a-python-lib') 
{'confidence': 0.98999999999999999, 'encoding': 'utf-8'} 

Xem Installing Pip nếu bạn không có một.

+1

Nó không tấn công bạn rằng 'ISO-8859-2' là một điều vô nghĩa? –

+0

@ John Machin: Vâng, đúng vậy. Đó là giáo dục để cho thấy rằng bạn không nên tin tưởng một cách mù quáng nó. Kết quả hiện tại khác nhau ('utf-8' và 'ascii' tương ứng). – jfs

1

Cách tốt nhất để thực hiện điều này mà tôi đã tìm thấy là thử lặp lại giải mã một khách hàng tiềm năng với từng mã hóa phổ biến nhất bên trong khối thử ngoại trừ.

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