11코딩완주챌린지 [5주차] 10,11일차
1. 학습내용
✔
✔[무비스타] - 프로젝트 세팅
flask,pymongo,requests,bs4세팅
✔[무비스타] - DB 만들기(데이터 쌓기)
moviestar 폴더 안에 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()
Run 실행해주기 (리스트가 완료될 것!)
✔[무비스타] - 뼈대 준비하기
<서버코드>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():
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)
<클라이언트 코드>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/[email protected]/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>
✔[무비스타] - GET연습(보여주기) : 영화인 정보를 카드로 보여주기(Read)
API 만들고 사용하기 - 영화인 조회 API (Read → GET)
(1) 조회(Read) 기능: 영화인 정보 전체를 조회
1. 클라이언트와 서버 연결 확인하기
<서버 코드> app.py
@app.route('/api/list', methods=['GET'])
def show_stars():
sample_receive = request.args.get('sample_give')
print(sample_receive)
return jsonify({'msg': 'list 연결되었습니다!'})
<클라이언트 코드> index.html
function showStar() {
$.ajax({
type: 'GET',
url: '/api/list?sample_give=샘플데이터',
data: {},
success: function (response) {
alert(response['msg']);
}
});
}
app.py에서 Run 실행 후, localhost:5000Enter 후 새로고침했을 때, 'list 연결되었습니다.' 라는 메시지가 뜨면 동작하는 것입니다.
- 서버부터 만들기
서버가 하는 일
\1. mystar 목록 전체를 검색합니다. ID는 제외하고 like 가 많은 순으로 정렬
\2. 성공하면 success 메시지와 함께 stars_list 목록을 클라이언트에 전달
@app.route('/api/list', methods=['GET'])
def show_stars():
movie_star = list(db.mystar.find({}, {'_id': False}).sort('like', -1)) ---pymongo sort w3chool 구글링
return jsonify({'movie_stars': movie_star})
- 클라이언트 만들기
클라이언트가 하는 일
\1. #star_box의 내부 html 태그를 모두 삭제
\2. 서버에 1) GET 방식으로, 2) /api/list 라는 주소로 stars_list를 요청
\3. 서버가 돌려준 stars_list를 stars라는 변수에 저장
\4. for 문을 활용하여 stars 배열의 요소를 차례대로 조회
\5. stars[i] 요소의 name, url, img_url, recent, like 키 값을 활용하여 값 조회
\6. 영화인 카드 코드 만들어 #star-box에 붙이기
function showStar() {
$.ajax({
type: 'GET',
url: '/api/list?sample_give=샘플데이터',
data: {},
success: function (response) {
let mystars = response['movie_stars']
console.log(mystars)
}
});
}
페이지에서 새로고침 후 검사 및 콘솔창에서 잘 돌아가는지 확인!
for 문 돌아야 한다.
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)
}
}
});
}
페이지에서 새로고침 후 검사 및 콘솔창에서 잘 돌아가는지 확인!
<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>
하단에서 cards안에 있는 것들 가져오기
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)
}
}
});
}
하단에서 가져온 id값인 star-box를 붙여주며, 그 하단에 있던 card...는 지워도 된다.
- 완성 확인하기
화면을 새로고침 했을 때 영화인 정보가 조회되는지 확인합니다.
Robot3T실행하여 mystar에서 한 사람의 like를 조정하여(Edit Document 클릭) 저장 후 페이지 새로고침 했을 때 한 사람이 첫번째 위로 가는지 확인!
✔[무비스타] - POST연습(좋아요+1)
API 만들고 사용하기 - 좋아요 API (Update → POST)
(2) 좋아요: 클라이언트에서 받은 이름(name_give)으로 찾아서 좋아요(like)를 증가
1. 클라이언트와 서버 연결 확인하기
<서버 코드>app.py
@app.route('/api/like', methods=['POST'])
def like_star():
sample_receive = request.form['sample_give']
print(sample_receive)
return jsonify({'msg': 'like 연결되었습니다!'})
<클라이언트 코드>index.html
function likeStar(name) {
$.ajax({
type: 'POST',
url: '/api/like',
data: {sample_give:'샘플데이터'},
success: function (response) {
alert(response['msg']);
}
});
}
'위로' 버튼을 눌렀을 때, 'like 연결되었습니다!' 내용의 alert창이 뜨면 제대로 동작하는 것입니다.
- 서버부터 만들기
서버가 하는 일
\1. 클라이언트가 전달한 name_give를 name_receive 변수에 넣습니다.
\2. mystar 목록에서 find_one으로 name이 name_receive와 일치하는 star를 찾습니다.
\3. star의 like 에 1을 더해준 new_like 변수를 만듭니다.
\4. mystar 목록에서 name이 name_receive인 문서의 like 를 new_like로 변경합니다.
@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'] ---찾은 것중에 like값을 찾아야 해요!
new_like = current_like + 1 ---like값에 1를 더한 것!
db.mystar.update_one({'name': name_receive}, {'$set': {'like': new_like}}) ---/4
return jsonify({'msg': '좋아요 완료!'})
- 클라이언트 만들기
클라이언트가 하는 일
\1. 서버에
1) POST 방식으로,
2) /api/like 라는 url에,
3) name_give라는 이름으로 name을 전달합니다.
(참고) POST 방식이므로 data: {'name_give': name} 사용
\2. '좋아요 완료!' alert 창을 띄웁니다.
\3. 변경된 정보를 반영하기 위해 새로고침합니다.
function likeStar(name) {
$.ajax({
type: 'POST',
url: '/api/like',
data: {name_give:name},
success: function (response) {
alert(response['msg']);
window.location.reload()
}
});
}
- 완성 확인하기
'위로' 버튼을 눌렀을 때 좋아요 수가 증가하고 영화인 카드의 순위가 변경되는지 확인합니다.
✔[무비스타] - POST연습(삭제하기)
API 만들고 사용하기 - 카드 삭제 API (Delete → POST)
(3). 삭제(Delete) 기능: 클라이언트에서 받은 이름(name_give)으로 영화인을 찾고, 해당 영화인을 삭제
1. 클라이언트와 서버 연결 확인하기
<서버 코드>app.py
@app.route('/api/delete', methods=['POST'])
def delete_star():
sample_receive = request.form['sample_give']
print(sample_receive)
return jsonify({'msg': 'delete 연결되었습니다!'})
<클라이언트 코드>index.html
function deleteStar(name) {
$.ajax({
type: 'POST',
url: '/api/delete',
data: {sample_give:'샘플데이터'},
success: function (response) {
alert(response['msg']);
}
});
}
'삭제' 버튼을 눌렀을 때, 'delete 연결되었습니다!' alert창이 뜨면
클라이언트 코드와 서버 코드가 연결 되어있는 것입니다.
2.서버부터 만들기
서버가 하는 일
\1. 클라이언트가 전달한 name_give를 name_receive 변수에 넣기
\2. mystar 에서 delete_one으로 name이 name_receive와 일치하는 star를 제거
\3. 성공하면 success 메시지를 반환
@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': '삭제 완료!'})
- 클라이언트 만들기
클라이언트가 하는 일
\1. 서버에
1) POST 방식으로,
2) /api/delete 라는 url에,
3) name_give라는 이름으로 name을 전달
(참고) POST 방식이므로 data: {'name_give': name}
\2. '삭제 완료! 안녕!' alert창 띄우기
\3. 변경된 정보를 반영하기 위해 새로고침
function deleteStar(name) {
$.ajax({
type: 'POST',
url: '/api/delete',
data: {name_give:name},
success: function (response) {
alert(response['msg']);
window.location.reload()
}
});
}
- 완성 확인하기
삭제 버튼을 눌렀을 때 영화인 카드가 삭제되는지 확인합니다.
✔내 프로젝트를 서버에 올리기
- 언제나 요청에 응답하려면,
1) 컴퓨터가 항상 켜져있고 프로그램이 실행되어 있어야하고,
2) 모두가 접근할 수 있는 공개 주소인 공개 IP 주소(Public IP Address)로 나의 웹 서비스에 접근할 수 있도록 해야해요. - 서버는 그냥 컴퓨터라는거 기억나시죠? 외부 접속이 가능하게 설정한 다음에 내 컴퓨터를 서버로 사용할 수도 있어요.
- 우리는 AWS 라는 클라우드 서비스에서 편하게 서버를 관리하기 위해서 항상 켜 놓을 수 있는 컴퓨터인 EC2 사용권을 구입해 서버로 사용할 겁니다.
✔AWS 서버 구매하기
[가장 많이 쓰이는 리눅스 명령어]
ls: 내 위치의 모든 파일을 보여준다.
pwd: 내 위치(폴더의 경로)를 알려준다.
mkdir: 내 위치 아래에 폴더를 하나 만든다.
cd [갈 곳]: 나를 [갈 곳] 폴더로 이동시킨다.
cd .. : 나를 상위 폴더로 이동시킨다.
cp -r [복사할 것][붙여넣기 할 것]: 복사 붙여넣기
rm -rf [지울 것]: 지우기
sudo [실행 할 명령어]: 명령어를 관리자 권한으로 실행한다.
sudo su: 관리가 권한으로 들어간다. (나올때는 exit으로 나옴)
그 후 만들었던 페이지를 서버에 올리는 과정은 강의자료에 쏙쏙쏙!!!
2. 학습소감
이로써 커리큘럼이 마치는 순간, 들었던 건 웹페이지하나가 공개적으로 올리는 과정이 넘나 신기했고, 기본적인 HTML, CSS, Javascript를 기초적인 거 배우면서 코드를 짜고 디자인하고 크롤링하면서 DB에 저장 후 서버에 올리는 과정이 참 재미있었고 처음으로 나와 이 프로그래밍과의 합을 맞춘 토대가 되어준 이 강의가 도움이 많이 되었다. 에러가 날 때, 모르는 코드는 구글링하며, 참고가 되어주는 부트스트랩 같은 기능을 보면서 참 이 직업을 택하더라도 아이디어와 커뮤니케이션 스킬, 끈기 등등 충분하다면, 이 직업으로 취업도전할 마음이 생긴것같다.
일단은 한번 따라해봤으니, 강의 한번 더 복습하고, 다음 강의커리큘럼에 레벨업해야겠다!!!
-----------웹개발 종합반(왕초보 시작반) 끝-------------
Author And Source
이 문제에 관하여(11코딩완주챌린지 [5주차] 10,11일차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@yimji20/11코딩완주챌린지-5주차-10일차저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)