2017-12-17 8 views
2

URL로 파일을 가져와이 파일에서 가장 많은 단어를 가진 문자열을 반환해야합니다. 여기 내 코드입니다 :Python. URL로 파일을 읽을 때 파일 인코딩

from urllib.request import urlopen 

def wordiest_line(url): 
    data = urlopen(url) 

    if data: 
     max_words = 0 
     max_line = "" 
     for line in data.readlines(): 
      #print(line) 
      the_encoding = "utf-8" 
      line = line.decode(the_encoding) 
      line = line.rstrip() 
      line_words = line.split() 
      if len(line_words) > max_words: 
       max_words = len(line_words) 
       max_line = line 

     #print("%s to RETURN\n" % max_line) 
     return max_line 

    else: 
     return None 

는 그리고이이 기능을 테스트하기 위해 주어진 일부 URL은 다음과 같습니다

  1. "http://math-info.hse.ru/f/2017-18/dj-prog/lines1.txt"
  2. ""
  3. "http://math-info.hse.ru/f/2017-18/dj-prog/lines2.txt"

을 링크 1과 3의 경우 제대로 작동합니다. 하지만 파일 인코딩으로 인해 wordiest_line("http://lib.ru/FOUNDATION/3laws.txt_Ascii.txt") 이 제대로 작동하지 않으므로 키릴 문자로 된 텍스트가 있습니다.

문자열 인코딩을 정의하고 디코딩하려고했습니다. 여기에 코드입니다 :

from urllib.request import urlopen 
import chardet  

def wordiest_line(url): 
    data = urlopen(url) 

    if data: 
     max_words = 0 
     max_line = "" 
     for line in data.readlines(): 
      #print(line) 
      the_encoding = chardet.detect(line)['encoding'] 
      line = line.decode(the_encoding) 
      #print(the_encoding, line) 
      line = line.rstrip() 
      line_words = line.split() 
      if len(line_words) > max_words: 
       max_words = len(line_words) 
       max_line = line 

     #print("%s to RETURN\n" % max_line) 
     return max_line 

    else: 
     return None 

그리고 지금 wordiest_line("http://lib.ru/FOUNDATION/3laws.txt_Ascii.txt") 오류와 함께 실패 '문자표'코덱의 위치는 8 바이트 0xdc를 디코딩 할 수 없습니다 문자는 아직 정의되지 않은

다른 URL로 매핑 잘 작동합니다. 그것을 고칠 수있는 제안이 있습니까?

답변

1

chardet 라이브러리는 지저분한 입력의 인코딩을 추측하거나 수정해야하는 경우 생명을 구할 수 있습니다. 그러나, 귀하의 경우이 정보는 최소한 lib.ru 예제에서 제공됩니다. 어떤 잘 행동 서버에서 예상대로 은 일반 텍스트 응답의 캐릭터 세트는 "콘텐츠 형식"에 지정된 헤더 :

import codecs 
from urllib.request import urlopen 

def wordiest_line(url): 
    resp = urlopen(url) 
    charset = resp.headers.get_content_charset() 
    textreader = codecs.getreader(charset)(resp) 
    for line in textreader: 
     line = line.rstrip() 
     # continue with tokenising and counting... 

참고 : 난 당신이 파이썬 3 사용한다고 가정; 위의 코드는 파이썬 2에서 작동하지 않을 것이다. 또한, 나는 당신이 파일 라인을 반복하기 전에 내용을 디코딩하는 것이 좋겠다. 다른 인코딩 된 라인을 가진 엉망인 입력 파일 같은 깨진 입력을받지 못할 것이라고 가정한다.

두 번째 메모 : requests 라이브러리를 사용하면이 작업을 위해 보일러 플레이트 코드를 적게 쓸 수 있습니다.

세 번째 참고 : 단어를 계산할 때 line.split()은 다소 단순합니다. 예를 들어 "주장하다"와 "논쟁하다"는 다른 단어로 간주 될 것이며, "논쟁하다"와 "주장하다"를 동일한 단어에 속하는 것으로 정의하기를 원할 수도 있습니다. 이 경우 NLTK 나 SpaCy와 같은 NLP 라이브러리를 사용해야합니다.

0

파이썬은 불쾌한 문자를 공식 U + FFFD 치환 문자로 대체하는`decode (encoding, 'replace')로 결함 허용 디코딩을 할 수있게합니다.

 line = line.decode(the_encoding, 'replace') 

을 심지어 UTF8 인코딩으로, 올바른 행을 식별하지만 당연하지 할 수 있습니다 (@lenz에 의해 제안 된 솔루션을 편리 아니었다면의), 당신은 사용해야 인코딩 확신이 있다면 여기에

정확하게 디코드하십시오

또는 Latin1 인코딩은 모든 바이트를 동일한 코드 값의 유니 코드 문자로 변환한다는 사실을 사용할 수 있습니다.여기에 당신은 할 수 :

 try: 
      line = line.decode(the_encoding) 
     except UnicodeDecodeError: 
      line = line.decode('Latin1') 

을뿐만 아니라이 올바르게 올바른 라인을 idendifies하지만 함께 :

line = wordiest_line("http://lib.ru/FOUNDATION/3laws.txt_Ascii.txt") 
orig = line.encode('Latin) 

당신이 생의 바이트의 원래 라인을 얻을 지금 제대로 디코딩을 검사 할 수 있습니다.

알아두기, 파일의 올바른 인코딩은 KOI8-R

입니다.