데일리로그C:
article thumbnail
Published 2022. 6. 29. 23:29
22.06.29(수) Python/Web_log

Project 마이 페이보릿 무비스타

  ㄴ> flask, pymongo(DB저장), requests(크롤링), bs4 패키지 설치

 

1. DB 만들기(데이터쌓기=웹스크래핑)

<bash />
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()

     ㄴ> RUN > Robo Refresh 후 확인 OK  > 파이썬에서 파일 Delete하기

 

 

2. 뼈대 준비

 1) app.py

<bash />
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(): sample_receive = request.args.get('sample_give') print(sample_receive) return jsonify({'msg': 'list 연결되었습니다!'}) @app.route('/api/like', methods=['POST']) def like_star(): sample_receive = request.form['sample_give'] print(sample_receive) return jsonify({'msg': 'like 연결되었습니다!'}) @app.route('/api/delete', methods=['POST']) def delete_star(): sample_receive = request.form['sample_give'] print(sample_receive) return jsonify({'msg': 'delete 연결되었습니다!'}) if __name__ == '__main__': app.run('0.0.0.0', port=5000, debug=True)

 

 2) index.html

<bash />
<!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?sample_give=샘플데이터', data: {}, success: function (response) { alert(response['msg']); } }); } function likeStar(name) { $.ajax({ type: 'POST', url: '/api/like', data: {sample_give:'샘플데이터'}, success: function (response) { alert(response['msg']); } }); } function deleteStar(name) { $.ajax({ type: 'POST', url: '/api/delete', data: {sample_give:'샘플데이터'}, success: function (response) { alert(response['msg']); } }); } </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 class="card"> <div class="card-content"> <div class="media"> <div class="media-left"> <figure class="image is-48x48"> <img src="https://search.pstatic.net/common/?src=https%3A%2F%2Fssl.pstatic.net%2Fsstatic%2Fpeople%2Fportrait%2F201807%2F20180731143610623-6213324.jpg&type=u120_150&quality=95" alt="Placeholder image" /> </figure> </div> <div class="media-content"> <a href="#" target="_blank" class="star-name title is-4">김다미 (좋아요: 3)</a> <p class="subtitle is-6">안녕, 나의 소울메이트(가제)</p> </div> </div> </div> <footer class="card-footer"> <a href="#" onclick="likeStar('김다미')" class="card-footer-item has-text-info"> 위로! <span class="icon"> <i class="fas fa-thumbs-up"></i> </span> </a> <a href="#" onclick="deleteStar('김다미')" class="card-footer-item has-text-danger"> 삭제 <span class="icon"> <i class="fas fa-ban"></i> </span> </a> </footer> </div> </div> </body> </html>

 

 

 

3. GET(보여주기)

 1) 서버 : 저장되어있는 DB 내려주기(like가 큰 순으로!)

    --> 컬렉션 이름은 robo3t에서 확인할 것! 

<bash />
@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})

      ㄴ> pymongo 정렬 : db.mystar.find( ).sort('이름', 1 or -1) 

 

 2) 클라이언트

   (1) response 콘솔 확인

<bash />
function showStar() { $.ajax({ type: 'GET', url: '/api/list?sample_give=샘플데이터', data: {}, success: function (response) { let mystars = response['movie_stars'] console.log(mystars) } }); }

         ㄴ> response[ ' movie_stars' ] : app.py에 return 부분에 지정한 거임... 헷갈리기 금지 ㅠㅠ

 

   (2) 반복문 console 확인

       --> 받아와야할 내용: name, img, recent, url, like (robo로 알 수 있음)

