728x90
로그인페이지, 회원가입페이지, 메인페이지, 총 3가지 페이지가 준비되었다
로그인 페이지 코드 (클라이언트)
<!doctype html>
<html lang="en">
<head>
<!-- Webpage Title -->
<title>Log In | SWEETER</title>
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
<meta property="og:title" content="MSS - My Small Space"/>
<meta property="og:description" content="mini project for Web Plus"/>
<meta property="og:image" content="{{ url_for('static', filename='ogimg.png') }}"/>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bulma CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.1/css/bulma.min.css">
<!-- Font Awesome CSS -->
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- Google Font -->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Gamja+Flower&family=Stylish&display=swap" rel="stylesheet">
<!-- JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"></script>
<style>
.title {
font-weight: 800;
font-size: 5rem;
font-family: 'Stylish', sans-serif;
}
.subtitle {
font-family: 'Gamja Flower', cursive;
font-size: 2rem;
}
.help {
color: gray;
}
</style>
<script>
// .toggleClass 로 열닫 기능
function toggle_sign_up() {
$("#sign-up-box").toggleClass("is-hidden")
$("#div-sign-in-or-up").toggleClass("is-hidden")
$("#btn-check-dup").toggleClass("is-hidden")
$("#help-id").toggleClass("is-hidden")
$("#help-password").toggleClass("is-hidden")
$("#help-password2").toggleClass("is-hidden")
}
// 정규 표현식
function is_nickname(asValue) {
var regExp = /^(?=.*[a-zA-Z])[-a-zA-Z0-9_.]{6,15}$/;
// (?=.*[a-zA-Z]) - a-z 혹은 A-Z가 꼭 있어야하고
// [-a-zA-Z0-9_.] - 나머지는 a-z, A-Z, 0-9, _, . 까지 있어도 되고
// {2,10} 최소 2자리에서 최대 10자리 까지 이다.
return regExp.test(asValue);
}
function is_password(asValue) {
var regExp = /^(?=.*\d)(?=.*[a-zA-Z])[0-9a-zA-Z!@#$%^&*]{8,20}$/;
return regExp.test(asValue);
}
function check_dup() {
// input 값 받기
let username = $("#input-username").val()
console.log(username)
// input 값이 아무것도 없을경우
if (username == "") {
$("#help-id").text("Enter Your ID").removeClass("is-safe").addClass("is-danger")
$("#input-username").focus()
return;
}
// input값을 위에서 만든 정규표현식 id에 넣었는데 원하는 아이디 형식이 아닐경우
if (!is_nickname(username)) {
$("#help-id").text("Please Check Your ID").removeClass("is-safe").addClass("is-danger")
$("#input-username").focus()
return;
}
// 그 외에 아이디 생성이 가능할때
$("#help-id").addClass("is-loading")
$.ajax({
type: "POST",
url: "/sign_up/check_dup",
data: {
username_give: username
},
success: function (response) { // db에 있는 아이디 일 경우
// 아이디가 이미 db에 있는지 체크
if (response["exists"]) {
$("#help-id").text("Already Used ID").removeClass("is-safe").addClass("is-danger")
$("#input-username").focus()
} else { // 없는경우, .addClass("is-success")를 추가해서, 회원가입전에 중복확인이 성공적인지 체크가 가능
$("#help-id").text("Able to Use This ID").removeClass("is-danger").addClass("is-success")
}
$("#help-id").removeClass("is-loading")
}
});
}
function sign_up() {
let username = $("#input-username").val()
let password = $("#input-password").val()
let password2 = $("#input-password2").val()
console.log(username, password, password2)
if ($("#help-id").hasClass("is-danger")) {
alert("Please Check Your ID Again")
return;
} else if (!$("#help-id").hasClass("is-success")) {
alert("Please Check If Your ID is Duplicated.")
return;
}
if (password == "") {
$("#help-password").text("Enter Your Password").removeClass("is-safe").addClass("is-danger")
$("#input-password").focus()
return;
} else if (!is_password(password)) {
$("#help-password").text("Please Check Your Password Type").removeClass("is-safe").addClass("is-danger")
$("#input-password").focus()
return
} else {
$("#help-password").text("Able to Use This Password").removeClass("is-danger").addClass("is-success")
}
if (password2 == "") {
$("#help-password2").text("Enter Your Password").removeClass("is-safe").addClass("is-danger")
$("#input-password2").focus()
return;
} else if (password2 != password) {
$("#help-password2").text("Invaild Password").removeClass("is-safe").addClass("is-danger")
$("#input-password2").focus()
return;
} else {
$("#help-password2").text("Valid Password").removeClass("is-danger").addClass("is-success")
}
$.ajax({
type: "POST",
url: "/sign_up/save",
data: {
username_give: username,
password_give: password
},
success: function (response) {
alert("Thank You for Signing Up")
window.location.replace("/login")
}
});
}
function sign_in() {
let username = $("#input-username").val()
let password = $("#input-password").val()
if (username == "") {
$("#help-id-login").text("Enter Your ID.")
$("#input-username").focus()
return;
} else {
$("#help-id-login").text("")
}
if (password == "") {
$("#help-password-login").text("Enter Your Password")
$("#input-password").focus()
return;
} else {
$("#help-password-login").text("")
}
// API를 보내기
$.ajax({
type: "POST",
url: "/sign_in",
data: {
// ID와 비밀번호
username_give: username,
password_give: password
},
// 보내기에 성공하면,
success: function (response) {
if (response['result'] == 'success') {
// 제이쿼리로 쿠키 생성
$.cookie('mytoken', response['token'], {path: '/'});
window.location.replace("/")
//href는 페이지를 이동하는 것이기 때문에 뒤로가기 버튼을 누른경우 이전 페이지로 이동이 가능하지만,
// replace는 현재 페이지를 새로운 페이지로 덮어 씌우기 때문에 이전 페이지로 이동이 불가능하다.
} else {
alert(response['msg'])
}
}
});
}
</script>
</head>
<body style="background-color: #F2F2F2 !important; ">
<section class="hero is-white" >
<div class="hero-body has-text-centered" style="padding-bottom:1rem;margin:auto;">
<h1 class="title is-sparta">M S S</h1>
<h3 class="subtitle is-sparta">My Small Space</h3>
</div>
</section>
<section class="section">
<div class="container">
<div class="box" style="max-width: 480px;margin:auto">
<article class="media">
<div class="media-content">
<div class="content">
<div class="field has-addons">
<div class="control has-icons-left" style="width:100%">
<input id="input-username" class="input" type="text" placeholder="ID or Nick Name">
<span class="icon is-small is-left"><i class="fa fa-user"></i></span>
</div>
<div id="btn-check-dup" class="control is-hidden">
<button class="button is-sparta" onclick="check_dup()">Duplication Check</button>
</div>
</div>
<p id="help-id" class="help is-hidden">At Least 6 Letters of English or Numbers or Special
Letters( . _ ),
<br>Maximum 15 Letters</p>
<p id="help-id-login" class="help is-danger"></p>
<div class="field">
<div class="control has-icons-left">
<input id="input-password" class="input" type="password" placeholder="Password">
<span class="icon is-small is-left"><i class="fa fa-lock"></i></span>
</div>
<p id="help-password" class="help is-hidden">At Least 8 Letters of English or Numbers or
Special Letters( !@#$%^&* ), <br>Maximum 20 Letters
</p>
<p id="help-password-login" class="help is-danger"></p>
</div>
</div>
<div id="div-sign-in-or-up" class="has-text-centered">
<nav class="level is-mobile">
<button class="level-item button is-sparta" onclick="sign_in()">
Sign In
</button>
</nav>
<hr>
<h4 class="mb-3">Want to be a Member of MSS?</h4>
<nav class="level is-mobile">
<button class="level-item button is-sparta is-outlined"
onclick="toggle_sign_up()">
Sign Up
</button>
</nav>
</div>
<div id="sign-up-box" class="is-hidden">
<div class="mb-5">
<div class="field">
<div class="control has-icons-left" style="width:100%">
<input id="input-password2" class="input" type="password"
placeholder="Verify Password">
<span class="icon is-small is-left"><i class="fa fa-lock"></i></span>
</div>
<p id="help-password2" class="help is-hidden">Verify Password</p>
</div>
</div>
<nav class="level is-mobile">
<button class="level-item button is-sparta" onclick="sign_up()">
Submit
</button>
<button class="level-item button is-sparta is-outlined" onclick="toggle_sign_up()">
Cancel
</button>
</nav>
</div>
</div>
</article>
</div>
</div>
</section>
</body>
</html>
로그인페이지 코드(서버)
from pymongo import MongoClient
import jwt
import datetime
import hashlib
from flask import Flask, render_template, jsonify, request, redirect, url_for
from werkzeug.utils import secure_filename
from datetime import datetime, timedelta
app = Flask(__name__) # Flask 객체를 app이라는 변수에 할당
#config안의 속성들의 값을 조절
app.config["TEMPLATES_AUTO_RELOAD"] = True
app.config['UPLOAD_FOLDER'] = "./static/profile_pics"
SECRET_KEY = 'SPARTA' # 로그인 토큰 만들때 secret key
# Mongo DB에 연결
client = MongoClient('13.124.196.127', 27017, username="test", password="test")
db = client.dbsparta_project_01_mss
# main page
@app.route('/')
def home():
# 생성된 쿠키 가져오기
token_receive = request.cookies.get('mytoken')
try: #쿠키를 이용해서 jwt 자유이용권 만듬
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
# 자유이용권에 등록된 유저 id를 가져오기
user_info = db.users.find_one({"username": payload["id"]})
# 유저 정보를 jinja로 가져다 쓸수있게 return 해줌
return render_template('index.html', user_info=user_info)
# 에러처리
except jwt.ExpiredSignatureError:
return redirect(url_for("login", msg="로그인 시간이 만료되었습니다."))
except jwt.exceptions.DecodeError:
return redirect(url_for("login", msg="로그인 정보가 존재하지 않습니다."))
# 로그인 페이지
@app.route('/login')
def login():
msg = request.args.get("msg")
return render_template('login.html', msg=msg)
# 로그인
@app.route('/sign_in', methods=['POST'])
def sign_in():
username_receive = request.form['username_give']
password_receive = request.form['password_give']
pw_hash = hashlib.sha256(password_receive.encode('utf-8')).hexdigest()
result = db.users.find_one({'username': username_receive, 'password': pw_hash})
if result is not None:
payload = {
'id': username_receive,
'exp': datetime.utcnow() + timedelta(seconds=60 * 60 * 24) # 로그인 24시간 유지
}
token = jwt.encode(payload, SECRET_KEY, algorithm='HS256')
return jsonify({'result': 'success', 'token': token})
# 찾지 못하면
else:
return jsonify({'result': 'fail', 'msg': 'Wrong ID/PASSWORD'})
# 회원가입
@app.route('/sign_up/save', methods=['POST'])
def sign_up():
username_receive = request.form['username_give']
password_receive = request.form['password_give']
password_hash = hashlib.sha256(password_receive.encode('utf-8')).hexdigest()
doc = {
"username": username_receive,
"password": password_hash,
"profile_name": username_receive,
"profile_pic": "",
"profile_pic_real": "profile_pics/profile_placeholder.png",
"profile_info": ""
}
db.users.insert_one(doc)
return jsonify({'result': 'success'})
# 중복확인
@app.route('/sign_up/check_dup', methods=['POST'])
def check_dup():
# id 중복확인
username_receive = request.form['username_give'] #request form으로 username을 받고
# bool 값을 사용해서, db에 username이 있는지 체크
exists = bool(db.users.find_one({"username": username_receive}))
# bool 값을 넘겨줘서 있다 없다를 체크 가능
return jsonify({'result': 'success', 'exists': exists})
다음으로는 네이버 뉴스를 크롤링 해오고 있다. 아직 오류가 많아 수정을 더 해야하지만,
기본적인 title과 시간은 가져올 수 있다. 일단은 크롤링해서 DB에 저장한다.
python 코드
from selenium import webdriver
from bs4 import BeautifulSoup
import time
from selenium.common.exceptions import NoSuchElementException
from pymongo import MongoClient
import requests
# 몽고 db에 저장
client = MongoClient('13.124.196.127', 27017, username="test", password="test")
db = client.dbsparta_project_01_mss
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://news.naver.com/main/ranking/popularDay.naver',headers=headers)
soup = BeautifulSoup(data.text, 'html.parser')
news = soup.select('#wrap > div.rankingnews._popularWelBase._persist > div.rankingnews_box_wrap._popularRanking > div > div')
for data in news:
title = data.select_one('ul > li > div > a').text;
time = data.select_one('ul > li > div > span').text;
print(title, time);
# 찾은 내용들을 db에 저장하기
doc = {
"title": title,
"time": time,
}
db.news.insert_one(doc)
클라이언트 쪽에서는 페이지가 로딩될때마다 뉴스를 가져오게 해 두었다.
function get_news() {
$.ajax({
type: "GET",
url: `/news`,
data: {},
success: function (response) {
let news = response["news_list"];
{#console.log(news);#}
for (let i = 0; i < news.length; ++i) {
let title = news[i]['title'];
let time = news[i]['time']
console.log(title)
let html_temp = ` <ul class="news-list">
<li>${title}</li>
<span>${time}</span>
</ul>`
// add html
$('#news').append(html_temp)
}
}
});
}
아래는 현재 진행상황이다.
728x90
'Sparta > 스파르타코딩 웹개발 종합반' 카테고리의 다른 글
Node.js 01 - 자바스크립트 정리 (0) | 2022.03.14 |
---|---|
웹개발 종합반 프로젝트 - 06 뉴스크롤링(네이버뉴스) (0) | 2022.03.13 |
종합반 4주차 - Bulma, 로그인, 회원가입 기능 (0) | 2022.03.12 |
종합반 플러스 - 3주차 - 네이버API, 셀레니움 (0) | 2022.03.07 |
웹개발 종합반 프로젝트 - 04 날씨&즐겨찾기 (0) | 2022.03.07 |