728x90
반응형

이전 포스팅에서 express의 미들웨어와 라우터 차이점에 대해서

 

미들웨어는 서버와 클라이언트 간의 중간 매개 역할을 담당합니다

그래서 서버 api 요청할 경우 미들웨어에서 공통업무를 할 수 있게 합니다

에러 페이지, 존재하지 않는 페이지 등

 

조금 더 상세한 정보를 알고 싶으시면 아래의 링크를 확인해주시길 바랍니다

 

 

 

2022.09.16 - [IT_Web/Nodejs] - Node express 서버의 미들웨어, 라우터 개념 제대로 알기 및 next함수 활용하기

 

Node express 서버의 미들웨어, 라우터 개념 제대로 알기 및 next함수 활용하기

이전 포스팅에서 express 서버 미들웨어 적용에 대해서 미들웨어가 무엇이며, 미들웨어를 어떻게 활용하는지에 대해서 알아보았습니다 미들웨어를 사용함에 있어 라우팅이 호출될 때 공통적으로

tantangerine.tistory.com

 


 

Express 라우터 url 파라미터 및 쿼리스트링 컨트롤 하기

 

라우터에서 서버 api요청 시 url의 파라미터와 쿼리 스트링을 제어할 수 있습니다

 

이 방법은 페이지를 이동하거나

서버에 요청하여 통신을 할 때 필요한 값을 전달할 때 자주 사용합니다

 

 


 

파라미터(parameters)란

 

번역하면 매개 변수라고 하며

url의 주소에 어떠한 특정한 값을 변수에 담아 유동적으로 

변화하는 값을 사용합니다

그래서 아래와 같이 '/top/:page'를 사용하면

/top/ 이후의 값은 변수에 담겨 라우터에서 사용이 가능합니다

 

 


 

쿼리스트링(Query String)

 

Query만 번역하면 의문,

String 컴퓨터 자료형으로 해석하면 문자를 의미합니다

그래서 이 두 가지를 합치면 의문 문자라고 해서

'/top/:page?id=컴퓨터&name=삼성'

위의 방식으로 의문(?)부터 시작된 문자를 쿼리 스트링이라고 합니다

 

 


코드 분석

 

그럼 코드를 보면서 나머지를 설명하겠습니다

아래와 같이 코드를 작성하고 npm start를 시작합니다

 

npm init, npm i express, npm i -d nodemon 등 설치는 

이전 포스팅을 찾아보시면 나와있으니 확인 부탁드립니다

 

 

const express = require('express');

const app = express();
app.set('port', process.env.PORT || 3000);

app.get('/top/:page', (req, res, next) => {
  console.log('top params: ', req.params)
  console.log('top queryString: ', req.query)
  res.send(`top: ${req.params.page} / id: ${req.query.id} name: ${req.query.name}`)
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '번 포트에서 대기 중');
});

 

 

 

위와 같이 실행하면 아래와 같이 이미지가 브라우저 및 콘솔 창에 노출됩니다

http://localhost:3000/top/head를 주소창에 입력했을 경우 

console.log함수에 노출되는 정보를 확인할 수 있습니다 

 

 

 

express_파라미터_쿼리스트링_1
express_파라미터_쿼리스트링 브라우저 확인

 

 

req.params, req.query로 접근해서 파라미터와 쿼리스트링을 가져올 수 있습니다

그리고 undefined가 발생하는 값을

브라우저 주소창에 http://localhost:3000/top/head?id=컴퓨터&name=삼성

입력하게 된다면 id, name 값이 할당될 것입니다

그 값은 아래의 이미지에서 확인할 수 있습니다

 

 

express_파라미터_쿼리스트링_2
express_파라미터_쿼리스트링 데이터

 

 

위의 데이터를 확인하고 아래와 같이 노출할 수 있는

코드를 작성할 수 있습니다

 

 

express_파라미터_쿼리스트링 브라우저 노출확인

 

 


이렇게 오늘은 파라미터와 쿼리스트링을 활용하는 방법을 알아보았습니다

 

그렇게 어렵지 않으며 nodeexpress 말고도 자바에서도 비슷한 방식으로

사용하고 있는 것만 알고 계시면 될 것 같습니다

 

하루에 1포스팅을 실천하기 위해 

공부도 나름 동기부여도 되는 것 같습니다

 

그럼 같이 파이팅 하시고 힘내세요!

우리의 IT 대모험 멀고도 머니깐요

 

 

728x90
반응형
728x90
반응형

이전 포스팅에서 express 서버 미들웨어 적용에 대해서

 

미들웨어가 무엇이며, 미들웨어를 어떻게 활용하는지에 대해서 알아보았습니다

미들웨어를 사용함에 있어 라우팅이 호출될 때 공통적으로 처리하거나

에러 미들웨어를 만들어 에러 발생 시 특정 함수를 실행하는 등

공통적인 부분을 담당하고 있는 미들웨어를 적용해보았습니다

 

더 상세한 정보를 알고 싶으시다면 아래의 링크를 확인해보세요

 

 

2022.09.15 - [IT_Web/Nodejs] - Node에서 express 서버 미들웨어 적용하기 그리고 middleware를 쓰는 이유가 뭘까??

 

Node에서 express 서버 미들웨어 적용하기 그리고 middleware를 쓰는 이유가 뭘까??

이전 포스팅 express 패키지 활용하여 서버 구축 및 html 서빙에 대해서 express에서 html 서빙 방법은 정말 간단합니다 express 내에서 html관련 패키지를 사용하고 있어 개발자들은 단지 메서드를 호출

tantangerine.tistory.com

 

 

express에서 미들웨어와 라우터 개념 제대로 알기

 

다른 개발자 분들은 use함수가 미들웨어가 아니라

get 함수 등(이외에도 많은 것들이 있습니다 post 등)

함수 내의 콜백 함수가 미들웨어라고 말하시는 분들이 있습니다

 

충분히 그렇게 생각할 수도 있지만

제 생각은 조금 다릅니다

 

미들웨어는 use 함수이며

라우터는 get 함수가 맞다고 생각합니다

 

그 이유는 미들웨어 격인 use 함수는 

라우터 함수가 호출될 때를 감지해서 우선 실행되는 함수입니다

클라이언트와 서버 간에 중간 매개 역할을 하여 컨트롤이 가능합니다

그래서 use 함수 자체가 미들웨어라고 할 수 있습니다

 

그리고 next 함수는 라우터와 미들웨어에서 편의성을 위한 기능일 뿐이라는 것입니다

 

그리고 엄연히 따지면 get 함수도 라우터가 아닌 서버 api 호출 문으로도 해석이 가능합니다

하지만 지금 현재 브라우저 주소 url서버의 연동하여 페이지를 전송받기 때문

라우터라고 부르는 것이 더 합리적일 것입니다 

 

 

 

express 서버 미들웨어와 라우터에 있는 콜백 함수 next 활용법

 

콜백 함수 next 함수를 호출하면

 

최우선 호출되는 것은 자신의 또 다른 콜백 함수가 호출됩니다

