2022. 5. 15. 18:26ㆍTech Note
해당 프로젝트 진행을 위해 샘플 데이터로 활용할 첫번째 타겟은 네이버 뉴스로 정했다.
카테고리는 경제, 사회, 정치 등의 각 분야에서 가져온다.
해당 작업을 위해 앞서 설정해놓은 express 서버에 크롤링 모듈을 설치하는 것.
파이썬의 경우 bs4, requests로 진행하면 되지만, node.js 서버의 경우 아래 플러그인을 활용하면 되겠다.
1. axios, cheerio 를 설치한다.
npm install --save axios cheerio
2. express 서버에 플러그인을 import 해준다.
const axios = require("axios")
const cheerio = require("cheerio")
3. 아래와 같이 입력, axios 호출을 통해 소스를 받아 온 후 cheerio를 통해 html eneity를 제어 할 수 있다.
const getAllNewsInfo = async function (req, res) {
let url = "https://news.naver.com/main/main.naver?mode=LSD&mid=shm&sid1=100"
getHtml(url)
.then(html => {
let ulList = []
const $ = cheerio.load(html.data)
const $bodyList = $("div.cluster").children("div.cluster_group")
$bodyList.each(function(idx, val) {
let title = $(this).find("div.cluster_text a").text()
ulList[idx] = {
"title": title,
"url" : $(this).find("div.cluster_text a").attr("href")
}
console.log(ulList)
})
res.status(200).json(ulList);
})
}
const getHtml = async(url) => {
return await axios.get(url)
}
4. 결과
확인해보니 encoding 이슈가 있는 것 같다. 해당 이슈는 플러그인 설치로 간단히 해결한 사례가 있으니 그대로 진행
node-iconv, iconv 등이 있으나, python, c# 등의 의존성이 있고 성능 이슈가 있는 듯하다.
node 서버에서 가장 대중적으로 쓰이는 iconv-lite를 사용해준다.
npm install --save iconv-lite
설치가 완료되면 요청을 보낼 네이버 뉴스의 header의 content-type을 확인해본다.
EUC-KR이 확인되니 아래와 같이 소스를 수정해준다.
const getAllNewsInfo = async function (req, res) {
let url = "https://news.naver.com/main/main.naver?mode=LSD&mid=shm&sid1=100"
let result = getHtml(url)
.then(html => {
let ulList = []
const contentType = html.headers["content-type"]
const charset = contentType.includes("charset=")
? contentType.split("charset=")[1] : 'UTF-8'
const $ = cheerio.load(html.data)
const $bodyList = $("div.cluster").children("div.cluster_group")
$bodyList.each(function(idx, val) {
let title = Iconv.decode($(this).find("div.cluster_text a").text(), charset)
ulList[idx] = {
"title": title,
"url" : $(this).find("div.cluster_text a").attr("href")
}
console.log(ulList)
})
res.status(200).json(ulList);
})
}
수정이 완료되면 실행!
값이 변경되긴 했으나 해결되진 않았다.
encoding 이슈가 아닌가?
5. 해결 및 결과 출력
encoding 문제가 맞다. 다만... 아래의 이유로 정상적인 진행이 되지 않았다.
1) euc-kr로 되어있는 페이지를 불러왔다. => 표현할 수 없는 값이라 한글 깨짐 발생
2) euc-kr을 decode해서 사용하기 전에 cheerio.load를 함으로써 변환 할 수 없는 객체가 되어버림.
3) 그 이후 decode를 한다. => 결국 decode 되지 않았다.
성공한 코드를 아래와 같다.
const getAllNewsInfo = async function (req, res) {
let url = "https://news.naver.com/main/main.naver?mode=LSD&mid=shm&sid1=100"
let result = getHtml(url)
.then(html => {
let ulList = []
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)
const $bodyList = $("div.cluster").children("div.cluster_group")
$bodyList.each(function(idx, val) {
let title = $(this).find("div.cluster_text a").text()
ulList[idx] = {
"title": title,
"url" : $(this).find("div.cluster_text a").attr("href")
}
// console.log(ulList)
})
res.status(200).json(ulList);
})
}
swagger UI를 통해 정상적으로 출력됨을 확인 할 수 있다!
별의별 해결방법을 다 고민하고 적용해봤지만 서순 문제였다. 개발은 늘 허를 찌르는 곳에서 날 힘들게 한다.
기본기의 중요성을 다시 한번 느낀다.
이번 문제를 해결하자마자 바로 async 이슈가 생겨서 작업이 한번 더 지체되었다.
다음 장엔 async/await 비동기처리 관련하여 정리해보고자 한다.
node.js를 하면서 날 가장 힘들게 하는 녀석이라. 한번 확실히 정리해두고 가야 될 듯하다.
'Tech Note' 카테고리의 다른 글
도커를 활용한 서비스 배포하기 (save, load, export, import) #4 (0) | 2022.06.16 |
---|---|
도커를 활용한 서비스 배포하기 (네트워크 설정 및 컨테이너 생성) #3 (0) | 2022.06.16 |
도커를 활용한 서비스 배포하기 (image search, pull) #2 (1) | 2022.06.15 |
도커를 활용한 서비스 배포하기 (rpm 설치) #1 (0) | 2022.06.08 |
크롤링 API 서버 개발#1 (기획 및 기본 서버 설정) (0) | 2022.05.09 |