본문 바로가기
웹개발/크롬 익스텐션

크롬 익스텐션 개발기(4) : html 디코딩

by 현댕5697 2021. 4. 25.
반응형

웹클리퍼 기능을 구현하면서 발생했던 주요 문제중에 하나는 바로 인코딩/디코딩 문제였다!

 

이 페이지를 웹클리핑하면

http://news.chosun.com/misaeng/site/data/html_dir/2017/08/21/2017082100911.html

 

http://news.chosun.com/misaeng/site/data/html_dir/2017/08/21/2017082100911.html

 

news.chosun.com

캡쳐에서 보이듯이 웹사이트 정보에 대한 텍스트들이 깨져서 나타났다.

이유를 확인해보니, axios를 이용하여 웹페이지의 html 문서를 가져올 때 utf-8 타입으로 가져오게 되는데, 이 사이트는 content-type이 euc-kr로 되어있어서 한글이 제대로 가져와지지 않았기 때문이었다.

 

이런 오류를 반복하지 않기 위해서는 페이지마다 다른 content-type에 대해 문자열로 디코딩하는 과정이 필요했다.

그래서 arraybufferTextDecoder 함수를 이용하였다.

 

TextDecoder 함수를 사용하기 위해서는 axios 요청시 데이터를 binary 형식으로 가져와야 한다.

따라서 다음 코드와 같이 axios 요청을 해주었다.

const getHTML = async url => {
  try {
    const response = await axios.request({
      url: url,
      method: 'GET',
      responseType: 'arraybuffer',
      responseEncoding: 'binary'
    });

    const decoded = await convert(response.data);
    return decoded;
  } catch (error) {
    console.log('[GET HTML] ERROR: ', error);
  }
};

responseType으로 arraybuffer을 사용하는 이유는 arraybuffer가 일반 고정 길이 binary 데이터 버퍼를 나타내는 데 사용되는 데이터 형식이기 때문이다.

 

convert()가 바로 데이터를 디코딩하는 함수이다.

이 함수의 코드는 다음과 같다.

const convert = async html => {
  // arraybuffer -> string
  var enc = new TextDecoder('utf-8');

  // 'euc-kr'찾기
  const $ = cheerio.load(enc.decode(html));

  let charsetNormal = $("meta[http-equiv='Content-Type']").attr('content');
  let charsetUpper = $("meta[http-equiv='CONTENT-TYPE']").attr('content');
  let charsetLower = $("meta[http-equiv='content-type']").attr('content');
  let charset = (charsetNormal? charsetNormal : (charsetUpper? charsetUpper : charsetLower));

  // decoding
  if(charset!==undefined){
    if(charset.toLowerCase().indexOf('euc-kr') > -1){
      enc = new TextDecoder("euc-kr");
      return enc.decode(html);
    }
  }

  return enc.decode(html);
};

먼저 axios 요청을 통해 얻은 html 문서가 utf-8 형식이라고 가정하고 TextDecoder를 사용하여 디코딩을 한다.

그 후 cheerio 라이브러리를 통해 사이트의 content-type을 찾아 charset 변수에 저장하는 과정을 거친다.

charset의 값이 euc-kr이면 TextDecoder를 사용하여 euc-kr 타입의 html 문서를 디코딩하여 반환한다.

 

 

 

반응형

댓글