하지만 자신의 콜백 함수를 호출하지 않고 다음 미들웨어나 라우터 함수를 호출하기 위해서는 

next('route')로 인자 값을 'route'로 입력하는 것입니다

 

하지만 이때 미들웨어인 use함수는 다음 미들웨어나 라우터 함수를 호출하는 것이 아닌

자신의 콜백 함수를 다시 호출한다는 점이 미들웨어와 라우터가 다른 기능입니다

 

* 미들웨어에서 next('route')를 호출하면 자기 콜백 함수를 우선 호출하고

그다음 라우터를 실행하게 됩니다 

 

 

그럼 아래의 코드를 실행해 봅시다

 

 

const express = require('express');
const path = require('path');

const app = express();
app.set('port', process.env.PORT || 3000);

app.use((req, res, next) => {
  try {
    console.log('express server: use ::: 1')
    next('route')
  } catch (error) {
    console.log('express server: error ::: use ::: 1', error)
    next(error)
  }
}, (req, res, next) => {
  console.log('express server: use ::: 2')
   next()
})

app.get('/', (req, res, next) => {
  try {
    console.log('express server: main ::: 1')
    if(true){
      next('route')
    } else {
      next()
    }
  } catch (error) {
    console.log('express server: error ::: main ::: 1', error)
    next(error)
  }
}, (req, res, next) => {
  console.log('express server: main ::: 2')
  next()
})

app.get('/', (req, res, next) => {
  try {
    res.json({ page: 'main'})
    console.log('express server: main ::: 3')
  } catch (error) {
    console.log('express server: error ::: main :: 3', error)
    next(error)
  }
});

app.get('/top', (req, res, next) => {
  try {
    console.log('express server: top ::: 3')
    res.json({ page: 'top'})
  } catch (error) {
    console.log('express server: error ::: top', error)
    next(error)
  }
});

app.use((req, res, next) => { 
  res.status(404).send('존재하지 않는 페이지 입니다(404)')
});

app.use((error, req, res, next) => {
  res.send('error 발생')
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '번 포트에서 대기 중');
});

 

 

그럼 아래처럼 화면이 노출됩니다

 

미들웨어에서 next()를 사용해서 use ::: 1, use ::: 2 함수가 실행되며

그다음 main ::: 1 함수가 실행되고

main ::: 2는 건너뛰고

 main ::: 3 함수가 실행됩니다

 

 

 

 

이렇게 미들웨어와 라우터 제어하는 함수를 알아보았습니다

next함수 활용법과 라우터와 미들웨어 둘의 차이점을 알아보았습니다

 

라우터와 미들웨어에 존재하는 next함수에 대해 이야기하고 넘어가야겠습니다

express 공부한 지 얼마 안 되었지만

 

그렇게 좋은지 알 수가 없었습니다

 

next함수만 보더라도 라우터 get함수의 콜백 함수 next와 

미들웨어 use함수의 콜백 함수 next는 활용방식이 너무나도 다릅니다

 

use함수 내에서는 next('route') 통하지 않고

자기 내부의 콜백 함수를 다시 호출하게 됩니다

 

이렇게 동일한 네이밍을 가진 함수인자 값으로만

기능이 구분되는 것은 좋지 않은 방식입니다

 

그리고 use 함수의 에러 미들웨어 기능

동일한 use 함수에서 매개변수 인자 값의 개수 4개면

에러 미들웨어의 기능을 구현하게 된다는 것입니다

 

이 경우 인자 값을 누락하게 된다면 에러가 발생하거나 

전혀 생각지도 않은 기능이 구현된다는 것입니다 

 

애초에 use 함수가 아닌 확실하게 구분할 수 있는 네이밍이었다면

더 좋을 것 같다같다는 생각이었습니다

 

 


 

 

express 서버를 공부하면서

모듈을 조합해서 만든 라이브러리라는 것을 느꼈습니다

하지만 이런 것도 공부가 되리라 생각합니다

 

여러 언어를 배우면서 생각의 전환을 하거나

약간 내가 생각지도 못한 것들을 생각하게 한다는 것이지요

그러면서 저의 실력도 늘어나는 것이 아닐까 합니다

 

그럼 어려운 공부 조금 더 힘내셔서

우리의 IT 대모험을 헤쳐나가시길 기대합니다

 

그럼 다음 포스팅도 기대해주세요!

 

 

 

728x90
반응형
728x90
반응형

이전 포스팅 express 패키지 활용하여 서버 구축 및 html 서빙에 대해서

 

express에서 html 서빙 방법은 정말 간단합니다

express 내에서 html관련 패키지를 사용하고 있어

개발자들은 단지 메서드를 호출하는 것만으로 html 서빙을 할 수 있습니다

 

조금 더 자세한 내용을 알고 싶으시다면 아래의 링크를 클릭하시길 바랍니다

 

2022.09.14 - [IT_Web/Nodejs] - Node활용해서 express 서버로 HTML 노출 및 서빙하기

 

Node활용해서 express 서버로 HTML 노출 및 서빙하기

이전 글 Npm이 무엇이며 활용법에 대해서 node에서 npm을 빼고는 말을 할 수 없을 정도로 중요한 부분을 차지합니다 그 이유는 많은 사람들이 개발한 오픈 소스를 관리해 주기 때문이지요 npm을 잘

tantangerine.tistory.com

 

 

지금 글은 이전 포스팅과 이어지는 부분이 있으니

이전 포스팅이  궁금하시거나 필요한 부분이 있으면 위의 링크를 클릭하시길 바랍니다

 


 

express 서버 미들웨어 적용하기

 

일단 미들웨어란 무엇일까요??

 

사전적 의미로는 양 쪽을 연결하여 데이터를 주고받을 수 있도록

중간 매개 역할을 하는 소프트웨어라고 할 수 있습니다

 

 express 서버의 미들웨어는 중간 매개 역할이 핵심이라고 할 수 있습니다

아래의 app.get() 메서드를 라우팅이라고 합니다

 

라우팅을 할 경우 에러가 발생할 경우

특정 api url이 호출될 경우

존재하지 않은 api url 호출될 경우

 

특정 함수를 실행,

에러 페이지를 노출,

특정 페이지를 노출 등

 

여러 가지의 공통 작업을 할 수 있습니다

 

 

express 서버 미들웨어 적용하기

 

아래의 코드를 보시면 app.use()가 정의되어있습니다

이 함수는 라우팅을 호출할 경우 app.use()가 실행합니다

 

즉, 라우팅 get()은 함수의 인자 값이

클라이언트에서 보낸 api 호출 url이 동일한 라우팅이 실행됩니다

 

이때 라우팅이 호출되면 라우팅 get()보다 

우선 use()인 미들웨어가 호출을 감지하여 우선 실행합니다

그리고 next()를 실행하게 되면서 다음 미들웨어나 라우팅이 실행됩니다

 

이때 미들웨어의 위치도 중요합니다

 

기본적으로 실행 순서는 위에서부터 아래까지 실행합니다

그래서 라우팅이 호출될 때마다 미들웨어인 use()최상단부터 하단까지 실행된다고 생각하시면 됩니다

 

