[Node.js] Puppeteer을 통한 42 intra 크롤링

Seongsu·2021년 9월 27일
0

42GG

목록 보기
1/1
post-thumbnail

🧐 Puppeteer 란?

유명한 크롤러 라이브러리로 Selenium이 있지만
Node.js로 웹 개발을 진행중이여서 노드 라이브러리를 찾게 되었다.

2017년 구글에서 만들어 낸 노드를 위한 웹 스크래핑 서비스 이며
예시로 크롤러가 사람처럼 input에 값을 넣고 로그인 버튼을 눌러준 후 페이지를 이동해 크롤링을 해올 수 있는 똑똑한 친구다.

공식 레퍼런스 또한 정리가 잘 되어있다.
https://pptr.dev/


🧑‍💻 인트라 크롤링 하기

42GG 사이트를 제작 중 42API 를 통해 카뎃 목록을 불러오려 하였는데
호출된 데이터에는 카뎃과 비 카뎃을 구분지을 수 없었다..

그래서 인트라 Grade 목록에서 해당 유저가 Learner 인지 Novice 인지 체크하는 검증 단계를 거치려고 크롤링을 공부하게 되었다.


  • 모듈 설치

npm i puppeteer


  • 코드
const puppeteer = require("puppeteer");

const getData = async () => {
  
  // 브라우저를 열어준다
  const browser = await puppeteer.launch();

  // 새 창을 띄운다
  const page = await browser.newPage();

  // 로그인을 위한 아이디, 비밀번호
  const login = "아이디";
  const password = "비밀번호";

  // 인트라 로그인 페이지 연결
  await page.goto("https://signin.intra.42.fr/users/sign_in");

  // 아이디, 비밀번호에 입력 (태그만 찾아주면 알아서 입력한다)
  await page.evaluate(
      (id, pw) => {
          document.querySelector('input[name="user[login]"]').value = id;
          document.querySelector('input[name="user[password]"]').value = pw;
      },
      login,
      password
  );

  // 로그인 버튼 클릭
  await page.click('input[name="commit"]');

  // puppeteer 에게 기다리라고 하는 함수 (default: 300000ms)
  // await page.waitForTimeout(5000);

  // 로그인 실패한 경우 (이미 로컬에 로그인 되어있는 브라우저가 열려있다던지 ..)
  if (page.url() === "https://signin.intra.42.fr/users/sign_in") {
      console.log("로그인 실패");
  }

  // 로그인 성공
  else {

      // 유저정보의 Grade란이 필요하니 유저정보 페이지로 이동
      await page.goto(`https://profile.intra.42.fr/users/유저명`);

      // $ 는 document.querySelector 과 같은 역할을 한다
      // $$ 는 document.querySelectorAll 과 같은 역할을 한다
      const crawl = await page.$(
              "body > div.page > div.page-content.page-content-fluid > div > div.container-item.full-width.profile-item.profile-on-users > div > div.profile-left-box > div.user-primary > div > div.user-infos-sub.margin-top-10 > div:nth-child(5) > span.user-grade-value"
          );

      // 해당 태그의 value를 반환한다
      const grade = await page.evaluate((element) => {
              return element.textContent;
          }, crawl);
      }
  }

  // 브라우저를 닫아준다
  await browser.close();
}



사실 인트라에서 유저 등급을 얻어온다는 아이디어가 좋다 생각해 크롤링을 시작했지만..
너무 느린 인트라 환경 덕에 유저 한명의 등급을 얻어오는데 평균 10초 가량 소비되었다 😕

참 좋은 크롤러지만 정보 하나 받아오는데 너무 긴 관계로 포기하고
귀찮지만 api로 하나하나 받아오면서 검증을 해야겠다 🥲

profile
양질의 코더

0개의 댓글