Node.js

[Node.js] axios, cheerio로 크롤링 시 한글 깨짐

pocket.dev 2024. 6. 13. 19:50
반응형

node.js

 

axios와 cheerio로 웹크롤링을 하는데 한글이 깨지는 현상이 발생했다.

원인: 크롤링 대상 홈페이지가 charset이 euc-kr로 되어있는 것을 발견했다.

이럴 땐 html 문서를 utf-8로 변환해서 가져와야한다.

 

1. iconv-lite를 이용해보자

utf-8 인코딩/디코딩을 지원하는 iconv-lite 패키지를 이용했다. 아래 코드는 html 파일에서 content-type 타입을 가져와서 디코딩을 하는 방식이다.

import axios from 'axios';
import * as cheerio from 'cheerio';
import iconv from 'iconv-lite';

const getHtml = async () => {
  let URL = '';
  try {
    const html = await axios.get(URL || '');
    const contentType = html.headers['content-type'];
    const charset = contentType.includes('charset=')
      ? contentType.split('charset=')[1]
      : 'UTF-8';
    const content = iconv.decode(html.data, charset).toString();
    const $ = cheerio.load(content);
  } catch (error) {
    console.error('error', error);
  }
};

 

응답 형태는 바뀌었지만 여전히 한글이 깨지는 현상이 발생하였다.

 

2. axios 응답을 buffer 형태로 받아오자

axios를 통해 호출할 때 responseType을 buffer 형태로 받아와야지 제대로 변환된다고 한다. 아래 코드로 다시 실행해봤다.

import axios from 'axios';
import * as cheerio from 'cheerio';
import iconv from 'iconv-lite';

const getHtml = async () => {
  let URL = '';
  try {
    const html = await axios.get(URL || '',{
      responseType: 'arraybuffer',
    });
    const contentType = html.headers['content-type'];
    const charset = contentType.includes('charset=')
      ? contentType.split('charset=')[1]
      : 'UTF-8';
    const content = iconv.decode(html.data, charset).toString();
    const $ = cheerio.load(content);
  } catch (error) {
    console.error('error', error);
  }
};

 

한글이 깨지지 않고 제대로 응답이 오는 것을 확인했다.