하지만 라우팅보다 미들웨어가 아래에 있다면 라우팅이 실행이 끝나는 순간

더 이상 실행하지 않고 종료가 됩니다

 

아래의 코드를 보면서 더 설명을 이어가겠습니다

 

 

 

const express = require('express');
const path = require('path');

const app = express();
app.set('port', process.env.PORT || 3000);

app.use((req, res, next) => {
  console.log('Hello, Express ::: 1');
  next()
},(req, res, next) => {
  console.log('Hello, Express ::: 2');
  next()
},(req, res, next) => {
  console.log('Hello, Express ::: 3');
  next()
})

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, '/index.html'));
});

app.use((req, res) => { 
  res.send('페이지 호출 오류')
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '번 포트에서 대기 중');
});

 

 

위의 코드를 작성하고 npm start를 입력하고

인터넷 브라우저 주소창에 "http://localhost:3000/"를 입력하게 되면

 

아래와 같이 커맨드 창이 노출됩니다

 

express_미들웨어_적용
express 라우팅 적용 결과

 

오른쪽에 보시면 최상단에 위치한 미들웨어부터 실행되며

그다음 라우팅이 호출되어 

주소창에 http://localhost:3000/"/"이 부분이 라우팅에 감지되어 위와 같은 결과가 노출됩니다

하지만 여기서 "/top"를 입력하면 아래와 같이 노출됩니다

 

 

express_미들웨어_적용2
express 미들웨어 적용 결과

 

top라는 라우팅 호출 주소가 동일하지 않아

최하단에 위치한 미들웨어가 실행되어 페이지 호출 오류 문구가 노출됩니다

 

이 결과 라우팅이 실행되지 않으면 미들웨어가 반응한다는 것을 알 수 있습니다

 

그리고 미들웨어 또한 호출 url주소를 감지할 수 있습니다

아래와 같이 코드를 변경해보도록 하겠습니다

 

express_미들웨어_적용3
express 미들웨어 호출 url 주소제어

 

위와 같이 코드를 변경하고 실행한 다음

브라우저 주소창 "http://localhost:3000/"를 입력합니다

 

위의 결과와는 다르게 커맨드 창에 최상단 미들웨어가 실행되지 않은 현상을 확인할 수 있습니다

 

express_미들웨어_적용6
express 미들웨어 url 주소 함수 결과

 

브라우저 주소창에 "http://localhost:3000/top"를 입력하면

아래와 같이 커맨드 창이 노출되는 것을 확인할 수 있습니다

 

express_미들웨어_적용4
express 미들웨어 url 주소제어 결과

 


 

 

 

미들웨어 에러 미들웨어 적용하기

 

이번에는 라우팅 내에서 Error가 발생할 경우 

제어하는 에러 미들웨어를 만들어 보겠습니다

 

 

const express = require('express');
const path = require('path');

const app = express();
app.set('port', process.env.PORT || 3000);

app.get('/', (req, res) => {
  try {
    csole.log('Hello, Express ::: 1');
    res.sendFile(path.join(__dirname, '/index.html'));
  } catch (e) {
    console.log('Error, Express ::: 00', e)
    throw new Error(e)
  }
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '번 포트에서 대기 중');
});

 

 

위의 코드를 실행하고 브라우저도 이전과 같은 주소를 입력합니다

그럼 아래와 같은 화면을 노출합니다

 

console.log()를 철자가 틀리게 일부러 코드 작성하였습니다

그래서 에러가 발생하였습니다

 

express에서는 기본적으로 에러가 발생하면 아래와 같이 화면을 처리합니다

하지만 아래와 같은 에러 페이지서버의 디렉터리 구조가 상세히 명세되어있습니다

그렇기 때문에 보안상 취약할 수밖에 없기 때문에 직접 처리해야 합니다

 

 

express_에러_미들웨어_적용
express 라우터 에러 발생 페이지

 

에러 미들웨어는 아래와 같이 코드를  최하단에 추가합니다

*app.listen() 위에 추가하셔야 합니다

 

코드 추가할 경우 error와 next매개변수의 위치를 꼭 지켜주셔야

에러 미들웨어를 구현할 수 있습니다

 

 

express_에러_미들웨어_적용2
에러 미들웨어 코드 적용

 

아래와 같이 에러 페이지를 노출됩니다

 

 

express_에러_미들웨어_결과
에러 미들웨어 결과 페이지

 

 


 

미들웨어 http 상태 코드 제어하기

 

아래와 같이 코드를 추가합니다

미들웨어는 next를 추가하는 것을 꼭 확인하세요 

 

 

express_미들웨어_http_상태코드제어_적용
미들웨어 http 상태 코드 제어 코드

 

위와 같이 status(404)라고 호출한다면

아래와 같이 404로 http 상태 코드가 변한 것을 확인할 수 있습니다

미들웨어를 실행하면 에러가 아니기 때문에

위의 코드를 적용하지 않는다면 200번 코드가 표시됩니다

 

express_미들웨어_http_상태코드제어
미들웨어 http 상태 코드 적용 결과

 

 

 

이것을 활용한다면 클라이언트에 모든 http 상태 코드일괄적으로 설정해서 보낼 수 있습니다

 

그렇게 일괄적으로 보내게 되면 개발하는데 어려움이 있을 수 있습니다

 

다만, 운영 단계의 서비스 경우에는

모든 에러가 404로 보내게 되면

해커들에게는 지금 어떤 에러가 발생하는지 알 수 없기 때문입니다

 

보안으로는 좋은 면이 있습니다

 

 


 

 

node에서 express는 아주 많이 사용되고 있으며,

서브 웹 서버로도 많이 사용하고 있습니다

 

SI 개발자라면 node보다는 자바를 많이 사용하며,

최근 react로 개발하는 프로젝트가 많아지면서 

node의 중요성도 조금씩 높아지고

자연스레 express의 서브 웹 서버로써 활용도가

조금씩  높아지고 있습니다

 

SI 개발자라면 어떤 언어라도 공부를 해야겠지요

그러니 흥미가 가는 언어는 아무거나 공부를 하셔도 됩니다!

 

도움 안 되는 공부는 없으니까요

 

그렇게 공부하다 보면 코드를 간결하게 되며 함수적 프로그래밍도

자연스레 몸으로 습득할 수 있을 것입니다

 

그럼 우리의 IT 대모험을 위해서

파이팅 하시길 바랍니다

 

그럼 다음 포스팅에서 뵙겠습니다

728x90
반응형
728x90
반응형

이전 글 Npm이 무엇이며 활용법에 대해서

node에서 npm을 빼고는 말을 할 수 없을 정도로 중요한 부분을 차지합니다

그 이유는 많은 사람들이 개발한 오픈 소스를 관리해 주기 때문이지요

 

npm을 잘 활용한다고 하면 패키지를 어떻게 잘 관리할지에 대해서

조금은 생각을 하고 있는 사람이 아닐까 합니다

 

더 자세한 사항을 알고 싶으시다면 아래의 링크를 클릭하시길 바랍니다 

 

 

