배경

우리는 로그인을 통해서 유저 이름과 학번을 가져오도록 하였다.

우리가 하려는 방식은 단순히 html을 탐색하는 것이 아니라 session을 이용하여 로그인을 성공한 후에 페이지를 가져와야 하기 때문에 단순 webscraping이 아니다.

그래서 cheerio나 여러 다른 webscraping 모듈로는 한계가 있다고 판단했다.

Spookyjs

webscraping tool인 Casperjs이 node에서는 돌아가지 않는 한계가 있었다.

이를 node에서 casperjs를 가능하게 해준 것이 Spookyjs이다.

그림

일단 spookyjs는 4년 전에 유지보수를 포기한 모듈이다. 그래서 불안전하고 여전히 해결되지 않은 issue들이 상당히 많다….

찾던 중 다른 대안이 없는 듯해서 spookyjs를 사용하기로 했다. 처음에는 로그인도 괜찮고 잘 돌아가는 듯했다.

하지만 서버에 올리고 테스트를 해보니 너무 많은 문제를 보유하고 있어서 spookyjs를 포기하기로 마음 먹었다.

발생한 문제들은 다음과 같다…!

그림 그림

그리고 서버에 계속해서 뭔가 남았다..(내가 코드를 잘못 짠건지 일단 phantomjs가 background에 계속 돌고 있었다.)

결국 다른 크롤링 방법을 찾아보던 중 나온 것이 puppeteer이다..!

Puppeteer

이 친구는 2017년에 대 구글에서 만들어낸 노드를 위한 최강의 웹스크래이핑 서비스이다.

코드도 엄청 직관적이었다.

크롤러가 사람처럼 페이지에서 input에 값을 넣고 버튼을 클릭한 후 page가 넘어가는 것을 기다렸다가 해당 페이지의 정보를 가져올 수 있는 무척이나 편리한 우리한테 너무너무 필요했던 그런 친구이다.

이제라도 나타나줘서 너무 고마웠다.

puppeteer에 대한 매뉴얼 또한 매우 잘 정리 되어있다.

https://pptr.dev/#?product=Puppeteer&version=v1.12.2&show=outline

이를 이용해서 로그인을 체크했다.

puppeteer로 로그인 후 정보 가져오기

코드를 보면 훨씬 잘 다가올 것이다.

다음은 우리학교 홈페이지(히즈넷)에 로그인 후에 이름과 학번을 가져오는 코드이다.

var puppeteer = require('puppeteer');

(async () => {

    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    const hisnet_id = '히즈넷 아이디';
    const hisnet_pw = '히즈넷 비밀번호';

    //페이지로 가라
    await page.goto('https://hisnet.handong.edu/login/login.php');

    //아이디랑 비밀번호 란에 값을 넣어라
    await page.evaluate((id, pw) => {
    document.querySelector('input[name="id"]').value = id;
    document.querySelector('input[name="password"]').value = pw;
    }, hisnet_id, hisnet_pw);

    //로그인 버튼을 클릭해라
    await page.click('input[src="/2012_images/intro/btn_login.gif"]');

    //로그인 화면이 전환될 때까지 .5초만 기다려라
    await page.waitFor(500);

    //로그인 실패시(화면 전환 실패시)
    if(page.url() === 'https://hisnet.handong.edu/login/_login.php'){
        student_id = 'nope';
        name = 'nope';
    }
    //로그인 성공시
    else{
        //학사 페이지로 가서
        await page.goto('https://hisnet.handong.edu/haksa/hakjuk/HHAK110M.php');
        //학번을 가져오고
        const element1 = await page.$('input[name="hakbun"]');
        student_id = await page.evaluate(element1 => element1.value, element1);
        //이름을 가져와라
        const element2 = await page.$('td[width="240"]');
        name = await page.evaluate(element2 => element2.textContent, element2);
    }
    //브라우저 꺼라
    await browser.close();        
})();

다음 코드를 통해서 student_id가 제대로 왔다면 로그인 성공으로 간주했다!

이상 node에 대한 로그인 크롤링 방법이었다. 구글과 puppeteer 개발자님들에게 너무 감사하다!!

바로 구글 스타 ㄱ

그림