크롤링

크롤링을 위해 cheerio라는 것을 사용한다.

github.com/cheeriojs/cheerio

 

cheeriojs/cheerio

Fast, flexible, and lean implementation of core jQuery designed specifically for the server. - cheeriojs/cheerio

github.com

var request = require('request');
var cheerio = require('cheerio');

app.get('/getMenu', function (req, res) {
  request("http://www.kopo.ac.kr/kangseo/content.do?menu=262", function(err, res2, body) {
    const $ = cheerio.load(body);
    var menus = [];

    for(var i = 0; i < 5; i++) {
      menus.push($('td')[i*4+2].children[1].children[0].data.replace(/\n/g, "").split(","));
    }
    // console.log(menus);

    res.send(menus);
  })
})

// const를 사용해 URL 요청을 option으로 따로 분리할 수 있다.
app.get('/getMenu', function (req, res) {
  const options = {
    url:'http://www.kopo.ac.kr/kangseo/content.do?menu=262',
    method: 'GET'
  }
  request.get(options, function(err,httpResponse,body){
    const $ = cheerio.load(body);
    var menus = [];

    for(var i = 0; i < 5; i++) {
      menus.push($('td')[i*4+2].children[1].children[0].data.replace(/\n/g, "").split(","));
    }

    res.send(menus);
  });
})

따라서

app.js

var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app).listen(80);
console.log("Server is running...")

var mysql = require('mysql');
var request = require('request');
var cheerio = require('cheerio');
const ExcelJS = require('exceljs');

var bodyParser = require("body-parser");
// extended : 객체 안의 객체를 파싱 가능하게 하려면 true로 해야한다.
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
app.use(bodyParser.json({limit: '50mb'}));

app.get('/', function (req, res) {
  res.sendfile("main.html");
});
app.get('/main', function (req, res) {
  res.sendfile("main.html");
});

app.get('/getMenu', function (req, res) {
  const options = {
    url:'http://www.kopo.ac.kr/kangseo/content.do?menu=262',
    method: 'GET'
  }
  request.get(options, function(err,httpResponse,body){
    const $ = cheerio.load(body);
    var menus = [];

    for(var i = 0; i < 5; i++) {
      menus.push($('td')[i*4+2].children[1].children[0].data.replace(/\n/g, "").split(","));
    }

    res.send(menus);
  });
})

 

main.html

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <span id="menuArea"></span>
    <br />
    <input type="button" id="drawGraph" value="그래프그리기">
    <input type="button" id="downloadExcel" value="엑셀다운로드">
    <div id="graph" style="width: 800px; height: 500px;"></div>
  </body>
  <script src="http://code.jquery.com/jquery-latest.min.js"></script>
  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <script type="text/javascript">
    var week = ['월','화','수','목','금'];
    var menus;

    $.ajax({
      url : '/getMenu',
      type : 'GET',
      data : {

      },
      success : function (data) {
        menus = data;  // 바깥 배열이 요일별로 분리, 안쪽 배열이 메뉴별로 분리된 매트릭스
        for(var i = 0; i < menus.length; i++) {
          // 바깥 배열 길이만큼 돌며 요일을 출력
          $("#menuArea").append(week[i] + "요일<br>");
          // console.log(week[i] + "요일<br>");

          // 셀렉트 박스를 만들기 위해 appendingText에 한 번에 담아서 출력하기
          for(var j = 0; j < menus[i].length; j++) {
            var appendingText = "";
            // i 요일의 j 번째 메뉴를 출력
            // appendingText += menus[i][j] + `<select id = "s${i}_${j}"`;
            appendingText += menus[i][j] + `<select name="s${i}">`;

            // select 의 수량을 10개 만든다.
            for (var k = 0; k < 11; k++) {
              appendingText += `<option value = ${k}>${k}</option>`;
            }
            appendingText += `<select><br>`;
            $("#menuArea").append(appendingText);
            // console.log(appendingText);
          }
          $("#menuArea").append("<br>");
        }
      }
    });

    // 그래프 그리기
    $("#drawGraph").click(function() {
    
    });

    // 엑셀 다운로드
    $("#downloadExcel").click(function() {
    
    });
  </script>
</html>

 

그래프