2022.09.10 - [IT_Web/Nodejs] - Node에서 중요한 NPM은 무엇이며, 그 활용법을 알아보자

 

Node에서 중요한 NPM은 무엇이며, 그 활용법을 알아보자

이전 포스팅 puppeteer 활용해서 웹크롤링에 대해서 웹크롤링은 업무적으로도 필요한 경우가 있습니다 그리고 배우는 것만으로도 충분히 재미를 느낄 수 있다고 생각합니다 그리고 웹크롤링은 비

tantangerine.tistory.com

 


 

Nodejs 활용해서 express 서버 구축하기

 

우선 처음 프로젝트를 만들 때 무엇을 해야 할지 모를 경우가 많습니다

일단 처음 node를 설치하였다면 프로젝트를 진행할 폴더에서

npm init을 하여 간단한 물음에 답을 합니다

 

그렇게 하면 package.json 생성되고

필요한 패키지를 설치하여 프로젝트를 진행합니다

 

그럼 파일이 생성되어 아래와 같은 구조를 가지게 될 것입니다

(index.html은 제가 미리 만든 파일입니다)

 

express_파일구조
파일 구조

 

그럼 express를 간단히 구현해 보도록 하겠습니다

 

먼저 개발에 유용한 패키지 nodemon을 설치하여 진행하겠습니다 

 

npm i -D nodemon

 

nodemon은 파일을 저장할 때마다 다시 npm start를 하지 않고

소스코드를 반영할 수 있게 하는 패키지입니다

 

아래와 같이 scripts를 설정하시고 진행하시길 바랍니다

 

express_package_파일정보
package.json 파일 정보

 


 

express 패키지 사용하기

 

커맨드 창에서 아래와 같이 패키지를 설치합니다

 

npm i express

 

아래와 같이 express패키지를 불러옵니다

require()node에서 모듈을 불러올 경우 사용할 수 있습니다

 

프로젝트 내에서 모듈을 불러올 수도 있으며,

npm이 관리하는 패키지일 경우에는

패키지명을 인자 값으로 할당해서 패키지를 불러올 수 있습니다

 

아래와 같이 서버를 만들고 

app.set()를 만들어서 port번호를 설정하게 됩니다

 

*env는 추후에 다시 설명해드리겠습니다

 

const express = require('express');
const path = require('path');

const app = express();
app.set('port', process.env.PORT || 3000);

app.get('/', (req, res) => {
  console.log('req: ', req)
  console.log('res: ', res)
  res.send(`Wellcome, Express Server`);
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '번 포트에서 대기 중');
});

 


 

express로 html 서빙하기

 

 

그럼 인터넷 브라우저를 열어 주소창에 "http://localhost:3000/" 입력합니다

 

아래와 같이 화면이 노출될 것입니다

왜 이렇게 노출될까요?

 

express_html_노출
express 노출 화면

 

아래의 app.get()는 라우터라는 명칭으로 서버에서 선언하여 사용합니다

이때 api 호출 방식은 get방식, post방식이 있습니다

 

*get방식 post방식의 차이는 추 후에 다시 설명해 드리겠습니다

 

그 라우터는 첫 번째 인자 값에 api 호출받을 주소를 지정하여

get방식을 호출하는 api 주소가 동일할 경우  두 번째 인자 값인 콜백 함수가 실행됩니다 

 

그 콜백 함수에서 (req, res) 두 개의 매개변수가 보일 것입니다

 

이 두 개의 매개변수의 정보들을 보면 화면이 왜 그렇게 노출되는지에 대한

궁금증을 풀 수 있을 것 같습니다 

 

아래의 코드에 제가 console.log를 호출해 놓았습니다

그럼 콘솔 창에 어떤 정보가 있는지 확인해 봅시다

 

 

express_get_변경
express 콘솔 찍어보기

 

 

아래는 req에 대한 정보가 json Object형으로  담겨있습니다

req정보는 클라이언트에서 요청할 때 보낸 정보들이 담겨있는 것을 알 수 있습니다

아래에 statusCode, url, params, query, route 등등 유용한 정보들이 있습니다

 

express_req_정보
express req 정보

 

 

그럼 실제 클라이언트에서는 어떻게 보내고 있는지 한번 확인해볼까요?

F12키를 눌러서 개발자 모드에서 api요청 보낸 정보들이 헤더에 담겨있는 것을 확인할 수 있습니다

 

 

express_클라이언트_요청
express 클라이언트 api요청 상세정보

 

그리고 두 번째 매개변수 res의 정보를 보겠습니다

res는 express에서 자체적으로 사용하는 패키지와 모듈이 있습니다

 

 

당연 req에서 받은 정보들도 res에서도 사용할 수 있도록 저장되어있으며

html을 기본 코드들이 내장되어있어

res.send()에서 매개변수 인자 값으로 문자열을 할당할 경우

그 인자 값의 정보들이 내장된 html 코드와 같이 페이지를 노출하게 됩니다

 

결과 값은 아래와 같습니다

 

express_html_자체서빙하기
express 자체 내장 html 서빙 화면

 

이 것을 이용해서 html 파일을 미리 만들어서 사용할 수 있습니다

위에 제가 미리 만들어 놓은 html은 확인하셨을 것입니다

 

 index.html을 아래와 같이 코드 작업을 합니다

 

 

<html>
<head>
  <meta charset="UTF-8" />
  <title>Express Server</title>
</head>
<body>
  <h1>Express Server</h1>
  <p>환영합니다.</p>
</body>
</html>

 

그리고 아래처럼 res.sendFile()를 활용해서 경로를 적용해서 매서드를 호출합니다

path node의 패키지로 프로젝트의 경로를 찾아 할당하기 유용한 패키지입니다

 

app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, '/index.html')); // 변경코드
});

 

코드를 변경했다면 아래와 같이 변경된 화면을 확인할 수 있습니다

 

 

express_html서빙하기
HTML 파일 읽기로 HTML 서빙결과

 

 


 

 

express 서버 구현하는 것을 알아보았습니다

아직 미들웨어, DB 연동, 세분화된 라우터, 세션, 쿠키 활용 등

아직 갈길이 멀기만 합니다

 

블로그에 포스팅을 업로드할 때마다

콘텐츠를 걱정하는 블로거들이 많다고 합니다

하지만 저는 그런 걱정은 별로 안 하는 것 같습니다

그저 제가 공부한 것들이나 알고 있는 것들을 풀기만 하면 되니깐요

 

그래서 요즘은 블로그에 글을 쓰려고 공부하는지 공부하려고 글을 쓰는지

알 수 없을 정도가 되었습니다

 

하지만 그것 또한 저 한태는 좋은 영향을 주는 것 같습니다

동기부여와 더 진취적으로 변해가는 저의 모습을 보니깐요

 

1일 1 포스팅이 왜 어려운지 요즘 많이 생각하게 됩니다

 

앞으로도 꾸준할 수 있도록 노력하겠습니다

그러니 다 같이 파이팅 하시길 바랍니다

 

우리의 IT 대모험은 아직 끝나지 않았으니까요!

 

