puppeteer를 활용하여 크롤링 해보기 (1)

·2022년 6월 18일
0

크롤링

목록 보기
2/6
post-thumbnail

커뮤니티를 보던 중 채용 관련 이야기가 많이 나왔다.

그러던 중 어떤 분이 제가 보고싶은 채용만 골라서 볼 수 있는거 있으면 좋겠네요... 라는 말을 듣게 됐다.

그리고 이게 정말 큰 공감이 갔다(...)

왜냐하면 나는 NodeJS개발자를 뽑는 것을 필터링을 걸어놓고 찾고 있는데
누르면 java python이 자아아안득 적혀있다.

제목에 Nodejs라고 적어놓은 곳이 아니라면 30% 이상이 node가 아닌 느낌?

그래서 크롤링이 바로 생각이 나가지고 진짜 오랜만에 찾아보길 시작해서 현재 이만큼까지 결과를 뽑아냈다.


크롤링 과정

  1. 필터가 걸려있는 URL을 따온다.
  2. 그것으로 퍼펫티어로 인터넷 창을 연다.
  3. 아래 카드형식으로 들어가있는 것을 클릭해서 속의 데이터를 꺼낸다.

현재 이만큼까지는 진행을 했는데..... 2가지 문제만 해결하면 된다.

첫번째는 클릭을 해서 페이지가 넘어간 상태에서 데이터를 수집하는데
다시 클릭하기 전의 페이지로 돌아오는 것이다.

뭐 window.history.go(-1)부터 시작해서 page.goBack() 이런거 막 써봤는데 안된다(...)

그런데 이것은 속도가 상당히 느릴 것 같아서 사용하지 않을 것 같고
새로운 탭을 만들어서 정보를 뽑아내고 그 탭만 꺼내면 비동기로 한번에 여러개의 작업도 가능할 것 같다.

두번째는 무한스크롤을 해결해야한다.

이게 페이지네이션이였다면 클릭이벤트를 줘서 페이지를 넘겼을텐데
무한스크롤이라 아래로 스크롤을 내리지 않으면 보여지는 개수의 한계가 존재한다.

이래서 퍼펫티어 탭 속에서 스크롤을 내리는 코드를 구현만 하면 될 것 같다.

그리고 나중에는 몽고디비에 넣던가 엘라스틱서치에 넣어서 내가 필요한 언어가 적혀있는 회사의 링크만 뽑아내가지고 쏙쏙 이력서를 넣으면 될 것 같다.

문득 생각이 들어서 찾아봤는데 원티드 크롤링해도 되는 것 같다 다행(...)


아래 올린건 현재 코드인데 말 그대로 구현 자체만 생각한 것이라 더럽다...^^..
그리고 waitFor가 빗금에 사라질 수 있다. 라고 적혀있는데 뭐로 구현을 해야할지 좀 찾아봐야할 것 같다..

import puppeteer from "puppeteer";

async function startCrawling() {
  const browser = await puppeteer.launch({ headless: true }); // 브라우저가 보이게 한다
  const page = await browser.newPage(); // 새로운 브라우저 켜기
  await page.setViewport({ width: 1280, height: 720 }); // 브라우저 크기 설정
  await page.goto(
    "https://www.wanted.co.kr/wdlist/518?country=kr&job_sort=company.response_rate_order&years=0&years=3&skill_tags=1547&selected=873&selected=872&selected=895&selected=1027&locations=seoul.all"
  ); // 페이지 이동
  await page.waitForTimeout(1000); // 일정 시간을 두고 접속하기

  const framePage = page
    .frames()
    .find((el) =>
      el
        .url()
        .includes(
          "/wdlist/518?country=kr&job_sort=company.response_rate_order&years=0&years=3&selected=873&selected=872&selected=895&selected=1027&locations=seoul.all"
        )
    );

  for (let i = 9; i < 10; i++) {
    await page.waitForTimeout(500);

    await framePage.click(
      `#__next > div.JobList_cn__t_THp > div > div > div.List_List_container__JnQMS > ul > li:nth-child(${i}) > div > a`
    );

    const qualification = await page.waitFor(
      `#__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 page.evaluate(
      (qualification) => qualification.textContent,
      qualification
    );

    const preferential = await page.waitFor(
      ` #__next > div.JobDetail_cn__WezJh > div.JobDetail_contentWrapper__DQDB6 > div.JobDetail_relativeWrapper__F9DT5 > div.JobContent_className___ca57 > div.JobContent_descriptionWrapper__SM4UD > section.JobDescription_JobDescription__VWfcb > p:nth-child(7) > span
      `
    );

    const preferentialData = await page.evaluate(
      (preferential) => preferential.textContent,
      preferential
    );

    const company = await page.waitFor(
      `#__next > div.JobDetail_cn__WezJh > div.JobDetail_contentWrapper__DQDB6 > div.JobDetail_relativeWrapper__F9DT5 > div > section.JobHeader_className__HttDA > div:nth-child(2) > h6 > a`
    );

    const companyData = await page.evaluate(
      (company) => company.textContent,
      company
    );
    const url = page.url();
    console.log(url);
    console.log(companyData);
    console.log(preferentialData.split("•"));
    console.log(qualificationData.split("•"));
  }

  await browser.close(); // 브라우저끄기
}

startCrawling();
profile
물류 서비스 Backend Software Developer

0개의 댓글