크롤링을 성공 했습니다. 문제는 cheerio, request 전부 다 있었습니다.
어제 확인했던 에러인데 에러 위치를 보면 노드모듈에 request였습니다. 어제는 너무 피곤한 나머지 대충 확인했었는데 cheerio를 바꿨음에도 안되는 것은 request에 문제가 있지 않을까 라고 생각했고, 그게 맞았습니다. 수정한 코드는
const cheerio = require("cheerio-without-node-native");
// const request = require("requestretry");
export default async function getPage() {
let pageNum = 1;
let result = [];
let ulList = [];
// 전체 페이지 리스트 구하기
let url = `https://www.nubija.com/board/getList.do?bdno=2&currPage=${pageNum}`;
const options = {
method: "GET",
encoding: null,
headers: {
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36",
Accept:
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Content-Type": "application/x-www-form-urlencoded",
Cookie:
"WMONID=m2zajRZqm5f; _ga=GA1.2.1860211416.1622781690; _gid=GA1.2.882171542.1623936429; JSESSIONID=DFFB23E27EFF9769B473D12C31A83487; _gat=1",
},
};
let html = await fetch(url, options);
let responseOK = html && html.ok;
if (responseOK) {
let data = await html.text();
const $ = cheerio.load(data);
const $list = $("#notice_border tbody tr td:nth-of-type(2) a").toArray();
const $maxPageNum = $("#list_number span:nth-of-type(2)")
.text()
.split("/")[1];
$list.map((el, idx) => {
ulList[idx] = parseInt($(el).attr("onclick").split("'")[1]);
});
// console.log(ulList, $maxPageNum);
}
// 페이지별 데이터 구하기
await Promise.all(
ulList.map((el, idx) => {
let liUrl = `https://www.nubija.com/board/getView.do?bdno=2&blno=${el}`;
return fetch(liUrl, options)
.then((res) => res.text())
.then((data) => {
const $ = cheerio.load(data);
//trim으로 공백 제거
result.push({
id: idx,
title: $(".view_title").text().trim(),
content: $("#board_contents").text().trim(),
date: $("#border_view tbody tr:nth-of-type(2) td:nth-of-type(1)")
.text()
.trim(),
});
});
})
);
// console.log(result);
return result;
}
cheerio-without-node-native를 사용했고, request 대신 fetch를 사용했습니다. fetch를 사용한 이유는 라이브러리를 import 하지 않아도 사용할 수 있습니다. React Native 의 경우에 업데이트가 잦기 때문에, 라이브러리가 이 업데이트를 쫓아오지 못하는 경우가 생긴다고 합니다. 하지만 Fetch는 이걸 걱정할 필요 없이 사용 가능해서 유용하다고 생각했습니다.
notice.js
import getPage from "../../getData/NoticeData";
function NoticeListScreen({ navigation }) {
const [noticeData, setNoticeData] = useState([{ title: "로딩 중" }]);
...
useEffect(() => {
//데이터 불러오기
async function fetchData() {
const notice = await getPage();
console.log(notice);
notice.sort((a, b) => {
//id를 오름차순으로 정렬하는 방법이라는데.. 잘모르겠다.
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
});
setNoticeData([...notice]);
}
fetchData();
}, []);
...
공지사항 버튼을 클릭하여 notice.js 가 실행되는 순간 데이터를 불러와서 값을 저장해주는 방식으로 작성해보았습니다. 그런데 로딩을 새로할 때마다 정렬이 되지않고 공지사항 리스트의 순서가 바뀌어서 렌더링 되었습니다. 이를 보완하기 위해 검색을 해서
notice.sort((a, b) => {
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
});
로 오름차순 정렬을 해주었습니다. 이전 값인 b.id가 a.id보다 크면 -1로 바꾸어주는 형식으로 만들었습니다.
기업협업으로 크롤링을 했었는데 당시 받았던 피드백과 수정 코드가 이렇게 도움이 될 줄 몰랐습니다. 앞으로 배울 것들을 꼼꼼히 메모하는 습관을 더욱 들여야겠습니다.
다음 해볼 것은 무한 스크롤과 새로고침입니다!