그럼 다음 글에서 뵙겠습니다

728x90
반응형
728x90
반응형

이전 포스팅 웹 크롤링 로그인 로그아웃에 대하여

로그인과 로그아웃에 대하여 알아보았습니다

코드를 함수형으로 만들어서 이전 코드보다 간결하게 만들어 보았지요

그리고 웹 크롤링에서는 무엇보다

태그를 찾는것중요하여 같이 알아보았습니다

 

좀 더 상세히 알고 싶으시다면 아래의 링크를 클릭하시길 바랍니다

 

 

2022.08.29 - [IT_Web/Nodejs] - 웹 크롤링 로그인, 로그아웃 그리고 waitForResponse 응답대기 활용하기 및 태그찾기, 태그 값 할당

 

웹 크롤링 로그인, 로그아웃 그리고 waitForResponse 응답대기 활용하기 및 태그찾기, 태그 값 할당

이전 포스팅에서 웹 크롤링 인피니트 스크롤링이 무엇인가 알아보았으며, 인피니트 스크롤링이 적용된 페이지에 대해서 이미지를 다운하고 파일로 만드는 방법을 알아보았습니다 인스타그램,

tantangerine.tistory.com

 

 

앞서 웹 크롤링에서 중요한것은 태그를 찾는것이라 했습니다

하지만 중요한것이 하나 더있습니다

그것은 바로 비동기입니다

하지만 비동기에서도 순ㅍ차적으로 실행할지 비순차적으로 할것인지가 중요합니다

웹 크롤링할 경우 순차적으로 진행할 경우가 많기 때문에 비동기식이며 순차적인 방법이 중요합니다

 

이전 포스팅에서는 로그인할경우 아이디를 inputvalue에 할당하여 한번에 아이디의 문자열이 모두 들어갔습니다

하지만 그렇게 된다면 유저가아닌 봇으로 의심을 받아 제재를 받을 수 있습니다 

그래서 이 부분을 함수형으로 만들어 간결하게 만들어봅시다

 

아래 handleWriteInput 함수를 만들어서 process.env.EMAIL을 id로 받아서 id를 확장 연산자를 사용해서

배열로 만들어서 로그인창에서 한글자씩 시간을 두고 글자를 입력하게됩니다

좀 더 자세한것은 아래에서 확인해보겠습니다

 

 

const puppeteer = require('puppeteer');
const writekeyboardList = require('./writekeyboardList');
const dotenv = require('dotenv'); // npm i dotenv
dotenv.config();

const setCrawler = async () => {
  const browser = await puppeteer.launch({
    headless: false,
    args:['--window-size=1920,1080']
  });
  const page = await browser.newPage();
  await page.setViewport({
    width: 1080,
    height:1080,
  })

  const handleWriteInuput = async (selector, id) => {
    const writeList = writekeyboardList()
    const idOfList = [...id]
    await page.click(selector);
    console.log(`idOfList`, idOfList)
      for (const id of idOfList) {
        const inputValue = await writeList.filter(element => element.ShiftLeft === id || element.key === id )
        if (inputValue.length > 0) {
          const code = inputValue[0].code
          const ShiftLeft = inputValue[0].ShiftLeft === id ? 'ShiftLeft' : ''
          if (ShiftLeft) {
            await page.keyboard.down(ShiftLeft);
            await setTime(selector, 500)
            await page.keyboard.press(code);
            await setTime(selector,500)
            await page.keyboard.up(ShiftLeft);
          } else {
            await page.keyboard.press(code);
          }
          await setTime(selector,500)
        }
      }
  }

  const inputValue = async (selector, value) => {
    await page.evaluate((selector, value) => {
      document.querySelector(selector).value = value
    }, selector, value)
    await setTime(selector)
  }

  const buttonClick = async (selector, nextSelector, type) => {
    await page.evaluate((selector) => {
      document.querySelector(selector).click();
    }, selector)
    if(type === 'login'){
      // waitForRequest(요청 대기), waitForResponse(응답 대기)
      const res = await page.waitForResponse(res => {
        return res.url().includes('graphql')
      })
      const result = await res.json()
      console.log('login', result);
      if(await result.extensions.is_final){
        await setTime(type, 2000)
        await page.keyboard.press('Escape')
      }
    } else if(type === 'logOut'){
      await page.waitForNavigation()
    } else {
      if(nextSelector){
        await page.waitForSelector(nextSelector)
      }
      await setTime(selector)
    }
  }

  const setTime = async (selector = 'normal', waitTime = 0) => {
    const setTime = await page.evaluate(async(waitTime) => {
      const timeList = await [3975, 4547, 5231, 6397, 7894, 3394, 4206, 5147, 6932, 7430, 3561, 4896, 5877, 6407, 7133];
      let randomTime = await timeList[Math.floor(Math.random() * timeList.length)]
      if (waitTime > 0) randomTime = waitTime
      await new Promise(r => setTimeout(r, randomTime))
      return randomTime
    }, waitTime)
    console.log(`waitTime[${selector}]: `, setTime)
    return setTime
  } 
  return { buttonClick, inputValue, handleWriteInuput, setTime, page: page, browser: browser }
}


const crawler = async () => {
  try {
    const { buttonClick, inputValue, handleWriteInuput, setTime, page, browser } = await setCrawler();
    await page.goto('https://facebook.com');

    const id = await process.env.EMAIL;
    const password = await process.env.PASSWORD;
    
    // 로그인
    //await inputValue('#email', id);
    handleWriteInuput('#email', id)
    await inputValue('#pass', password);
    await buttonClick('[name="login"]', '', 'login');
   

    // 로그아웃
    await buttonClick('.i8zpp7h3', '.i1n1lj7b.mmwt03ec');
    await buttonClick('.i1n1lj7b.mmwt03ec > div:last-child > div', '', 'logOut')
    await page.close();
    await browser.close();
  } catch (e) {
    console.log(e);
  }
}

crawler()

 

 

아래의 함수를 확인하면 각자의 역할들이 존재합니다

아래에서 차근차근 설명해 보겠습니다

 

웹크롤링-키보드코드
키보드 코드 사용하여 입력하기 함수형!

 

 

먼저 빨강 테두리의 함수는 키보드 코드 리스트가 담겨져 있으며,

require()를 사용해서 파일에 접근해서 함수를 사용할 수 있게 합니다

 

 

웹크롤링-nodejs
웹크롤링 키보드 코드 파일

 

 

파일에는 아래와 같은 함수가 export되고 있습니다

code가 위의 keyboard.press()의 매개변수 인자값이 되며

Shift를 누른 상태 값은 ShiftLeft의 값이 대체되어 값이 입력된다

 

 

 

 

