Crawling 크롤링 - 네이버 영화순위 node.js

2020. 1. 16. 00:22Node.js, Express

 

https://movie.naver.com/movie/sdb/rank/rmovie.nhn  를 가져옵니다.

 

 

랭킹 : 네이버 영화

영화, 영화인, 예매, 박스오피스 랭킹 정보 제공

movie.naver.com

데이터를 가져와서 디비에 저장 후 디비에 저장한 값을 보여주는 형태로 만들겠습니다.

 

저는 Bootstrap, node.js, Express.js, Mysql, Sequelize, ejs 를 사용합니다.

 

express를 설치 하고 view템플릿을 ejs로 사용합니다.

를 터미널에 치면 

파일이 생성됩니다.

cd myapp로 파일를 변경하고 

Sequelize, Mysql를 설치합니다. Mysql은 mysql2를 설치합니다.

디비를 연결합니다. 

DB폴더와 DB파일을 만들고

DB를 이런식으로 연결하고

config.json파일에서 

development 부분을 DB와 같게 설정합니다.

app.js에가서 sequelize  sync를 설정합니다.

sequelize-cli를 이용해서 모델을 만듭니다.

터미널에 sequelize model:create --name crawling --attributes "name:string, tage:string" 입력

model폴더와 migrations폴더에 있는 파일을

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('crawlings', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      name: {
        allowNull: false,
        type: Sequelize.STRING
      },
      tage: {
        allowNull: false,
        type: Sequelize.STRING
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('crawlings');
  }
};

변경

models의 파일을 변경

'use strict';
module.exports = (sequelize, DataTypes) => {
  const crawling = sequelize.define('crawling', {
    name: {
      type: DataTypes.STRING,
      allowNull: false
    },
    tage: {
      type: DataTypes.STRING,
      allowNull: false
    }
  }, {});
  crawling.associate = function(models) {
    // associations can be defined here
  };
  return crawling;
};

변경 후 

sequelize db:migrate 입력 하고 pm2 실행을 하면 DB에 table이 생성됌

 

app.js에 model에 index.js를 require함

이제 값을 크롤링하는 기능을 만듭니다.

설치 

request : html데이터를 받아오는 모듈

cheerio: html에 문서에 필요한 데이터만 가져오게 해주는 모듈

iconv-lite : 문자열을 변경

가져와야 하는 데이터 내용

14 ~ 15 : request에서 데이터를 받아오고 html_result에 사이트의 문자열은 euc-kr이고 decode에는원본 문자열을 넣어야 해서 euc-kr를 작성

16 ~ 17 : cheerio으로 필요한 데이터만 빼오는 과정

$(".tit3") 에 가져오려는 속성을 쓰면 됌

 

18 ~ 19 : 데이터를 DB에 저장하기 전에 초기화를 먼저하고 넘어가도록함

22 ~ 29 : 데이터를 for문으로 가져와서 DB에 저장함

DB에서 순위값을 빼옴 

41 ~ 46 : craw_result[ ]에 for문으로 담은 후

48 ~ 50 : view에 있는 craw파일에 craw_result의 배열 craw로 보냄 

let express = require('express');
let router = express.Router();
let models = require('../models');
const request = require('request');
const cheerio = require('cheerio');
const iconv = require('iconv-lite');

router.get("/",function(req,res,next){
  let url = "http://movie.naver.com/movie/sdb/rank/rmovie.nhn";
  let craw =[];
  let craw_a =[];
  //대상 사이트에서 값 가져옴
  request({url, encoding:null}, function(err, response, body){
    let html_result=iconv.decode(body,'euc-kr');
    const $ = cheerio.load(html_result);
    let colArr = $(".tit3");
    models.crawling.destroy({
      where:{}
    })
    .then(result =>{
      for(let i =0; i< colArr.length;i++){
        craw.push(colArr[i].children[1].attribs.title)
        craw_a.push(colArr[i].children[1].attribs.href)
        //디비에 저장
        models.crawling.create({
          movie_name:craw[i],
          movie_a:craw_a[i]
        })
        .then(result1=>{
          console.log("저장 완료");
        })
        .catch(err=>{
          console.log("데이터 추가 실패");
        })
      }
    })
    models.crawling.findAll()
  .then(result2=>{    
    let craw_result=[];
      for(let i=0; i<result2.length;i++){
        craw_result.push({
        movie_name:result2[i].movie_name,
        movie_a:result2[i].movie_a
        });
      }
      console.log(craw_result[1].movie_name);
      res.render("craw",{
      craw:craw_result
    })
    })
    
  })
  
});

module.exports = router;

그 후 views에 들어 갈 craw파일을 만듬니다.

1, 26 : (top, footer 파일을 만들예정)views폴더 안에 index폴더에 있는 top, footer.ejs 파일을 불러옴

12 ~ 21 : for문으로 routes안에 있는 index.js에서 보낸 craw를 받아옴

 

index폴더를 만들고 안에 top.ejs footer.ejs 파일을 만듭니다.

top.ejs에 작성합니다.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="../../public/stylesheets/style.css">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
  <title>Movie Ranking</title>
</head>
<body>
  <header id="header" class="bg-info text-white">
    <div  class="layout">
      <h1>Movie Ranking</h1>
    </div>
  </header>

파란색 박스가 Bootstrap

footer.ejs에는 

<footer id="footer">
    <div class="content">
    <div id="footerContent">
        <p>
            상호명 : (주)바삭바삭 / 주소 : crispypotato.tistory.com  
            <br>대표: 바삭바삭 / 사업자등록번호 : 000-00-00000 </br>
            주소 : https://github.com/Crispyfrenchfries
        </p>
    </div>
    <div id="copyright">
        <p>
            Copyright © 2019 by Crispy Story Inc All Rights Reserved
        </p>
    </div>
</div>
</footer>
</body>
</html>

로 작성합니다.

 

 

 

참조: https://victorydntmd.tistory.com/94?category=677306

728x90
반응형