Giter VIP home page Giter VIP logo

music_recommend_be's Introduction

๐Ÿ“Œํ•˜๋ฃจ์ข…์ผ ๋“ฃ๊ณ  ์‹ถ์–ด!

๋…ธ๋ž˜ ์ถ”์ฒœ ์„œ๋น„์Šค


1. ์ œ์ž‘ ๊ธฐ๊ฐ„ & ์ฐธ์—ฌ ์ธ์› & ๋งก์€ ์—ญํ• 

  • 2022๋…„ 11์›” 2์ผ ~ 11์›” 8์ผ
  • ํŒ€ ํ”„๋กœ์ ํŠธ (5๋ช…)
๋งก์€ ์—ญํ• 
  • ์œ ์ € ๊ด€๋ฆฌ ๋ฐ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ
  • Playlist ์ƒ์„ฑ/์ˆ˜์ •/์‚ญ์ œ ๋ฐ ์ƒ์„ธํŽ˜์ด์ง€ ๊ธฐ๋Šฅ

2. ์‚ฌ์šฉ ๊ธฐ์ˆ 

Back-end

  • Python 3.10.7
  • Django 4.1.3
  • DRF 3.14.0
  • Django simple JWT 5.2.2

Database

  • SQLite

Front-end

  • Vanilla JS
  • Element UI

Management

  • Notion
  • Github
  • Slack

3. ํ•ต์‹ฌ ๊ธฐ๋Šฅ

  • ์‚ฌ์šฉ์ž ํ™˜๊ฒฝ(ํšŒ์›๊ฐ€์ž…, ๋กœ๊ทธ์ธ, ํšŒ์›์ •๋ณด ๊ด€๋ฆฌ ๋“ฑ)
  • ํ”Œ๋ ˆ์ด๋ฆฌ์ŠคํŠธ ์ž‘์„ฑ, ์ˆ˜์ •, ์‚ญ์ œ ๊ธฐ๋Šฅ ๊ตฌํ˜„(์‚ฌ์ง„ ์—…๋กœ๋“œ ๋“ฑ)
  • ๋Œ“๊ธ€ ๋ฐ ๋ชจ์ฐฝ ์—…๋กœ๋“œ, ์ข‹์•„์š” ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • ์‚ฌ์šฉ์ž ์ทจํ–ฅ์— ๋งž๋Š” ์Œ์•… ์ถ”์ฒœ

ex_screenshot


5. API ์„ค๊ณ„

USER API

ex_screenshot

SONG API

ex_screenshot ex_screenshot

PLAYLIST API

ex_screenshot


6. ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

6.1. Email ์ „์†ก ์†๋„ ํ–ฅ์ƒ(๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์ ์šฉ)

์ƒ์„ธ์„ค๋ช…

  • ๋ฌธ์ œ: ๋น„๋ฐ€๋ฒˆํ˜ธ ์ฐพ๊ธฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ์ค‘ ์ด๋ฉ”์ผ ์ „์†ก ์†๋„ ๋Š๋ฆผ
๊ธฐ์กด ์ฝ”๋“œ
def send_email(message):
    email = EmailMessage(subject=message["email_subject"], body=message["email_body"], to=[message["to_email"]])
    email.send()
  • ํ•ด๊ฒฐ: ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์ ์šฉ ํ›„ ์ž‘์—…๊ฐ€์ค‘์น˜๋ฅผ ๋Š˜๋ ค ์‹คํ–‰ํ•˜์ง€ ์•Š๋Š” ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋ฅผ ํผ๋œจ๋ ค ์‚ฌ์šฉ์ž์—๊ฒŒ ์‘๋‹ตํ•˜๋Š” ๊ฒฝ๋กœ๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ์†๋„ ํ–ฅ์ƒ 2.5s -> 0.1ms
๊ฐœ์„ ๋œ ์ฝ”๋“œ
import threading
 