module.exports = function writekeyboardList() {
  const keyboard = [
    {'keyCode': 48, 'code': 'Digit0', 'ShiftLeft': ')', 'key': '0'},
    {'keyCode': 49, 'code': 'Digit1', 'ShiftLeft': '!', 'key': '1'},
    {'keyCode': 50, 'code': 'Digit2', 'ShiftLeft': '@', 'key': '2'},
    {'keyCode': 51, 'code': 'Digit3', 'ShiftLeft': '#', 'key': '3'},
    {'keyCode': 52, 'code': 'Digit4', 'ShiftLeft': '$', 'key': '4'},
    {'keyCode': 53, 'code': 'Digit5', 'ShiftLeft': '%', 'key': '5'},
    {'keyCode': 54, 'code': 'Digit6', 'ShiftLeft': '^', 'key': '6'},
    {'keyCode': 55, 'code': 'Digit7', 'ShiftLeft': '&', 'key': '7'},
    {'keyCode': 56, 'code': 'Digit8', 'ShiftLeft': '*', 'key': '8'},
    {'keyCode': 57, 'code': 'Digit9', 'ShiftLeft': '\(', 'key': '9'},
    {'keyCode': 65, 'code': 'KeyA', 'ShiftLeft': 'A', 'key': 'a'},
    {'keyCode': 66, 'code': 'KeyB', 'ShiftLeft': 'B', 'key': 'b'},
    {'keyCode': 67, 'code': 'KeyC', 'ShiftLeft': 'C', 'key': 'c'},
    {'keyCode': 68, 'code': 'KeyD', 'ShiftLeft': 'D', 'key': 'd'},
    {'keyCode': 69, 'code': 'KeyE', 'ShiftLeft': 'E', 'key': 'e'},
    {'keyCode': 70, 'code': 'KeyF', 'ShiftLeft': 'F', 'key': 'f'},
    {'keyCode': 71, 'code': 'KeyG', 'ShiftLeft': 'G', 'key': 'g'},
    {'keyCode': 72, 'code': 'KeyH', 'ShiftLeft': 'H', 'key': 'h'},
    {'keyCode': 73, 'code': 'KeyI', 'ShiftLeft': 'I', 'key': 'i'},
    {'keyCode': 74, 'code': 'KeyJ', 'ShiftLeft': 'J', 'key': 'j'},
    {'keyCode': 75, 'code': 'KeyK', 'ShiftLeft': 'K', 'key': 'k'},
    {'keyCode': 76, 'code': 'KeyL', 'ShiftLeft': 'L', 'key': 'l'},
    {'keyCode': 77, 'code': 'KeyM', 'ShiftLeft': 'M', 'key': 'm'},
    {'keyCode': 78, 'code': 'KeyN', 'ShiftLeft': 'N', 'key': 'n'},
    {'keyCode': 79, 'code': 'KeyO', 'ShiftLeft': 'O', 'key': 'o'},
    {'keyCode': 80, 'code': 'KeyP', 'ShiftLeft': 'P', 'key': 'p'},
    {'keyCode': 81, 'code': 'KeyQ', 'ShiftLeft': 'Q', 'key': 'q'},
    {'keyCode': 82, 'code': 'KeyR', 'ShiftLeft': 'R', 'key': 'r'},
    {'keyCode': 83, 'code': 'KeyS', 'ShiftLeft': 'S', 'key': 's'},
    {'keyCode': 84, 'code': 'KeyT', 'ShiftLeft': 'T', 'key': 't'},
    {'keyCode': 85, 'code': 'KeyU', 'ShiftLeft': 'U', 'key': 'u'},
    {'keyCode': 86, 'code': 'KeyV', 'ShiftLeft': 'V', 'key': 'v'},
    {'keyCode': 87, 'code': 'KeyW', 'ShiftLeft': 'W', 'key': 'w'},
    {'keyCode': 88, 'code': 'KeyX', 'ShiftLeft': 'X', 'key': 'x'},
    {'keyCode': 89, 'code': 'KeyY', 'ShiftLeft': 'Y', 'key': 'y'},
    {'keyCode': 90, 'code': 'KeyZ', 'ShiftLeft': 'Z', 'key': 'z'},
    {'keyCode': 190, 'code': 'Period', 'ShiftLeft': '>', 'key': '.'},
  ]
  return keyboard
};

 

 

 

 

더 많은 키보드 코드들을 알고 싶다면,

사이드 바에 공식문서 & 유용한 도구 목록을 확인해보세요!

 

 

웹크롤링-공식문서
웹크롤링 공식문서

 

그렇게 지정된 코드들을 아래의 특정 문자열을 받아와서 filter()를 적용해서 code, ShiftLeft를 가져옵니다

ShiftLeft가 값이 할당되면 대문자라는 뜻이므로 

대문자라면 keyboard.down(), keyboard.up()을 적용합니다

 

아래의 함수를 선언해서 handleWrite를 호출하는 것만으로 간단하게 적용할 수 있습니다

또 한, for(const id of idOfList)에서 비동기식 순차적으로 실행하게되어

글자를 한글자씩 입력하게됩니다

 

for (const id of idOfList) {
    const inputValue = await writeList.filter(element => element.ShiftLeft === id || element.key === id )
    if (inputValue.length > 0) {
      const code = inputValue[0].code
      const ShiftLeft = inputValue[0].ShiftLeft === id ? 'ShiftLeft' : ''
      if (ShiftLeft) {
        await page.keyboard.down(ShiftLeft);
        await setTime(selector, 500)
        await page.keyboard.press(code);
        await setTime(selector,500)
        await page.keyboard.up(ShiftLeft);
      } else {
        await page.keyboard.press(code);
      }
      await setTime(selector,500)
    }
}

 

 

 

이렇게 웹크롤링에서 키보드 코드를 입력해서 사용자 친화적으로 만들어서

봇으로 의심을 조금이라도 피하게하기위함입니다

웹크롤링의 포스팅 글이 점점 길어지고 있습니다

그래도 알게되는 것도 많으며,  앞으로 확실히 나아가는 것같습니다

그럼 다음 포스팅도 기대해주시고 

 

다음 웹 크롤링 관련 글로 찾아뵙겠습니다

 

대모험이 끝나기를 기대하며 화이팅!

 

 

 

728x90
반응형
728x90
반응형

이전 포스팅에서 웹 크롤링을 하여 스크린샷을 찍는 방법에 대해

풀 스크린과 어느 특정 영역, 또는 화면 전체 이렇게 3가지 방법으로

스크린샷 찍는 방법을 알아보았습니다

 

웹크롤링할 때 화면 비율을 적용하는 등 여러가지를 알아보았습니다

더 자세히 알고 싶으시다면 아래 링크를 클릭해 주시길 바랍니다

 

그리고 이전 포스팅에서 설명한 세팅엑셀파일 쓰기, 읽기

자세한 설명은 생략할 수 있으니 참고 하시길 바랍니다

 

 

2022.08.26 - [IT_Web/Nodejs] - 웹 크롤링 퍼펫티어 활용하여 스크린샷 이미지 폴더에 저장하기

 

웹 크롤링 퍼펫티어 활용하여 스크린샷 이미지 폴더에 저장하기

이전 포스팅 웹크롤링 이미지 다운로드 적용하기 퍼펫티어를 활용해 웹 크롤링을 하여 이미지 다운로드를 적용해보았다 navigator.userAgent에 대한 속성 값도 변경해보고, 이미지를 웹에서 다운받

