from flask import Flask, render_template, jsonify, request
import requests
from bs4 import BeautifulSoup
from pymongo import MongoClient # pymongo를 임포트 하기(패키지 인스톨 먼저 해야겠죠?)
app = Flask(__name__)
client = MongoClient('localhost', 27017) # mongoDB는 27017 포트로 돌아갑니다.
db = client.dbsparta # 'dbsparta'라는 이름의 db를 만들거나 사용합니다.
@app.route('/')
def home():
return render_template('index.html')
@app.route('/memo', methods=['POST'])
def post_article():
# 1. 클라이언트로부터 데이터를 받기
url_receive = request.form['url_give'] # 클라이언트로부터 url을 받는 부분
comment_receive = request.form['comment_give'] # 클라이언트로부터 comment를 받는 부분
# 2. meta tag를 스크래핑하기
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_receive, headers=headers)
soup = BeautifulSoup(data.text, 'html.parser')
og_image = soup.select_one('meta[property="og:image"]')
og_title = soup.select_one('meta[property="og:title"]')
og_description = soup.select_one('meta[property="og:description"]')
url_title = og_title['content']
url_description = og_description['content']
url_image = og_image['content']
article = {'url': url_receive, 'title': url_title, 'desc': url_description, 'image': url_image,
'comment': comment_receive}
# 3. mongoDB에 데이터를 넣기
db.articles.insert_one(article)
return jsonify({'result': 'success'})
@app.route('/memo', methods=['GET'])
def read_articles():
# 1. mongoDB에서 _id 값을 제외한 모든 데이터 조회해오기 (Read)
result = list(db.articles.find({}, {'_id': 0}))
# 2. articles라는 키 값으로 article 정보 보내주기
return jsonify({'result': 'success', 'articles': result})
if __name__ == '__main__':
app.run('0.0.0.0', port=5000, debug=True)
<!Doctype html>
<html lang="ko">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"
integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
<!-- JS -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="../static/index.js"></script>
<link href="https://fonts.googleapis.com/css?family=Stylish&display=swap" rel="stylesheet">
<title>SW사관학교 정글 | 나홀로 메모장</title>
<!-- style -->
<style type="text/css">
* {
font-family: "Stylish", sans-serif;
}
.wrap {
width: 900px;
margin: auto;
}
.comment {
color: blue;
font-weight: bold;
}
#post-box {
width: 500px;
margin: 20px auto;
padding: 50px;
border: black solid;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="wrap">
<div class="jumbotron">
<h1 class="display-4">나홀로 링크 메모장!</h1>
<p class="lead">중요한 링크를 저장해두고, 나중에 볼 수 있는 공간입니다</p>
<hr class="my-4">
<p class="lead">
<button onclick="openClose()" id="btn-post-box" type="button" class="btn btn-primary">포스팅 박스 열기
</button>
</p>
</div>
<div id="post-box" class="form-post" style="display:none">
<div>
<div class="form-group">
<label for="post-url">아티클 URL</label>
<input id="post-url" class="form-control" placeholder="">
</div>
<div class="form-group">
<label for="post-comment">간단 코멘트</label>
<textarea id="post-comment" class="form-control" rows="2"></textarea>
</div>
<button type="button" class="btn btn-primary" onclick="postArticle()">기사저장</button>
</div>
</div>
<div id="cards-box" class="card-columns">
<div class="card">
<img class="card-img-top"
src="https://www.eurail.com/content/dam/images/eurail/Italy%20OCP%20Promo%20Block.adaptive.767.1535627244182.jpg"
alt="Card image cap">
<div class="card-body">
<a href="#" class="card-title">여기 기사 제목이 들어가죠</a>
<p class="card-text">기사의 요약 내용이 들어갑니다. 동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세 무궁화 삼천리 화려강산...</p>
<p class="card-text comment">여기에 코멘트가 들어갑니다.</p>
</div>
</div>
<div class="card">
<img class="card-img-top"
src="https://www.eurail.com/content/dam/images/eurail/Italy%20OCP%20Promo%20Block.adaptive.767.1535627244182.jpg"
alt="Card image cap">
<div class="card-body">
<a href="#" class="card-title">여기 기사 제목이 들어가죠</a>
<p class="card-text">기사의 요약 내용이 들어갑니다. 동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세 무궁화 삼천리 화려강산...</p>
<p class="card-text comment">여기에 코멘트가 들어갑니다.</p>
</div>
</div>
<div class="card">
<img class="card-img-top"
src="https://www.eurail.com/content/dam/images/eurail/Italy%20OCP%20Promo%20Block.adaptive.767.1535627244182.jpg"
alt="Card image cap">
<div class="card-body">
<a href="#" class="card-title">여기 기사 제목이 들어가죠</a>
<p class="card-text">기사의 요약 내용이 들어갑니다. 동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세 무궁화 삼천리 화려강산...</p>
<p class="card-text comment">여기에 코멘트가 들어갑니다.</p>
</div>
</div>
<div class="card">
<img class="card-img-top"
src="https://www.eurail.com/content/dam/images/eurail/Italy%20OCP%20Promo%20Block.adaptive.767.1535627244182.jpg"
alt="Card image cap">
<div class="card-body">
<a href="#" class="card-title">여기 기사 제목이 들어가죠</a>
<p class="card-text">기사의 요약 내용이 들어갑니다. 동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세 무궁화 삼천리 화려강산...</p>
<p class="card-text comment">여기에 코멘트가 들어갑니다.</p>
</div>
</div>
<div class="card">
<img class="card-img-top"
src="https://www.eurail.com/content/dam/images/eurail/Italy%20OCP%20Promo%20Block.adaptive.767.1535627244182.jpg"
alt="Card image cap">
<div class="card-body">
<a href="#" class="card-title">여기 기사 제목이 들어가죠</a>
<p class="card-text">기사의 요약 내용이 들어갑니다. 동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세 무궁화 삼천리 화려강산...</p>
<p class="card-text comment">여기에 코멘트가 들어갑니다.</p>
</div>
</div>
<div class="card">
<img class="card-img-top"
src="https://www.eurail.com/content/dam/images/eurail/Italy%20OCP%20Promo%20Block.adaptive.767.1535627244182.jpg"
alt="Card image cap">
<div class="card-body">
<a href="#" class="card-title">여기 기사 제목이 들어가죠</a>
<p class="card-text">기사의 요약 내용이 들어갑니다. 동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세 무궁화 삼천리 화려강산...</p>
<p class="card-text comment">여기에 코멘트가 들어갑니다.</p>
</div>
</div>
</div>
</div>
</body>
</html>
$(document).ready(function () {
showArticles();
});
function openClose() {
// id 값 post-box의 display 값이 block 이면(= 눈에 보이면)
if ($("#post-box").css("display") == "block") {
// post-box를 가리고
$("#post-box").hide();
// 다시 버튼을 클릭하면, 박스 열기를 할 수 있게 텍스트 바꿔두기
$("#btn-post-box").text("포스팅 박스 열기");
} else {
// 아니면(눈에 보이지 않으면) post-box를 펴라
$("#post-box").show();
// 다시 버튼을 클릭하면, 박스 닫기를 할 수 있게 텍스트 바꿔두기
$("#btn-post-box").text("포스팅 박스 닫기");
}
}
function postArticle() {
let url = $("#post-url").val();
let comment = $("#post-comment").val();
// 2. memo에 POST 방식으로 메모 생성 요청하기
$.ajax({
type: "POST", // POST 방식으로 요청하겠다.
url: "/memo", // /memo라는 url에 요청하겠다.
data: {
url_give: url,
comment_give: comment
}, // 데이터를 주는 방법
success: function (response) { // 성공하면
if (response["result"] == "success") {
alert("포스팅 성공!");
// 3. 성공 시 리스트 새로고침하기
showArticles();
} else {
alert("서버 오류!")
}
}
})
}
function showArticles() {
$("#cards-box").html("");
$.ajax({
type: "GET",
url: "/memo",
data: {},
success: function (response) {
let articles = response["articles"];
console.log(articles);
for (let i = 0; i < articles.length; i++) {
makeCard(articles[i]["image"], articles[i]["url"], articles[i]["title"], articles[i]["desc"],
articles[i]["comment"]);
}
}
});
}
function makeCard(image, url, title, desc, comment) {
let tempHtml = `<div class="card">
<img class="card-img-top" src="${image}" alt="Card image cap">
<div class="card-body">
<a href="${url}" target="_blank" class="card-title">${title}</a>
<p class="card-text">${desc}</p>
<p class="card-text comment">${comment}</p>
</div>
</div>`;
$("#cards-box").append(tempHtml);
}
아래 정리된 내용을 참고한다.
data: {
url_give: $("#post-url").val(),
comment_give: $("#post-comment").val()
}, // 데이터를 주는 방법
client = MongoClient('localhost', 27017)
db = client.dbsparta
데이터가 변수 article 에 저장, 그것을 db.articles에 insert_one(). 즉, db의 articles 폴더에 저장.
http://localhost:5000/memo에 접속했을 때, 결과가 JSON 형식으로 보이면 성공입니다. 브라우저에서 주소창에 엔터를 치는 것이 GET 요청과 같다는 사실, 기억하시죠??
네이버 메인 아무거나 들어가서 포스트 주소를 가져왔다.
https://post.naver.com/viewer/postView.naver?volumeNo=33033414&memberNo=48374180
결과는 다음과 같이 잘 작동한다.
스게... 신기하다.