[개인 Project] expo에서 크롤링 성공!, 메뉴 버튼 추가, 탭 추가

김민성·2021년 6월 18일
1

알GO누비자

목록 보기
9/25
post-thumbnail

크롤링을 성공 했습니다. 문제는 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로 바꾸어주는 형식으로 만들었습니다.

기업협업으로 크롤링을 했었는데 당시 받았던 피드백과 수정 코드가 이렇게 도움이 될 줄 몰랐습니다. 앞으로 배울 것들을 꼼꼼히 메모하는 습관을 더욱 들여야겠습니다.

다음 해볼 것은 무한 스크롤과 새로고침입니다!

profile
https://github.com/alstjd8826

0개의 댓글