tantangerine.tistory.com

 

 


 

인피니트 스크롤링이란?

 

먼저 인피니트 스크롤링이란 무엇일까요?

이 효과는 페이스북, 인스타그램 등 많은 사이트에서 사용을 하고 있는 방법입니다

사용자가 클릭을 하지않고 컨텐츠에 계속 집중할 수 있도록

스크롤링만으로 사용자에게 컨텐츠가 무한 노출하여

사이트 이탈율을 방지하는 효과가 있습니다

 

그래서 조회하는 버튼형식이 아닌 스크롤을 조작해서

어느 위치에 오면 컨텐츠를 조회하는 것입니다

 

그래서 이제는 웹크롤링할 때 스크롤을 조작해서 

이미지를 다운받는 방법 구현하려합니다

 

하지만 인피니트 스크롤링을 구현할 경우에는

싱글 페이지 어플리케이션을 활용하는 웹 사이트가 대부분입니다

 

그리고 리액트를 사용했다면 클라이언트 사이드 랜더링을 사용하기 때문에

웹크롤링이 쉽지않습니다

 

그래서 이런 경우에는 puppeteer를 사용하면 웹크롤링이 수월해집니다

 

그리고 웹 크롤링하기 적당한 웹 사이트인지 판단하기위해 

postman을 사용하여 개발하기 이전에 어느정도 판단이 가능합니다

 

 

아래의 빨간영역을 보시면 웹크롤링할 사이트로 요청을 보내면

html코드, 그리고 웹 크롤링하려는 사이트의 미리보기가 가능합니다

그래서 이미지를 보거나 코드를 보면서 선택자 접근이 얼마나 가능한지도 판단해서

웹크롤링을 시작할 수 있습니다

 

웹크롤링-스크롤링이미지
웹 크롤링에 적합한 사이트 알아보기

 


 

 

 


 

스크롤조작 해서 이미지 다운받기

 

웹 스크롤 대상 웹 사이트는 unsplash.com 입니다

 

 

이미지 다운받기 이전에

태그에 접근 하는 방법을 먼저 알아보고 코드 분석에 들어가겠습니다

 

 

웹크롤링-스크롤링2
웹 스크롤링 태그 접근 미리하기

 

지금 현재 위에서 보시면 두개의 태그가 있습니다

<div class="GIFah"> <img class="YV19w"> 두 개의 태그를 볼 수 있습니다

그래서 접근이 가능한지 아니면 필요없는 태그가 붙어서 오는지 선택자를 사용해서 미리 태그에 접근을 해봅니다

아래의 이미지와 같이 태그 접근이 가능한 것을 확인할 수 있습니다

 

 

웹크롤링-스크롤3
선택자로 태그 접근하기

 

 

 

 

그럼 이제 아래의 코드를 천천히 분석해보시길 바랍니다

 

아래에 코드를 보시면

브라우저와 페이지 영역을 설정하여 해상도를 높입니다

그리고 querySelectorALL을 활용해서 이미지의 부모 엘리먼트를 태그를 가져옵니다

그리고 태그로 forEach를 사용하여 자식 img태그에 접근하여

src에 접근하여 이미지 주소를 가져와 이미지 다운받는 것까지 구현하였습니다

 

상세한 설명은 아래에서 하겠습니다

 

const axios = require('axios')
const fs = require('fs');
const puppeteer = require('puppeteer');

fs.readdir('imges', (err) => {
  if(err) {
    console.log('imges 폴더가 없어 imges 폴더를 생성합니다.')
    fs.mkdirSync('imges')
  }
})

const crawler = async () => {
  try {
  const browser = await puppeteer.launch({
      headless: false,
      args:['--window-size=1920,1080']
    });
  const page = await browser.newPage();
  await page.setViewport({
    width: 1920,
    height:1080,
  });
  await page.goto('https://unsplash.com')
  let result = []
  while(result.length < 10) {
    const srcs = await page.evaluate(() => {
      window.scrollBy(0, 0)
      const imgs = []
      const imgEls = document.querySelectorAll('.GIFah')
      if (imgEls.length) {
        imgEls.forEach((y, i) => {
          let src = y.querySelector('img.YVj9w').src
          if(i < 10){
            if(src){
                imgs.push(src)
            }
            y.parentElement.removeChild(y);
          }
        });
      }
      window.scrollBy(0, 30)
      return imgs
    });
    result = result.concat(srcs)
    await page.waitForSelector('.GIFah')
    console.log('result', result.length, result)
  }
  result.forEach(async(imgUrl, i) => {
    if (imgUrl) {
      const imgInfo = await axios.get(imgUrl.replace(/\?.*$/,''), { 
        responseType: 'arraybuffer',
      })
      fs.writeFileSync(`imges/${new Date().valueOf()}.jpeg`, imgInfo.data)
    }
  })
  await page.close();
  await browser.close();
  } catch (e) {
    console.error(e)
  }
}

crawler();

 

아래의 같이 해상도를 크게 설정합니다

스크롤을 조작하는데 너무 해상도가 작으면

스크롤 위치가 너무 많이 이동을 하게되면

스크롤링으로 다음 컨텐츠 조회가 잘 되지않는 현상이 있으니 참고하시길 바랍니다

 

웹크롤링-스크롤링4
웹크롤링 화면 비율 조정하기

 

 

아래에서 선택자를 사용해서 태그에 접근합니다

그리고 그 태그로 이미지태그를 접근하여 이미지를 다운받습니다

그리고 중요한것은 현재 가지고 있는 태그의 부모 태그에 접근해서 모든 하위 태그를 삭제합니다

그렇게 되면 처음 가져온 image 주소를 저장하고나서 필요없게 된 태그를 삭제하여

다음 스크롤링 해서 가져온 이미지 관련 태그만 접근할 수 있다는 장점이 있습니다

 

 

웹크롤링-스크롤5
태그 접속해서 삭제및 이미지 주소가져오기

 

while문으로 특정 조건이 만족할 때까지 무한 루프가 실행됩니다

그리고 concat을 해서 가져온 이미지 주소를 

최종 결과 변수에 저장을 합니다

 

 

 

웹크롤링-스크롤링6
특정 조건을 허용하기 전까지 무한루프 돌기

 

 

 

그리고 forEach로 파일을 만들어서 확인할 수있습니다

window.scrollBy()로 스크롤릉 내리는 효과를 주어 다음 컨텐츠를 조회하게 합니다

그리고 최종 결과 변수 값에 배열이 계속저장되어

결국에는 특정조건이 맞지 않게되면

무한 루프에서 나와 파일을 만들고

브라우저 및 페이지를 종료합니다

 

 

오늘은 여기까지입니다

웹 크롤링을 사이드 프로젝트를 하게되면서 여러가지 응용할 수 있을것같습니다

그래서 조금 기대도 되고 다음에 사이드 프로젝트를 하는것을

포스팅해서 올리겠습니다

 

이렇게 공부를 하면서 사이드 프로젝트를 만들어가는 과정에

흥미를 붙여서 계속 공부하려는 의지를 붙여주는게 정말 중요한 것같습니다

 

