2009-11-11 1 views
6

나는 그 모든 올바른 방법을 가지고 있습니까? 어쨌든, 나는 많은 HTML을 파싱하고 있지만, 어떤 인코딩이 될 것인지 항상 알지는 못한다. (놀라운 숫자는 거짓말이다.) 아래의 코드는 지금까지 내가 해왔 던 것을 쉽게 보여 주지만 더 좋은 방법이 있다고 확신합니다. 당신의 제안은 많이 감사 할 것입니다.Python 2.5에서 알려지지 않은 유니 코드 인코딩을 해독하는 가장 좋은 방법

import logging 
import codecs 
from utils.error import Error 

class UnicodingError(Error): 
    pass 

# these encodings should be in most likely order to save time 
encodings = [ "ascii", "utf_8", "big5", "big5hkscs", "cp037", "cp424", "cp437", "cp500", "cp737", "cp775", "cp850", "cp852", "cp855", 
    "cp856", "cp857", "cp860", "cp861", "cp862", "cp863", "cp864", "cp865", "cp866", "cp869", "cp874", "cp875", "cp932", "cp949", 
    "cp950", "cp1006", "cp1026", "cp1140", "cp1250", "cp1251", "cp1252", "cp1253", "cp1254", "cp1255", "cp1256", "cp1257", "cp1258", 
    "euc_jp", "euc_jis_2004", "euc_jisx0213", "euc_kr", "gb2312", "gbk", "gb18030", "hz", "iso2022_jp", "iso2022_jp_1", "iso2022_jp_2", 
    "iso2022_jp_2004", "iso2022_jp_3", "iso2022_jp_ext", "iso2022_kr", "latin_1", "iso8859_2", "iso8859_3", "iso8859_4", "iso8859_5", 
    "iso8859_6", "iso8859_7", "iso8859_8", "iso8859_9", "iso8859_10", "iso8859_13", "iso8859_14", "iso8859_15", "johab", "koi8_r", "koi8_u", 
    "mac_cyrillic", "mac_greek", "mac_iceland", "mac_latin2", "mac_roman", "mac_turkish", "ptcp154", "shift_jis", "shift_jis_2004", 
    "shift_jisx0213", "utf_32", "utf_32_be", "utf_32_le", "utf_16", "utf_16_be", "utf_16_le", "utf_7", "utf_8_sig" ] 

def unicode(string): 
    '''make unicode''' 
    for enc in self.encodings: 
     try: 
      logging.debug("unicoder is trying " + enc + " encoding") 
      utf8 = unicode(string, enc) 
      logging.info("unicoder is using " + enc + " encoding") 
      return utf8 
     except UnicodingError: 
      if enc == self.encodings[-1]: 
       raise UnicodingError("still don't recognise encoding after trying do guess.") 
+0

자동 검색은 텍스트에 대해 * 전혀 * 알지 못하지만 적어도 텍스트가있는 언어를 아는 경우에는 거의 옵션이 없습니다. 그래서 인코딩 탐지는 기본적으로 문자의 빈도에 따라 언어를 추측하려고 시도하는 것을 의미합니다. –

+0

Erm, unicode()는 UTF-8이 아닌 유니 코드를 반환합니다. –

답변

8

알 수없는 인코딩을 검출하기위한 두 개의 범용 라이브러리가 있습니다

다음 정규식을 사용하여 바이트 문자열에서 utf8을 검색 할 수 있습니다 S :

실제로
import re 

utf8_detector = re.compile(r"""^(?: 
    [\x09\x0A\x0D\x20-\x7E]   # ASCII 
    | [\xC2-\xDF][\x80-\xBF]    # non-overlong 2-byte 
    | \xE0[\xA0-\xBF][\x80-\xBF]  # excluding overlongs 
    | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte 
    | \xED[\x80-\x9F][\x80-\xBF]  # excluding surrogates 
    | \xF0[\x90-\xBF][\x80-\xBF]{2}  # planes 1-3 
    | [\xF1-\xF3][\x80-\xBF]{3}   # planes 4-15 
    | \xF4[\x80-\x8F][\x80-\xBF]{2}  # plane 16 
)*$""", re.X) 

당신은 내가 다음 발견 된 시간의 99.9 % 작동 한 영어를 처리하는 경우 : 그것은 위의 정규식을 통과하면, 그것은 ASCII 또는 UTF8 이

  1. 의를 이 0x80-0x9f하지만 0xa4에서 모든 바이트를 포함하는 경우
  2. 는, 그것이 0xa4이 포함 된 경우, 그렇지 않으면 그것은 라틴어 - 1
  3. 을 가정 해는 라틴어-15
  4. 를 가정 해 윈도우 1252
  5. 입니다 0
+1

이 코드는 http : // pastebin에 저장합니다.com/f76609aec – user132262

+0

붙여 넣은 코드에 문제가 있습니다. '^ (? : \ xA4) * $'는 문자열이 * 완전히 *'\ xA4'이고 다른 문자가없는 경우 일치합니다. 두 개의 다른 정규 표현식에 대해서만're.compile (r '\ xA4')'와're.compile (r '[\ x80- \ xBF]')'가 필요합니다. –

1

파이썬을 사용하고 있으므로 UnicodeDammit을 시도 할 수 있습니다. 유용 할 수도있는 Beautiful Soup의 일부입니다.

이름에서 알 수 있듯이 UnicodeDammit은 세상에서 찾을 수있는 쓰레기 중에서 적절한 유니 코드를 얻는 데 필요한 모든 것을하려고합니다.

+0

일찍 시도했지만 실패했습니다. – user132262

+0

정말! 문제는 무엇 이었습니까? 그것은 자신의 롤백보다 일하는 것이 더 쉬울 수 있습니다. –

+0

"세상에서 찾을 수있는 쓰레기"? – Sabuncu

2

나는 동일한 문제를 해결했으며 콘텐츠에 대한 메타 데이터없이 콘텐츠의 인코딩 유형을 결정할 방법이 없다는 것을 알아 냈습니다. 그래서 내가 여기서 시도하는 것과 동일한 접근 방식을 사용하게되었습니다.

당신이 한 일에 대한 또 다른 조언은 가장 가능성이 높은 순서로 가능한 인코딩 목록을 주문하는 것이 아니라 특이성으로 주문해야한다는 것입니다. 특정 문자 집합이 다른 문자 집합의 일부인 것을 발견 했으므로 두 번째 선택으로 utf_8을 확인하면 utf_8의 하위 집합을 찾을 수 없습니다 (한국어 문자 집합 중 하나는 utf와 동일한 숫자 공간을 사용한다고 생각합니다.)).

chardet의 일부 way that firefox does it의 포트 있어야하는데 :

+0

사실. 'ascii'는'utf-8'의 부분 집합이고'utf-8'로 올바르게 디코드되기 때문에'ascii'를 남겨 둘 수 있습니다. 'latin-1'과 같은 8 비트 인코딩은 모든 경우에 _ 무언가로 디코드됩니다. 따라서 마지막에 하나를 넣으십시오. – Thomas

관련 문제