class EmailThread(threading.Thread):
    def __init__(self, email): 
        self.email = email 
        threading.Thread.__init__(self) 
        
    def run(self):
        self.email.send() 

def send_email(message):
    email = EmailMessage(subject=message["email_subject"], body=message["email_body"], to=[message["to_email"]])
    EmailThread(email).start()

6.2. Serializer Request

  • ๋ฌธ์ œ: ์š”์ฒญ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ serializers.py์— ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• ๋ชจ๋ฆ„
  • ํ•ด๊ฒฐ: serializer๋ฅผ ๊ฒ€์ฆํ•  ๋•Œ dict๋กœ request๋ฅผ ๋„˜๊ฒจ์ฃผ์–ด ํ•ด๊ฒฐ
์ฝ”๋“œ
#views.py
serializer = ChangePasswordSerializer(user, data=request.data, context={'request': request})

#serializers.py
current_password = self.context.get("request").user.password

6.3. serializer validate error

  • ๋ฌธ์ œ: drf ์œ ํšจ์„ฑ ๊ฒ€์ฆ ๋กœ์ง ๊ตฌํ˜„ ์•ˆ๋จ
  • ๋ฌธ์ œ์˜ ์›์ธ: drf์—์„œ ์ด๋ฏธ ์ œ๊ณตํ•˜๋Š” ์œ ํšจ์„ฑ ๊ฒ€์ฆ ๋กœ์ง์ด ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ํŒŒ์•…

๊ธฐ์กด ์ฝ”๋“œ
#serializers.py
nickname = date.get('nickname')
if nickname == '':
	raise serializers.ValidationError(detail={"nickname":"๋‹‰๋„ค์ž„์„ ์ž„๋ ฅํ•ด์ฃผ์„ธ์š”"})
  • ํ•ด๊ฒฐ: validate์ปค์Šคํ„ฐ๋งˆ์ด์ง• ์‹œ unique ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ์œผ๋ฉด error message๋ฅผ unique error์— ๋Œ€ํ•œ ์ •์˜ ํ•ด์คŒ, ๋นˆ๊ฐ’๊ณผ ํ•„๋“œ๊ฐ’์ด ๋น„์–ด์žˆ์œผ๋ฉด extra_kwargs๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์ • ๋ณ€๊ฒฝํ•จ(required์™€ blank์™€ invlid ์‚ฌ์šฉ)

๊ฐœ์„ ๋œ ์ฝ”๋“œ
#models.py
email = models.EmailField( max_length=255,unique=True, error_messages={'unique': "์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์ด๋ฉ”์ผ ์ฃผ์†Œ์ž…๋‹ˆ๋‹ค."})
nickname = models.CharField(max_length=15, unique=True, error_messages={'unique': "์ด๋ฏธ ์กด์žฌํ•˜๋Š” ๋‹‰๋„ค์ž„์ž…๋‹ˆ๋‹ค."})

#serializers.py
extra_kwargs= 
{'email': {'error_messages': {
'required': '์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.',
'invalid': '์•Œ๋งž์€ ํ˜•์‹์˜ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.',
'blank':'์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.',}},
  
'nickname': {
'error_messages': {
'required': '๋‹‰๋„ค์ž„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.',
'blank':'๋‹‰๋„ค์ž„์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”',}},}

7. ํŒ€์› ๊ฐˆ๋“ฑ

  • ๋ฌธ์ œ: ์ฃผ์ œ ์„ ์ •์— ๊ฐˆ๋“ฑ์ด ์žˆ์–ด ์‰ฝ๊ฒŒ ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ์ง€ ๋ชปํ•˜๋Š” ์ƒํ™ฉ
  • ํ•ด๊ฒฐ: ๊ธฐํš์„ค๋ช…๊ณผ ๋ฉœ๋ก  100์œ„ ํฌ๋กค๋ง ๋ฐ์ดํ„ฐ๋ฅผ ์ค€๋น„ํ•˜์—ฌ ์„ค๋“ํ•˜์—ฌ ๋‚ฉ๋“ ํ›„ ์ฃผ์ œ ๊ฒฐ์ •
  • ๊นจ๋‹ฌ์€ ์ : ์ถ”์ƒ์ ์ธ ์•„์ด๋””์–ด๋ฅผ ๋‚ด๋Š” ๊ฒƒ๋ณด๋‹ค ์ •ํ™•ํ•œ ๋ฐ์ดํ„ฐ์™€ ์„ค๋ช…์œผ๋กœ ์„ค๋“ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ 