우리는 아직 너무많은 이야기들이 남았으니까요

솔직히 개발자가들의 공부가 어디가 끝인지도 잘모르겠네요

그러니 흥미 잃지마시고 끝까지 파이팅 하시길바랍니다

 

우리 IT 대모험은 끝나지 않았으니까요!!

 

 

 

 

728x90
반응형
728x90
반응형

이전 포스팅 웹크롤링 이미지 다운로드 적용하기

퍼펫티어를 활용해 웹 크롤링을 하여 이미지 다운로드를 적용해보았다

navigator.userAgent에 대한 속성 값도 변경해보고,

이미지를 웹에서 다운받아 드라이버에 저장하는 것과

받아온 이미지 링크 주소를 엑셀에도 넣어보았습니다

 

이번 포스팅도 이어지는 부분이 있으니 확인하시길 바랍니다

그리고 조금 더 상세한 부분은 아래의 링크를 확인해주세요

 

 

2022.08.24 - [IT_Web/Nodejs] - 웹크롤링 이미지 다운로드 및 puppeteer 활용해 이미지 주소 엑셀에 입력하기

 

웹크롤링 이미지 다운로드 및 puppeteer 활용해 이미지 주소 엑셀에 입력하기

이전 포스팅에서 웹크롤링 Puppeteer 및 Promise 활용 방법 Node.js로 웹 크롤링할 경우 Puppeteer를 사용하면 정말 편하게 개발을 할 수 있습니다 evaluate() 함수를 활용하여 잠시 대기시간을 갖거나, 선택

tantangerine.tistory.com

 


 

Puppeteer 활용해서 웹 사이트 스크린샷 이미지 저장하기

 

웹 크롤링을 하기위한 세팅은 이전 포스팅에서부터 이어지고 있으니

관심 있으신 분은 #웹 크롤링 태그를 클릭해서 확인해주시길 바랍니다

 

우선 아래의 코드를 작성합니다

 

launch(), setViewport(), page.screenshot()

함수에 대해서 알아보겠습니다

 

const fs = require('fs');
const puppeteer = require('puppeteer');

const xlsx = require('xlsx');
const workbook = xlsx.readFile('xlsx/data.xlsx');
const ws = workbook.Sheets.Sheet1;
const xlsxRecords = xlsx.utils.sheet_to_json(ws)

fs.readdir('screenShot', (err) => {
  if(err) {
    console.log('screenShot 폴더가 없어 screenShot 폴더를 생성합니다.')
    fs.mkdirSync('screenShot') 
  }
})

const screenshotCrawler = async () => {
  try {
    const browser = await puppeteer.launch({
      headless: false,
      args:['--window-size=1920,1080']
    });
    console.log('첫번째: records', xlsxRecords)
    const page = await browser.newPage();
    await page.setViewport({
      width: 1920,
      height:1080,
    });
    await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36')
    for(const [i, r] of xlsxRecords.entries()) {
      await page.goto(r.링크);
      await page.screenshot({ 
        path: `screenShot/${r.제목}.png`, // 저장할 위치를 지정한다
        fullPage: false, // 웹 페이지의 스크롤의 밑 전체 페이지를 스크린샷할 수 있다
        clip: {
          x: 100,
          y: 100,
          width: 300,
          height: 300,
        }// 왼쪽 상단 모서리 (x, y), 너비(width), 높이(height)
      });// 그리고 fullPage와 clip은 같이 사용할 수 없다
      
      const setTime = await page.evaluate(async() => {
        const timeList = await [3975, 4547, 5231, 6397, 7894, 3394, 4206, 5147, 6932, 7430, 3561, 4896, 5877, 6407, 7133];
        const randomTime = await timeList[Math.floor(Math.random() * timeList.length)]
        await new Promise(r => setTimeout(r, randomTime))
        return randomTime
      })
      console.log('setTime', setTime)
    }
    await page.close();
    await browser.close();
  } catch (e) {
    console.error(e)
  }
}

screenshotCrawler();

 

 

우선 초기에 해상도를 적용하지 않을 경우

아래와 같이 브라우저는 큰 화면이 아닌 반 정도인 것을 확인할 수 있습니다

 

 

웹크롤링-스크린샷2
초기 브라우저 설정

 

 

아래의 코드에 보면 기존 코드에 args:['--window-size=1920,1080']를 추가하면 됩니다

그리고 1920, 1080은 자신의 모니터 해상도를 생각하시고 지정합시다

 

 

웹크롤링-스크린샷3
브라우저 해상도 지정하기

 

 

위의 코드를 적용하면 브라우저의 크기가 커진것을 확인할 수 있습니다

이제는 화면의 해상도를 키우면 브라우저만큼 크게 넓어질 것 같습니다

 

 

웹크롤링-스크린샷4
args 값 적용 화면

 

 

아래의 코드 setViewport() 함수를 적용합니다 

브라우저 해상도와 맞게 값을 지정합니다

 

 

웹크롤링-스크린샷5
화면 해상도 지정하기

 

 

아래와 같이 화면이 해상도에 맞게 커지게 되었습니다

이제는 스크린샷을 찍는 코드를 적용하도록 하겠습니다

 

 

웹크롤링-스크린샷6
setViewport() 적용 화면

 

 

 

 

 

 

아래의 코드를 확인해봅시다

clip에 값을 지정하면 어느 한 영역을 스크린샷하여 찍을 수 있습니다

그 영역은 지정된 웹 페이지의 x, y축에서

width, height를 지정하여 사각형 영역을 만들어 스크린샷을 찍습니다

 

 

 

웹크롤링-스크린샷7
스크린샷 적용 코드

 

위와 같이 코드를 적용하면 아래와 같이 

스크린샷을 찍게 되어 path위치에 저장하게 됩니다

 

 

웹크롤링-스크린샷8
스크린샷 clip 값 적용 화면

 

 

아래의 전체 화면에 clip영역이 어떻게 지정되는지 확인이 가능합니다

이제는 fullPagetrue값을 주면 어떻게 스크린샷을 찍는지 확인해보겠습니다

 

 

웹크롤링-스크린샷9
clip 값 영역 지정

 

 

fullPage값을 true로 지정하게 되면 아래와 같이 전체 화면을 찍게 됩니다

웹 페이지 전체를 찍는 것이니 유의해 주시길 바랍니다

그리고 한 가지 더 fullPage 값이 true일 경우 clip 값을 지정하면

에러가 발생하니 주의하시길 바랍니다

 

 

웹크롤링-스크린샷10
fullPage값이 true로 지정된 스크린샷 이미지

 

 

이렇게 웹크롤링에서 스크린샷을 찍어 보았습니다

간단하게 함수 3개로 구현하였습니다

 

웹크롤링 기능은 아직 많이 남았으니

조금만 참고 포스팅을 기대해주시고 

힘내시길 바랍니다

 

아직 IT 대모험은 끝나지 않았으니까요

그럼 파이팅 하시고

 

다음 포스팅에서 뵙겠습니다

 

728x90
반응형

+ Recent posts

Powered by Tistory, Designed by wallel