이미 html에 가져온 데이터만을 이용해 자바스크립트로 그려낼 것이기 때문에 main.html 안에서 해결한다.

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>

    <div id="graph" style="width: 800px; height: 500px;"></div>
  </body>
  <script src="http://code.jquery.com/jquery-latest.min.js"></script>
  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <script type="text/javascript">
    var week = ['월','화','수','목','금'];
    var menus;

    // 그래프 그리기
    $("#drawGraph").click(function() {
      var averageArr = [];
      console.log($("#count").val());

      // 월 ~ 금 반복문
      for (var i = 0; i < menus.length; i++) {
        var dailyAverage = 0;
        // 각 요일별 메뉴의 반복문
        var dailyScore = $(`select[name=s${i}]`);
        for (var j = 0; j < dailyScore.length; j++) {
          // 각 메뉴별 1 ~ 10 점 중 어떤 것이 선택되었는지를 확인
          for (var k = 0; k < 11; k++) {
            if (dailyScore[j][k].selected) {
              dailyAverage +=k; // 각 요일별 메뉴들의 점수의 총 합
            }
          }
        }
        dailyAverage = dailyAverage / dailyScore.length // 각 요일별 메뉴의 점수들의 총 합을 메뉴의 개수로 나눠 평균을 계산
        averageArr.push([week[i], dailyAverage]);
        console.log(averageArr);
      }

      google.charts.load('current', {'packages':['corechart', 'line']});
      google.charts.setOnLoadCallback(drawCurveTypes);

      function drawCurveTypes() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', '요일');
        data.addColumn('number', '점수');

        data.addRows(averageArr);

        var options = {
          hAxis: {
            title: '요일'
          },
          vAxis: {
            title: '만족도'
          },
          series: {
            1: {curveType: 'function'}
          }
        };

        var chart = new google.visualization.LineChart(document.getElementById('graph'));
        chart.draw(data, options);
      }
    });

    // 엑셀 다운로드
    $("#downloadExcel").click(function() {

    });
  </script>
</html>

 

 

엑셀

엑셀로 만들어주기 위해 exceljs를 사용한다.

app.js (엑셀 파일을 만드는 라우터)

const ExcelJS = require('exceljs');

// ajax로 데이터 넘겨받아 엑셀형식으로 만들기
app.post('/getExcel', async function (req, res) {
  var menus = req.body.menus;
  var scores = req.body.scores;

  const workbook = new ExcelJS.Workbook();
  const sheet = workbook.addWorksheet('menu');

  const alpahbet = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
  const dayOfTheWeek = ['월','화','수','목','금','토','일'];
  var menusMaxLength = 0;
  var roundedAverage = [];

  // 월, 화, 수, 목, 금을 도는 for문
  for (var i = 0; i < menus.length; i++) {
    sheet.getCell(`${alpahbet[i*2]}1`).value = dayOfTheWeek[i]; // 1행에 월, 화, 수, 목, 금
    scores[i] = scores[i].map( str => parseInt(str) );  // str to integer (점수 array 형변환)

    // 각 요일별 메뉴의 개수만큼 도는 for문 (각 요일의 메뉴와 메뉴별 점수를 엑셀에 삽입한다.)
    for (var j = 0; j < menus[i].length; j++) {
        sheet.getCell(`${alpahbet[i*2]}${j+2}`).value = menus[i][j].trim();
        sheet.getCell(`${alpahbet[i*2+1]}${j+2}`).value = scores[i][j];
    }
    // 각 요일별 메뉴의 평균 점수를 계산하고, 이를 배열에 담아둔다.
    // reduce 참고 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
    // acc : 누적값, (,0 : 초기값), curr : 현재값... 그러니까 파이썬 식으로 표현하면 sum = sum + curr 이런거다.
    const sum = scores[i].reduce( ( accumulator, currentValue ) => accumulator + currentValue, 0);
    const average = sum / menus[i].length;
    roundedAverage[i] = ( Math.round(average*10) ) / 10; // 소수점 첫째 자리까지 표현

    // 메뉴의 길이 중 최대로 긴 값의 크기를 구해서 저장한다. (요일마다 메뉴의 길이가 다를 수 있으니까.)
    if (menus[i].length > menusMaxLength) menusMaxLength = menus[i].length;
  }

  // 요일마다 메뉴의 길이가 다른 경우가 있기 때문에 위에서 메뉴를 모두 채우는 동안 배열에 저장해둔 다음 한 번에 출력한다.
  for (var i = 0; i < menus.length; i++) {
  sheet.getCell(`${alpahbet[i*2]}${menusMaxLength+3}`).value = '평균';
  sheet.getCell(`${alpahbet[i*2+1]}${menusMaxLength+3}`).value = roundedAverage[i];  // 계산한 평균을 입력
  }

  // await : 파일이 다 만들어 질 때까지 기다려준다. (callback 함수와 같은 기능. 최근에 생겨난 함수다.)
  await workbook.xlsx.writeFile('menu.xlsx');
  // 엑셀 다 만들었다고 클라이언트에 응답을 보냄.
  res.send("ok");
});

