오늘은 어제 고민하던 것들을 모두 해결하고 새로운 고민이 생겼다.
원티드는 페이지네이션이 아니라 무한스크롤이 구현되어있어서 스크롤을 아래까지 쭉 내려야만 해당되는 채용 카드의 정보를 가져올 수 있었다.
그래서 자기가 알아서 스크롤을 내리는 코드를 구현했어야했는데
솔직히 이건 진짜 모르겠어서 검색을 했고 코드를 찾아서 붙여넣었다.
https://stackoverflow.com/questions/51529332/puppeteer-scroll-down-until-you-cant-anymore
let lastHeight = await page.evaluate("document.body.scrollHeight");
while (true) {
await page.evaluate("window.scrollTo(0, document.body.scrollHeight)");
await page.waitForTimeout(2000); // sleep a bit
let newHeight = await page.evaluate("document.body.scrollHeight");
if (newHeight === lastHeight) {
break;
}
lastHeight = newHeight;
}
어떤 의미를 가지고 있는지는 알아야할 것 같아서 확인을 해보니
웹 페이지의 끝이 될 때까지 스크롤을 내려라. 가 이 코드의 명령어다.
상단에 크롤링을 이야기하는 소프트웨어 제어가 떠있는 모습
중앙 페이지에서 각 카드에 들어가서 정보를 긁어와야했기 때문에
근데 창을 껏다가 뒤로 돌아가는건 정말 비효율적인 것 같아서 이리저리 찾아봤는데
마우스 휠로 클릭을 유도해가지고 새로운 탭이 생기게 하는 옵션이 있었다(신기해라)
https://stackoverflow.com/questions/59575748/puppeteer-how-to-click-element-so-it-opens-in-new-tab
let options = { button: "middle" }; //<- 이거가 휠로 누르는 것
await framePage.click(
`#__next > div.JobList_cn__t_THp > div > div > div.List_List_container__JnQMS > ul > li:nth-child(${i}) > div > a`,
options
);
이렇게 새로운 탭을 만들어내는 것은 문제가 없었는데, 정보를 가져오는 것이 문제가 됐다.
페이지를 넘어가서 정보를 가져와야하는데 어떻게...가져오나요...?
또 검색했다..^^ (선배 개발자들의 삽질은 나의 행복)
https://stackoverflow.com/questions/62746325/switching-to-a-new-tab-using-browser-pages-in-puppeteer
const [tab1, tab2, tab3] = await browser.pages();
await tab3.bringToFront();
await tab3.waitForNavigation();
퍼펫티어를 활용하면 나만 그런지는 몰라도(...)
아무것도 없는 공백 창 1개, 내가 goto()로 생성한 창 1개로 총 2개가 뜨게 된다.
여기서 새로운 탭을 생성할 경우에는 1개가 더 떠서 총 3개가 뜨는데
이것을 구조분해할당으로 분리해서 각각에 접근을 할 수 있다는 것을 알게 되었다.
그리고 bringToFront()는 페이지를 이동하는 메소드고
waitForNavigation()는 페이지를 기다려주는 메소드다.
정보를 가져와야하니 페이지를 이동하고, 구성이 될 때까지 기다린다고 생각하면 될 것 같다(아마두)
그리고 빗줄이 그어져있던 waitFor도 해결했다.
const qualification = await tab3.waitForSelector(
`#__next > div.JobDetail_cn__WezJh > div.JobDetail_contentWrapper__DQDB6 > div.JobDetail_relativeWrapper__F9DT5 > div > div.JobContent_descriptionWrapper__SM4UD > section > p:nth-child(5)`
);
const qualificationData = await tab3.evaluate(
(qualification) => qualification.textContent,
qualification
);
waitForSelector이라는 메소드를 통하여 같은 동작을 가능캐 하였다.
사실 2개로 분리되어있는 것을 $eval로 고칠 수 있는 것 같은데
얘가 낮은 확률로 오류(?)를 뱉길래 정확하게 확인이 되지 않아서 주석처리만 해놓았다.
그리고 정보를 다 긁었으면 닫고 반복문이 돌아가게 되는 구조로 만들었다.
결국은 이러한 구조를 가지고 움직인다고 생각하면 된다.
이제 1-4까지는 완성이 되었으니 5번의 존재하는 카드 개수를 확인만 하면 된다.
그리고 최종적으로 엘라스틱서치에 데이터를 집어넣어서 검색기능이 가능하도록 구현을 하면 되는데
아마도 프론트 한명 붙잡고 미니프로젝트처럼 해야할 것 같다는 생각이 든다.
그리고 데이터를 바로 엘라스틱서치에 집어넣을지, 아니면 MySQL이나 MongoDB에 집어넣었다가 Logstash로 넘길지 고민하고 있다.
뭐가 좋을지는 생각을 좀 해봐야할 것 같다...
끝!
nestjs 정리해야하는데 으으!
저도 스크롤 해서 데이터를 가져오는 로직이 필요했는데 블로그 글을 보고 바로 해결이 되었어요! ㅎㅎ 감사합니다~