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 |