• Python Requests 한글 깨짐 문제 해결하기

    2021. 7. 13.

    by. Jacob Lee

    728x90

     


     

    Requests 인코딩 문제

    이전에 requests로 링크에 접근했을 때 인코딩 문제로 깨지는 몇 몇의 웹사이트들이 존재했었다.

    모든 케이스가 다 인코딩이 ISO-8859-1였을 때 문제가 발생하는 것을 확인하고 resp.encdoingutf-8로 바꾸어주었다.

     

    다음과 같이 바꾸어주었을 때, 몇 몇 Read the Docs 공식 문서라던지, 한국 사이트 들이 깨지는 문제가 온전히 해결되었었다.

    resp = requests.get(url, headers=headers, timeout=3)
    
    if resp.encoding == 'ISO-8859-1':
        resp.encoding = 'utf-8'

     

    하지만 최근에 어떤 기사 링크가 깨지는 것을 확인할 수 있었는데, 아래와 같은 괴상한 문자가 리턴이 되었다..

    "title": "��ġ����, ÷�� �Ű��� �ڱ���� �������� ���ָ�",

     

    어떻게 또 해결을 해야할 까, 고민을 해보고 'EUC-KR'로 교체하면 해결되지 않을까 하여 시도해 봤을 때, 결과는 성공적이였다. 하지만 더 나아가서 문제는.. 'UTF-8'을 사용했을 때 깨지지 않던 링크가 다시 깨진다는 것이였다..

     

    하나 고치면 다른데서 문제가 생기고, 이 문제를 해결하면 또 다른데서 문제가 생기는 루틴의 반복이였다. 버깅을 해보기 위해 requests.headers['content-type']으로 접근하려는 웹사이트의 charset이 무엇인지 찾아보기로 했다.

     

    결과는 다음과 같다.

    # 인코딩 문제 웹사이트
    text/html
    
    # 정사적인 웹사이트
    text/html; charset=utf-8

     

    apparent_encoding

    그래서 근본적으로 고칠 수 있는 방법이 있지 않을까 하여 찾아보다가 requests.apparent_encoding이라는 requests 라이브러리에서 제공하는 메소드를 발견했다.

    requests.apparent_encoding, 즉 분명한 인코딩을 사용해 준다는 것인데, 공식 문서에서의 설명은 다음과 같다.

    "The apparent encoding, provided by the charset_normalizer or chardet libraries"

     

    풀어 말해보면, apprent_encoding 메소드는 charset_nomalizerchardet 라이브러리를 사용해 확실한(적절한) 인코딩을 해주는 것이다.

     

    apparent_ecoding source code

    @property
    def apparent_encoding(self):
        """The apparent encoding, provided by the charset_normalizer or chardet libraries."""
        return chardet.detect(self.content)['encoding']

    위 소스 코드에서 보이는 것과 같이, chardet 라이브러리를 사용해 content-type을 찾아내고 인코딩 해준다.

     

    출력 결과

    >>> EUC-KR
    >>> utf-8

     

    시도했던 두 개의 웹사이트 모두 처음에는 깨지던 사이트이고, 첫 번째는 utf-8로 하면 깨지는, 그리고 두 번째는 euc-kr로 하면 깨지던 웹사이트였다. requests.apparent_encoding을 사용하니 안 깨지는 인코딩으로 자체 적용이 된 것을 확인할 수 있었다.

    # euc-kr 적용
    "title": "퍼치나인, 첨단 신개념 자기공진 무선충전 ‘주목’"
    
    # utf-8 적용
    "title": "쇼핑 유형 테스트"

     

    UTF-8로 인코딩 되어있는데 변환 문제

    마지막으로 다 해결된 줄 알았지만, 역시나 또 다른 고난이 나를 기다리고 있었다.

    apparent_encoding을 사용하니 정상적으로 utf-8로 인코딩 되어있던 웹사이트들이 다음과 같이 자동 변환되며 오히려 깨지는 상황이 발생하는 것이다.

    text/html; charset=UTF-8
    ascii
    text/html; charset=utf-8
    Windows-1254

     

    다시 한번 머리가 찌끈거리기 시작하면서.. 어떻게 해결할까 하다가, 결국에는 코드에서 분기를 해주어야겠다는 생각을 했다. 최종적으로 완성된(최선의 방법..) 코드는 다음과 같다.

    resp = requests.get(url, headers=headers, timeout=3)
    content_type = resp.headers['content-type']
    
    if not 'charset' in content_type:
        resp.encoding = resp.apparent_encoding

     

    728x90

    댓글