ํฌ๋กค๋ง ์ฝ”๋“œ
from urllib.request import urlopen
import pandas as pd
import urllib.request
import urllib.parse
import time
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException

driver = webdriver.Chrome('C:/chromedriver_win32/chromedriver.exe') #ํฌ๋กฌ ๋“œ๋ผ์ด๋ฒ„ ์ ‘๊ทผ
driver.implicitly_wait(1)

url = 'https://www.melon.com/chart/age/index.htm?chartType=YE&chartGenre=KPOP&chartDate='
year = ['1990','1991','1992','1993','1994','1995','1996','1997','1998','1999', '2000', '2001','2002','2003','2004','2005','2006','2007','2008','2009','2010','2011','2012','2013','2014', '2015','2016','2017','2018','2019']

#์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์„ ๊ณณ
df = pd.DataFrame() 

#test
driver.get(url+year[0]) #์—ฐ๋„ ์„ ํƒ - ๋ฐ˜๋ณต๋ฌธ 


jenre = [] # ํฐ ๋ฐ˜๋ณต๋ฌธ ์•ˆ์—
lyrics = []
titles = []
year = []



for i in range(50):

    info_list = driver.find_elements_by_css_selector('#lst50 > td:nth-child(4) > div > a') #Top50 ๋ฆฌ์ŠคํŠธ #Top50 ๋ฆฌ์ŠคํŠธ
    info_list[i].click() #๊ณก์ •๋ณด ์„ ํƒ
    time.sleep(2)

    #๊ฐ€์‚ฌ ํŽผ์น˜๊ธฐ
    try:
        driver.find_element_by_css_selector('.button_more.arrow_d').click()
        time.sleep(2)
    except NoSuchElementException: #๊ฐ€์‚ฌ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ํŽผ์น˜๊ธฐ ์ˆ˜ํ–‰x
        pass
   


    #์žฅ๋ฅด, ๊ฐ€์‚ฌ, ๋…ธ๋ž˜ ์ œ๋ชฉ ํฌ๋กค๋ง
    titles.append(driver.find_element_by_css_selector('#downloadfrm > div > div > div.entry > div.info > div.song_name').text)
    jenre.append(driver.find_element_by_css_selector('#downloadfrm > div > div > div.entry > div.meta > dl > dd:nth-child(6)').text)
    lyrics.append(driver.find_element_by_css_selector('#lyricArea').text)
    year.append('1990')
    
    driver.back()
    time.sleep(2)

df = pd.DataFrame(zip(year, titles, jenre, lyrics), columns=['year','titles','jenre','lyrics'])


time.sleep(2)
driver.close()

df.to_csv('C:/Users/haeni_kim/Desktop/PROJECT/multi_project/melon_inform.csv',encoding = 'utf-8-sig')

8. ํšŒ๊ณ  / ๋Š๋‚€์  / ํ˜„ํ™ฉํŒ / ๊ทธ ์™ธ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ ํšŒ๊ณ  ๊ธ€: https://bolder-starburst-a73.notion.site/221108-9cab6c3034624797b2d3c3179e79c282


ํ”„๋กœ์ ํŠธ ํ˜„ํ™ฉํŒ / ๊ทธ ์™ธ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…: https://bolder-starburst-a73.notion.site/0ddbb2be0a474d35a4a957278980445b

music_recommend_be's People

Contributors

2jiyeong0 avatar jayjin avatar sajaehyukc avatar son950610 avatar woong-garden avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.