*/스파르타코딩클럽 웹개발종합반

[스파르타코딩클럽 | 웹개발종합반] 5주차: 미니프로젝트3, AWS

sssbin 2021. 9. 13. 01:04

 

1. moviestar

  ▶ DB 만들기 (데이터 쌓기)

# db_init.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()

  ▶ pymongo 정렬

col.find().sort(fieldname, direction)
# fieldname : 정렬 기준 필드
# direction : 정렬 방향 (1: 오름차순, -1: 내림차순)

 

  1) 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():
    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']

    target_star = db.mystar.find_one({'name':name_receive})
    current_like = target_star['like']

    new_like = current_like + 1
    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)

  2) 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 name = mystars[i]['name']
                            let img_url = mystars[i]['img_url']
                            let recent = mystars[i]['recent']
                            let url = mystars[i]['url']
                            let like = mystars[i]['like']

                            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>

 

2. AWS

  1) ec2 인스턴스 시작

  2) filezila 다운 → 연결 만들어주기 (호스트: ec2 퍼블릭 IPv4 주소)\\

  3) 서버 세팅

https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/web101/week5/initial_ec2.sh
sudo chmod 755 initial_ec2.sh
./initial_ec2.sh

  4) 패키지 설치

pip install flask
pip install pymongo

  5) ec2 포트 열어주기

  6) Robo3T → 내 서버(ec2) 주소로 connection 생성, authentication 생성 (username: test, pw: test)

      ** 참고 **

initial_ec2.sh 파일의 user, pwd 부분
app.py  파일의 db 연결 부분

  7) 파일 넣어서 실행시키면 끝!

  8) 포트 번호를 떼보자

- http 요청에서는 80포트가 기본 → :80을 붙이지 않아도 자동으로 연결됨
- 80포트로 오는 요청을 5000포트로 전달하게 하는 포트포워딩(port forwarding) 사용
- 리눅스에서 기본으로 제공해주는 포트포워딩 사용! 따라서 그냥 포트번호 떼도 실행 됨!

   ** 참고 ** (initial_ec2.sh 파일에서 이미 해줬음)

# 80포트 -> 5000포트
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 5000

  9) nohup 설정하기 (계속해서 서버가 실행되도록 함)

nohup python app.py &

  10) 서버 종료하기

# 아래 명령어로 미리 pid 값(프로세스 번호)을 본다
ps -ef | grep 'app.py'

# 아래 명령어로 특정 프로세스를 죽인다
kill -9 [pid값]

  11) 도메인 구입하기

      - 가비아 → DNS 관리 툴 → 설정 → 레코드 수정 → 레코드 추가

      - 호스트: @

      - 값/위치: 서버 주소

     → 도메인으로 연결 가능!

 

  12) og 태그 만들기

<!-- index.html -->

<meta property="og:title" content="내 사이트의 제목" />
<meta property="og:description" content="보고 있는 페이지의 내용 요약" />
<meta property="og:image" content="{{ url_for('static', filename='ogimage.png') }}" />

    ** 참고 **

        - 페이스북 og 태그 초기화 하기: https://developers.facebook.com/tools/debug/

        - 카카오톡 og 태그 초기화 하기: https://developers.kakao.com/tool/clear/og