/getExcel 라우터가 main.html에서 보낸 ajax request를 받아서 body에 실어 보낸 데이터를 분해, 엑셀 파일로 만든다.

exceljs를 사용하며, sheet.getCell();을 통해 각 셀에 데이터를 삽입한다.

주의 : 이 때 각 요일별 메뉴의 개수가 달라지는 주가 존재한다. 따라서 최대값을 구한 다음 마지막 줄 최종 평균은 위 for문이 끝난 다음 다른 for문을 통해 구현한다.

// 월, 화, 수, 목, 금을 도는 for문
for (var i = 0; i < menus.length; i++) {
  sheet.getCell(`${alpahbet[i*2]}1`).value = dayOfTheWeek[i]; // 1행에 월, 화, 수, 목, 금
  scores[i] = scores[i].map( str => parseInt(str) );  // str to integer (점수 array 형변환)

  // 각 요일별 메뉴의 개수만큼 도는 for문 (각 요일의 메뉴와 메뉴별 점수를 엑셀에 삽입한다.)
  for (var j = 0; j < menus[i].length; j++) {
      sheet.getCell(`${alpahbet[i*2]}${j+2}`).value = menus[i][j].trim();
      sheet.getCell(`${alpahbet[i*2+1]}${j+2}`).value = scores[i][j];
  }
  // 각 요일별 메뉴의 평균 점수를 계산하고, 이를 배열에 담아둔다.
  // reduce 참고 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
  // acc : 누적값, (,0 : 초기값), curr : 현재값... 그러니까 파이썬 식으로 표현하면 sum = sum + curr 이런거다.
  const sum = scores[i].reduce( ( accumulator, currentValue ) => accumulator + currentValue, 0);
  const average = sum / menus[i].length;
  roundedAverage[i] = ( Math.round(average*10) ) / 10; // 소수점 첫째 자리까지 표현

  // 메뉴의 길이 중 최대로 긴 값의 크기를 구해서 저장한다. (요일마다 메뉴의 길이가 다를 수 있으니까.)
  if (menus[i].length > menusMaxLength) menusMaxLength = menus[i].length;
}

// 요일마다 메뉴의 길이가 다른 경우가 있기 때문에 위에서 메뉴를 모두 채우는 동안 배열에 저장해둔 다음 한 번에 출력한다.
for (var i = 0; i < menus.length; i++) {
sheet.getCell(`${alpahbet[i*2]}${menusMaxLength+3}`).value = '평균';
sheet.getCell(`${alpahbet[i*2+1]}${menusMaxLength+3}`).value = roundedAverage[i];  // 계산한 평균을 입력
}

reduce 함수

developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

 

Array.prototype.reduce()

reduce() 메서드는 배열의 각 요소에 대해 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결과값을 반환합니다.

developer.mozilla.org

sum 함수가 없어서 reduce를 사용해 배열의 합을 구한 것에 주목한다.

const sum = scores[i].reduce( ( accumulator, currentValue ) => accumulator + currentValue, 0);

 

마찬가지로 반올림의 자리수를 따로 지정할 수 없어 round함수를 사용하기 전, 10을 곱하고 다시 10으로 나누는 것에 주목한다. 만약 소수점 둘째 자리까지 남기고 싶다면 100을 곱한 다음 100으로 나누면 된다.

roundedAverage[i] = ( Math.round(average*10) ) / 10; // 소수점 첫째 자리까지 표현

 

await

마지막으로 콜백함수와 동일한 기능을 하지만, 기존 콜백함수 구현보다 훨씬 짧고 간결한 await가 있다. 단, 나온지 얼마 안 되어서 지원되지 않는 라이브러리들이 있을 수 있다.