<bash />
function showStar() { $.ajax({ type: 'GET', url: '/api/list?sample_give=샘플데이터', 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'] console.log(name, img_url, recent, url, like) } } }); }

 

   (3) 반복문 temp_html 작성

<code />
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>`

     ㄴ> 카드 html 복붙해서 해당부분 ${ } 로 변경!!!! (주의 ★ <a>에서 href= " ${ url } " 빠지지않게 !!!)

     ㄴ> 5000에 카드 다 생성된거 확인 후 카드 html 은 지워줄 것!

 

   (4) like 0 -> 높게 수정하기

         ㄴ> robo) 원하는 사람 like 우클릭 > edit document > like 숫자 변경 

 

 

4. POST(좋아요 기능)

   --> 클라이언트에서 이름(name_give) 받아서 해당 like 값을 찾은 다음, 그 값에 1을 더해서 덮어씌우기

 

 1) 서버

<bash />
@app.route('/api/like', methods=['POST']) def like_star(): name_receive = request.form['name_give'] <!--이름 받아야함--> target_star = db.mystar.find_one({'name': name_receive}) <!--이름 찾은 것 중에(find)--> current_like = target_star['like'] <!--like 값 가져오기--> new_like = current_like + 1 <!--찾은 like 값에 1 더하기--> db.mystar.update_one({'name': name_receive}, {'$set': {'like': new_like}}) <!--덮어씌우기(업데이트)--> return jsonify({'msg': '좋아요 완료!'})

 

 

 2) 클라이언트

<bash />
function likeStar(name) { $.ajax({ type: 'POST', url: '/api/like', data: {name_give:name}, <!--이름 건네주기--> success: function (response) { alert(response['msg']); <!--response 받아온걸 msg로 띄워준다--> window.location.reload() <!--refresh--> } }); }

 

 

5. POST(삭제하기 기능)

   --> 클라이언트에서 받은 이름(name_give)으로 찾고, 해당 이름을 삭제

 

 1) 서버

<bash />
@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': '삭제 완료!'})

 

 

 2) 클라이언트

<bash />
function deleteStar(name) { $.ajax({ type: 'POST', url: '/api/delete', data: {name_give:name}, <!--이름 받기--> success: function (response) { alert(response['msg']); <!--response 받아오면 msg로 띄워주기--> window.location.reload() <!--refresh--> } }); }

 

 

 

6. 완성본

 1) app.py

<code />
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

<code />
<!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?sample_give=샘플데이터', 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>

 

 

 

웹서비스 런칭

 

1. 서버

   --> 클라이언트(브라우저)가 요청을 하면 그릴 것을 주거나, Ajax 요청하면 Ajax에 대한 답으로 데이터를 주거나..

             ㄴ> 언제나 요청에 응답하려면, 항상 컴터 켜져있어야함(app.py 항상 실행), 공개 IP 주소 

             ㄴ> 해결: 클라우드 환경 (AWS 아마존 웹서비스)

 

 

2. AWS 서버 사기(1년 무료)

 1) 화면 우측 상단에 서울인지 확인!

 

 2) 인스턴스(=컴퓨터 한대) 시작 버튼 클릭       

      > Ubuntu Server 18.04 LTS 선택          리눅스 기반 OS : 오픈소스(라이센스 비용 X), 가장 보편적임

      > t2:micro 선택 후 시작하기 버튼 클릭

      > 키페어생성(잘 보관해야함) - RSA 유형, 이름 입력

      > 키페어 다운로드(바탕화면)

      > 인스턴스 시작 버튼 클릭

 

 3) 인스턴스 종료(다시 반납), 중지(잠깐 인스턴스 꺼두기), 재부팅

 

 

3. 원격접속

 1) Git Bash 켜기 > ssh -i 키페어파일 갖다넣기 ubuntu@퍼블릭IPv4주소  > 엔터 > yes 입력

 2) 맨 마지막 줄에 ubuntu@ip~~~~~~~~:~$ 나오면 원격접속 성공!

 

 

4. 명령어 공부 (★띄어쓰기 중요★)

 1) mkdir 폴더 이름 > 엔터 : make directory (폴더 만들어줘)

 2) l(엘)s > 엔터 : 내 위치에서 폴더가 하나 있어요 라는 의미

 3) cd 폴더이름/ > 엔터 : 폴더에 들어가줘

 4)  ~$ : 경로(내 위치)

 5) cd .. > 엔터 : 폴더 나가기

'Python > Web_log' 카테고리의 다른 글

22.07.01(금)  (0) 2022.07.02
22.06.30(목)  (0) 2022.07.02
22.06.28(화)  (0) 2022.06.28
22.06.27(월)  (0) 2022.06.27
22.06.24(금)  (0) 2022.06.24
profile

데일리로그C:

@망밍

포스팅이 도움됐다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!