course/spartacoding

[웹개발 종합반] 5주차 (1) 무비스타

hjkim0502 2021. 11. 5. 17:24
  • DB 세팅
    • # init_db.py
      
      import requests
      from bs4 import BeautifulSoup
      
      from pymongo import MongoClient
      
      client = MongoClient('localhost', 27017)
      db = client.dbsparta
      
      
      # DB에 저장할 영화인들의 출처 url을 가져옵니다.
      def get_urls():
          headers = {
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
          data = requests.get('https://movie.naver.com/movie/sdb/rank/rpeople.nhn', headers=headers)
      
          soup = BeautifulSoup(data.text, 'html.parser')
      
          trs = soup.select('#old_content > table > tbody > tr')
      
          urls = []
          for tr in trs:
              a = tr.select_one('td.title > a')
              if a is not None:
                  base_url = 'https://movie.naver.com/'
                  url = base_url + a['href']
                  urls.append(url)
      
          return urls
      
      
      # 출처 url로부터 영화인들의 사진, 이름, 최근작 정보를 가져오고 mystar 콜렉션에 저장합니다.
      def insert_star(url):
          headers = {
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
          data = requests.get(url, headers=headers)
      
          soup = BeautifulSoup(data.text, 'html.parser')
      
          name = soup.select_one('#content > div.article > div.mv_info_area > div.mv_info.character > h3 > a').text
          img_url = soup.select_one('#content > div.article > div.mv_info_area > div.poster > img')['src']
          recent_work = soup.select_one(
              '#content > div.article > div.mv_info_area > div.mv_info.character > dl > dd > a:nth-child(1)').text
      
          doc = {
              'name': name,
              'img_url': img_url,
              'recent': recent_work,
              'url': url,
              'like': 0
          }
      
          db.mystar.insert_one(doc)
          print('완료!', name)
      
      
      # 기존 mystar 콜렉션을 삭제하고, 출처 url들을 가져온 후, 크롤링하여 DB에 저장합니다.
      def insert_all():
          db.mystar.drop()  # mystar 콜렉션을 모두 지워줍니다.
          urls = get_urls()
          for url in urls:
              insert_star(url)
      
      
      ### 실행하기
      insert_all()
      튜터가 미리 영화인들의 정보를 크롤링한 코드를 제공해주셨다
    • 위 파일을 실행하여 db에 저장하고 디렉토리에서 파일 자체를 삭제해 이후에 헷갈리지 않게끔 한다
  • # app.py
    
    from pymongo import MongoClient
    
    from flask import Flask, render_template, jsonify, request
    
    app = Flask(__name__)
    
    client = MongoClient('localhost', 27017)
    db = client.dbsparta
    
    
    # HTML 화면 보여주기
    @app.route('/')
    def home():
        return render_template('index.html')
    
    
    # API 역할을 하는 부분
    @app.route('/api/list', methods=['GET'])
    def show_stars():
        # like 수를 기준으로 내림차순 정렬 (구글링)
        movie_star = list(db.mystar.find({}, {'_id': False}).sort('like', -1))
        return jsonify({'movie_stars': movie_star})
    
    
    @app.route('/api/like', methods=['POST'])
    def like_star():
        name_receive = request.form['name_give']
        # db에서 해당 이름의 좋아요 수 불러오기
        target_star = db.mystar.find_one({'name': name_receive})
        current_like = target_star['like']
        # 현재 좋아요 값에 1 더해줌
        new_like = current_like + 1
        # 새 좋아요 값을 db에 업데이트
        db.mystar.update_one({'name': name_receive}, {'$set': {'like': new_like}})
    
        return jsonify({'msg': '좋아요 완료'})
    
    
    @app.route('/api/delete', methods=['POST'])
    def delete_star():
        name_receive = request.form['name_give']
    
        db.mystar.delete_one({'name': name_receive})
    
        return jsonify({'msg': '삭제 완료'})
    
    
    if __name__ == '__main__':
        app.run('0.0.0.0', port=5000, debug=True)
    <!--index.html-->
    
    <!DOCTYPE html>
    <html lang="ko">
        <head>
            <meta charset="UTF-8"/>
            <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
            <title>마이 페이보릿 무비스타 | 프론트-백엔드 연결 마지막 예제!</title>
            <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
            <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.8.0/css/bulma.min.css"/>
            <script defer src="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script>
            <style>
                .center {
                    text-align: center;
                }
    
                .star-list {
                    width: 500px;
                    margin: 20px auto 0 auto;
                }
    
                .star-name {
                    display: inline-block;
                }
    
                .star-name:hover {
                    text-decoration: underline;
                }
    
                .card {
                    margin-bottom: 15px;
                }
            </style>
            <script>
                $(document).ready(function () {
                    showStar();
                });
    
                function showStar() {
                    $.ajax({
                        type: 'GET',
                        url: '/api/list',
                        data: {},
                        success: function (response) {
                            let mystars = response['movie_stars']
    
                            for (let i = 0; i < mystars.length; i++) {
                                let img_url = mystars[i]['img_url']
                                let like = mystars[i]['like']
                                let name = mystars[i]['name']
                                let recent = mystars[i]['recent']
                                let url = mystars[i]['url']
    
                                let temp_html = `<div class="card">
                                                    <div class="card-content">
                                                        <div class="media">
                                                            <div class="media-left">
                                                                <figure class="image is-48x48">
                                                                    <img
                                                                            src="${img_url}"
                                                                            alt="Placeholder image"
                                                                    />
                                                                </figure>
                                                            </div>
                                                            <div class="media-content">
                                                                <a href="${url}" target="_blank" class="star-name title is-4">${name} (좋아요: ${like})</a>
                                                                <p class="subtitle is-6">${recent}</p>
                                                            </div>
                                                        </div>
                                                    </div>
                                                    <footer class="card-footer">
                                                        <a href="#" onclick="likeStar('${name}')" class="card-footer-item has-text-info">
                                                            위로!
                                                            <span class="icon">
                                                  <i class="fas fa-thumbs-up"></i>
                                                </span>
                                                        </a>
                                                        <a href="#" onclick="deleteStar('${name}')" class="card-footer-item has-text-danger">
                                                            삭제
                                                            <span class="icon">
                                                  <i class="fas fa-ban"></i>
                                                </span>
                                                        </a>
                                                    </footer>
                                                </div>`
                                $('#star-box').append(temp_html)
                            }
                        }
                    });
                }
    
                function likeStar(name) {
                    $.ajax({
                        type: 'POST',
                        url: '/api/like',
                        data: {name_give:name},
                        success: function (response) {
                            alert(response['msg']);
                            window.location.reload()
                        }
                    });
                }
    
                function deleteStar(name) {
                    $.ajax({
                        type: 'POST',
                        url: '/api/delete',
                        data: {name_give:name},
                        success: function (response) {
                            alert(response['msg']);
                            window.location.reload()
                        }
                    });
                }
    
            </script>
        </head>
        <body>
            <section class="hero is-warning">
                <div class="hero-body">
                    <div class="container center">
                        <h1 class="title">
                            마이 페이보릿 무비스타😆
                        </h1>
                        <h2 class="subtitle">
                            순위를 매겨봅시다
                        </h2>
                    </div>
                </div>
            </section>
            <div class="star-list" id="star-box">
            </div>
        </body>
    </html>
    ${}로 html에 js코드 작성할때, 원래 있던 따옴표는 다 그대로 유지하기! (${name}에서 버그)