// await : 파일이 다 만들어 질 때까지 기다려준다. (callback 함수와 같은 기능. 최근에 생겨난 함수다.)
await workbook.xlsx.writeFile('menu.xlsx');

 

기존의 콜백함수 형식

// 콜백함수
res.sendFile(__dirname + '/menu.xlsx', function(err) {  // 파일 보내기가 완료 되면
  fs.unlinkSync(__dirname + '/menu.xlsx');  // 파일을 삭제해라.
});

 

main.html

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <span id="menuArea"></span>
    <br />
    <input type="button" id="drawGraph" value="그래프그리기">
    <input type="button" id="downloadExcel" value="엑셀다운로드">
    <div id="graph" style="width: 800px; height: 500px;"></div>
  </body>
  <script src="http://code.jquery.com/jquery-latest.min.js"></script>
  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <script type="text/javascript">
    var week = ['월','화','수','목','금'];
    var menus;

    $.ajax({
      url : '/getMenu',
      type : 'GET',
      data : {

      },
      success : function (data) {
		... 생략
      }
    });

    // 그래프 그리기
    $("#drawGraph").click(function() {

    });

    // 엑셀 다운로드
    $("#downloadExcel").click(function() {
      var scores = [];

      for (var i = 0; i < menus.length; i++) {
        scores[i] = [];
        var dailyScore = $(`select[name=s${i}]`);
        for (var j = 0; j < dailyScore.length; j++) {
          for (var k = 0; k < 11; k++) {
            if (dailyScore[j][k].selected) {
              scores[i].push(k);
            }
          }
        }
      }
      console.log(scores);
      console.log(menus);
      $.ajax({
        url : '/getExcel',
        type : 'POST',
        data : {
          scores : scores,
          menus : menus
        },
        success : function (res) {
          console.log(res);
          location.href = '/getExcelFile';
        }
      });

    });
  </script>
</html>

ajax로 /getExcel 라우터에 요청을 보낸 다음, 라우터가 파일을 다 만들었다고 응답을 보내면, success에서 다시 /getExcelFile 라우터에 요청을 보내 엑셀을 다운로드 하게 된다. 즉, 엑셀을 만드는 라우터(/getExcel)와 엑셀 파일을 전송하는 라우터(/getExcelFile)를 클라이언트의 html 파일 내의 자바스크립트 로직이 연결을 하게 된다는 것을 알 수 있다.

app.js (엑셀 파일을 전송하는 라우터)

// 위에서 파일 만들기가 완료되었다는 응답이 가면 ajax가 이쪽 라우터로 이동시켜준다.
app.get('/getExcelFile', function (req, res) {
  res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  res.setHeader("Content-Disposition", "attachment; filename=menu.xlsx");

  var fs = require('fs');
  // 콜백함수
  res.sendFile(__dirname + '/menu.xlsx', function(err) {  // 파일 보내기가 완료 되면
    fs.unlinkSync(__dirname + '/menu.xlsx');  // 파일을 삭제해라.
  });
});

 

 

전체 코드

app.js

var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app).listen(80);
console.log("Server is running...")

var mysql = require('mysql');
var request = require('request');
var cheerio = require('cheerio');
const ExcelJS = require('exceljs');

// var connection = mysql.createConnection({
//   host: 'localhost',
//   port: 3308,
//   user:'root',
//   password: '1234',
//   database: 'javascript'
// });
var bodyParser = require("body-parser");
// extended : 객체 안의 객체를 파싱 가능하게 하려면 true로 해야한다.
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
app.use(bodyParser.json({limit: '50mb'}));

app.get('/', function (req, res) {
  res.sendfile("main.html");
});
app.get('/main', function (req, res) {
  res.sendfile("main.html");
});

// app.get('/getMenu', function (req, res) {
//   request("http://www.kopo.ac.kr/kangseo/content.do?menu=262", function(err, res2, body) {
//     const $ = cheerio.load(body);
//     var menus = [];
//
//     for(var i = 0; i < 5; i++) {
//       menus.push($('td')[i*4+2].children[1].children[0].data.replace(/\n/g, "").split(","));
//     }
//     // console.log(menus);
//
//     res.send(menus);
//   })
// })

