본문 바로가기
tech documents/node

[Cheerio],[Axios] 모듈을 사용한 웹 크롤링 - 3

by kimtahen 2020. 4. 3.
반응형

  이전 포스팅에서는, Thebook 서비스의 책 내용에 해당하는 html을 크롤링하여 저장하는 함수까지 완성하였다. 현재로서는 프로젝트 루트에 ./fetching.js 만이 존재할 것이다.

 

  마지막으로, fetching.js 로 크롤링한 Thebook의 책 내용을 읽기 편한 형태로 다시 렌더링하여 html response를 전송하는 express 서버를 제작해보려 한다. 일단. 프로젝트 루트에 ./app.js 파일을 하나 생성한다. 그리고 아래의 코드를 작성한다.

 

./app.js

const express = require('express');
const loading = require('./fetching.js');

const app = express();

app.get('/book', (req, res, err) => {
    const booknum = req.query.id;

    res.writeHead('200', {'Content-Type': 'text/html;charset=utf8'});
    res.write(`<html><head><title>theBook 쉽게보기</title></head><body><div style="width: 700px;margin: 0 auto;">` );
    loading(booknum).then((bookContents)=>{
        res.write(bookContents);
        res.end();
    })

});
app.listen(3000, () => {
    console.log('listening from 3000')
});

실행에 앞서, 터미널로 express 모듈을 설치한다.

npm install express

app.js 코드는 express 모듈을 사용하여 웹 서버를 가동한다. app.get('/book' ... 이 코드는 클라이언트로부터 /book 에 대한 get 요청을 받으면 콜백함수(get 메서드의 두번째 인자)가 실행됨을 의미한다. 쿼리스트링을 통하여 책의 id를 입력받는다. 그러면 ./fetching.js 에서 가져온 loading 함수를 통하여 책 내용에 해당하는 html을 크롤링한다. 이후 크롤링이 완료되었다면 res.write 메서드로 크롤링한 데이터를 클라이언트에게 응답으로 보낸다.

node app.js

터미널에서 app.js를 노드로 실행시키면 

https://localhost:3000 에서 서버를 실행시킬 수 있다.

 

이제 http://localhost:3000/book?id=006982 이 URL로 접속하면 

정상적으로 크롤링이 된 것을 확인할 수 있다.

 

하지만 직접 실행해보면 알 수 있듯이, 크롤링에 많은 시간이 소요된다. 그렇게 때문에 한 번 크롤링 하였다면, 그 크롤링 데이터를 저장해 놓은뒤 다른 접속자가 똑같은 책 id에 요청을 보낼때 사용하는 식으로 코드를 작성하는 편이 로딩 속도나 효율성 측면에서 더 나을 것이다. 따라서 아래와 같이 코드를 수정한다. 

const express = require('express');
const loading = require('./fetching.js');

const app = express();

const ssrData = {};

app.get('/book', (req, res, err) => {
    const booknum = req.query.id;
    res.writeHead('200', {'Content-Type': 'text/html;charset=utf8'});
    res.write(`<html><head><title>theBook 쉽게보기</title></head><body><div style="width: 700px;margin: 0 auto;">` );
    if (!ssrData[booknum]) {
        console.log('making ssr rendering');
        loading(booknum)
            .then(bookContents=>{
                ssrData[booknum] = bookContents;
                res.write(ssrData[booknum]);
                res.write('</div></body></html>');
                res.end();
            })
            .catch(()=>{
                res.write('<h1>404 ERROR</h1>');
                res.write('</div></body></html>');
                res.end();
            })
    } else {
        res.write(ssrData[booknum]);
        res.write('</div></body></html>');
        res.end();
    }

});
app.listen(3000, () => {
    console.log('listening from 3000')
});

ssrData 객체를 생성한다. 크롤링시 데이터를 [책id]: bookContents 이런식으로 저장해서, 다시 같은 id에 대한 요청을 보내면 저장해 놓은 ssrData를 클라이언트에게 보낼 수 있도록 한다. 또한 .catch 메서드를 사용해서 loading 함수의 axios에서 404오류가 발생하면 클라이언트에게 404 ERROR 이라는 문자열을 반환할 수 있도록 한다. 

node app.js

수정한 코드를 다시 실행시켜보자. http://localhost:3000/book?id=006982 이 URL에 접속하면, 크롤링에 많은 시간이 소요된다. 로드가 된 후, 브라우저의 탭을 하나 더 열어서 같은 URL 로 접속하면, 훨씬 빠르게 로딩 되는 것을 확인할 수 있다.

 

반응형

댓글