app.get('/getMenu', function (req, res) {
  const options = {
    url:'http://www.kopo.ac.kr/kangseo/content.do?menu=262',
    method: 'GET'
  }
  request.get(options, function(err,httpResponse,body){
    const $ = cheerio.load(body);
    var menus = [];

    for(var i = 0; i < 5; i++) {
      menus.push($('td')[i*4+2].children[1].children[0].data.replace(/\n/g, "").split(","));
    }

    res.send(menus);
  });
})

// ajax로 데이터 넘겨받아 엑셀형식으로 만들기
app.post('/getExcel', async function (req, res) {
  var menus = req.body.menus;
  var scores = req.body.scores;

  const workbook = new ExcelJS.Workbook();
  const sheet = workbook.addWorksheet('menu');

  const alpahbet = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
  const dayOfTheWeek = ['월','화','수','목','금','토','일'];
  var menusMaxLength = 0;
  var roundedAverage = [];

  // 월, 화, 수, 목, 금을 도는 for문
  for (var i = 0; i < menus.length; i++) {
    // console.log(`${alpahbet[i*2]}1 = ${dayOfTheWeek[i]}`);
    sheet.getCell(`${alpahbet[i*2]}1`).value = dayOfTheWeek[i]; // 1행에 월, 화, 수, 목, 금
    scores[i] = scores[i].map( str => parseInt(str) );  // str to integer (점수 array 형변환)

    // 각 요일별 메뉴의 개수만큼 도는 for문 (각 요일의 메뉴와 메뉴별 점수를 엑셀에 삽입한다.)
    for (var j = 0; j < menus[i].length; j++) {
        // console.log(`${alpahbet[i*2]}${j+2} = ${menus[i][j].trim()}`);
        // console.log(`${alpahbet[i*2+1]}${j+2} = ${scores[i][j]}`);
        sheet.getCell(`${alpahbet[i*2]}${j+2}`).value = menus[i][j].trim();
        sheet.getCell(`${alpahbet[i*2+1]}${j+2}`).value = scores[i][j];
    }
    // 각 요일별 메뉴의 평균 점수를 계산하고, 이를 배열에 담아둔다.
    // reduce 참고 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
    // acc : 누적값, (,0 : 초기값), curr : 현재값... 그러니까 파이썬 식으로 표현하면 sum = sum + curr 이런거다.
    const sum = scores[i].reduce( ( accumulator, currentValue ) => accumulator + currentValue, 0);
    const average = sum / menus[i].length;
    roundedAverage[i] = ( Math.round(average*10) ) / 10; // 소수점 첫째 자리까지 표현

    // 메뉴의 길이 중 최대로 긴 값의 크기를 구해서 저장한다. (요일마다 메뉴의 길이가 다를 수 있으니까.)
    // console.log(`${alpahbet[i*2]}${menus[i].length+3} = 평균`);
    if (menus[i].length > menusMaxLength) menusMaxLength = menus[i].length;
  }

  // 요일마다 메뉴의 길이가 다른 경우가 있기 때문에 위에서 메뉴를 모두 채우는 동안 배열에 저장해둔 다음 한 번에 출력한다.
  for (var i = 0; i < menus.length; i++) {
  sheet.getCell(`${alpahbet[i*2]}${menusMaxLength+3}`).value = '평균';
  sheet.getCell(`${alpahbet[i*2+1]}${menusMaxLength+3}`).value = roundedAverage[i];  // 계산한 평균을 입력
  }

  // await : 파일이 다 만들어 질 때까지 기다려준다. (callback 함수와 같은 기능. 최근에 생겨난 함수다.)
  await workbook.xlsx.writeFile('menu.xlsx');
  // 엑셀 다 만들었다고 클라이언트에 응답을 보냄.
  res.send("ok");
});

// 위에서 파일 만들기가 완료되었다는 응답이 가면 ajax가 이쪽 라우터로 이동시켜준다.
app.get('/getExcelFile', function (req, res) {
  res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  res.setHeader("Content-Disposition", "attachment; filename=menu.xlsx");

  var fs = require('fs');
  // 콜백함수
  res.sendFile(__dirname + '/menu.xlsx', function(err) {  // 파일 보내기가 완료 되면
    fs.unlinkSync(__dirname + '/menu.xlsx');  // 파일을 삭제해라.
  });
});

 

main.html

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <span id="menuArea"></span>
    <br />
    <input type="button" id="drawGraph" value="그래프그리기">
    <input type="button" id="downloadExcel" value="엑셀다운로드">
    <div id="graph" style="width: 800px; height: 500px;"></div>
  </body>
  <script src="http://code.jquery.com/jquery-latest.min.js"></script>
  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  <script type="text/javascript">
    var week = ['월','화','수','목','금'];
    var menus;

    $.ajax({
      url : '/getMenu',
      type : 'GET',
      data : {

      },
      success : function (data) {
        menus = data;  // 바깥 배열이 요일별로 분리, 안쪽 배열이 메뉴별로 분리된 매트릭스
        for(var i = 0; i < menus.length; i++) {
          // 바깥 배열 길이만큼 돌며 요일을 출력
          $("#menuArea").append(week[i] + "요일<br>");
          // console.log(week[i] + "요일<br>");

          // 셀렉트 박스를 만들기 위해 appendingText에 한 번에 담아서 출력하기
          for(var j = 0; j < menus[i].length; j++) {
            var appendingText = "";
            // i 요일의 j 번째 메뉴를 출력
            // appendingText += menus[i][j] + `<select id = "s${i}_${j}"`;
            appendingText += menus[i][j] + `<select name="s${i}">`;

            // select 의 수량을 10개 만든다.
            for (var k = 0; k < 11; k++) {
              appendingText += `<option value = ${k}>${k}</option>`;
            }
            appendingText += `<select><br>`;
            $("#menuArea").append(appendingText);
            // console.log(appendingText);
          }
          $("#menuArea").append("<br>");
        }
      }
    });

    // 그래프 그리기
    $("#drawGraph").click(function() {
      var averageArr = [];
      console.log($("#count").val());

      // 월 ~ 금 반복문
      for (var i = 0; i < menus.length; i++) {
        var dailyAverage = 0;
        // 각 요일별 메뉴의 반복문
        var dailyScore = $(`select[name=s${i}]`);
        for (var j = 0; j < dailyScore.length; j++) {
          // 각 메뉴별 1 ~ 10 점 중 어떤 것이 선택되었는지를 확인
          for (var k = 0; k < 11; k++) {
            if (dailyScore[j][k].selected) {
              dailyAverage +=k; // 각 요일별 메뉴들의 점수의 총 합
            }
          }
        }
        dailyAverage = dailyAverage / dailyScore.length // 각 요일별 메뉴의 점수들의 총 합을 메뉴의 개수로 나눠 평균을 계산
        averageArr.push([week[i], dailyAverage]);
        console.log(averageArr);
      }

      google.charts.load('current', {'packages':['corechart', 'line']});
      google.charts.setOnLoadCallback(drawCurveTypes);

      function drawCurveTypes() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', '요일');
        data.addColumn('number', '점수');

        data.addRows(averageArr);

        var options = {
          hAxis: {
            title: '요일'
          },
          vAxis: {
            title: '만족도'
          },
          series: {
            1: {curveType: 'function'}
          }
        };

        var chart = new google.visualization.LineChart(document.getElementById('graph'));
        chart.draw(data, options);
      }
    });

    // 엑셀 다운로드
    $("#downloadExcel").click(function() {
      var scores = [];

      for (var i = 0; i < menus.length; i++) {
        scores[i] = [];
        var dailyScore = $(`select[name=s${i}]`);
        for (var j = 0; j < dailyScore.length; j++) {
          for (var k = 0; k < 11; k++) {
            if (dailyScore[j][k].selected) {
              scores[i].push(k);
            }
          }
        }
      }
      console.log(scores);
      console.log(menus);
      $.ajax({
        url : '/getExcel',
        type : 'POST',
        data : {
          scores : scores,
          menus : menus
        },
        success : function (res) {
          console.log(res);
          location.href = '/getExcelFile';
        }
      });

    });
  </script>
</html>

 

 

cheerio 모듈 읽어볼만한 글

magic.wickedmiso.com/142

 

[Node.js] SCRAPING을 위한 cheerio 모듈과 cheerio-httpcli 모듈

발췌 : 자바스크립트와 Node.js를 이용한 웹 크롤링 테크닉 ※ 스크래핑이란? -. 웹의 세계에서 흔히 말하는 '스크래핑'은 웹 사이트에서 HTML 데이터를 수집하고, 특정 데이터를 추출, 가공하여 저��

magic.wickedmiso.com

 

+ Recent posts