개발자 되는 중/개발 공부

스파르타 코딩 웹개발 개발일지 3주차 (복습)

SeonChoco 2022. 10. 12. 16:41

수업 목표

  1. 파이썬 기초 문법을 안다.
  2. 원하는 페이지를 크롤링 할 수 있다.
  3. pymongo를 통해 mongoDB를 제어할 수 있다.

01. 3주차 설치

파이썬 들어간다~

파이참이라는 프로그램이 파이썬이랑 같은 건줄 알았다ㅋㅋㅋㅋ

파이썬 프로그램 다운로드 한다.

Git Bash 다운로드 한다. (여기서 다운 받았던것을 잊어버리고 썼었다. 기본 프로그램인줄)

 

02. 연습 겸 복습 - 스파르타피디아에 OpenAPI 붙여보기

 

시작하자마자 로딩하는것

저번 수업에는 function() 안에 새로운 함수를 넣지 않고 그냥 그 안에 넣어버렸는데

이번에는 listing 함수 을 실행해라 라는 명령 따로

listing 함수 적는것 따로 해서 두개로 나누어 준다

눈에 보기 좋다

        $(document).ready(function(){
listing();
});

function listing() {
console.log('화면 로딩 후 잘 실행되었습니다');
}

숫자로 된 평점을 별로 바꿔주는 Javascipt

let star_image = '⭐'.repeat(star)

 

 

<!doctype html>
<html lang="en">

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
crossorigin="anonymous"></script>
    <link href="https://fonts.googleapis.com/css2?family=Gowun+Dodum&display=swap" rel="stylesheet">


<title>스파르타코딩클럽 | 부트스트랩 연습하기</title>
    <style>
        * {
            font-family: 'Gowun Dodum', sans-serif;
          }
        .mytitle {
            background-image: linear-gradient(0deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)) ,url("https://movie-phinf.pstatic.net/20210715_95/1626338192428gTnJl_JPEG/movie_image.jpg");
            background-size: cover;
            background-position: center;

            color: white;

            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;

            height: 250px;
            width: 100%;
        }
        .mytitle > button {
            width: 200px;
            height: 50px;
            background-color:transparent;
            color: white;
            border: 1px solid white;
            border-radius: 50px;
            margin-top: 10px;
        }
        .mytitle > button:hover {
            border:2px solid white;
        }
        .mycomment {
            color:grey;
        }
        .wrap{
            width: 95%;
            max-width: 1200px;
            margin: 20px auto 0px auto;
        }

        .mypost {
            max-width: 500px;
            width: 95%;
            margin:20px auto 0px auto;
            padding:20px;
            box-shadow: 0px 0px 3px 0px gray;

            display: none;

        }

        .mybtns {

            display: flex;
            flex-direction: row;
            justify-content: center;
            align-items: center;
            margin-top: 20px;
        }
        .mybtns> button {
            margin-right: 10px;
        }
          .mybucket > input {
            width: 70%;
        }
            .mybox > li {
            display: flex;
            flex-direction: row;
            align-items: center;
            justify-content: center;

            margin-bottom: 10px;
            min-height: 48px;
        }

    </style>
    <script>
        $(document).ready(function(){
listing();
});

function listing() {
     $.ajax({
            type: "GET",
            url: "http://spartacodingclub.shop/web/api/movie",
            data: {},
            success: function (response) {
                let rows = response['movies']
                for (let i = 0; i < rows.length; i++) {
                    let image = rows[i]['image']
                    let title = rows[i]['title']
                    let desc = rows[i]['desc']
                    let star = rows[i]['star']
                    let comment = rows[i]['comment']

                    let star_image = '⭐'.repeat(star)

                    let temp_html = `
                    <div class="col">
                    <div class="card">
                        <img src="${image}" class="card-img-top" alt="...">
                        <div class="card-body">
                            <h5 class="card-title">${title}</h5>
                            <p class="card-text">${desc}</p>
                            <p>${star_image}</p>
                            <p class="mycomment">${comment}</p>
                        </div>
                    </div>
                </div>
                    `
                    $('#cards-box').append(temp_html)
                }
            }
        })
}


        function hey() {
            $('#post-box').show()
        }

        function hey1() {
            $('#post-box').hide()
        }


    </script>
</head>

<body>
    <div class="mytitle">
        <h1>내 생애 최고의 영화들</h1>
        <button onclick="hey()">영화 기록하기</button>
    </div>

    <div class="mypost" id="post-box">

        <div class="form-floating mb-3">
            <input type="email" class="form-control" id="url" placeholder="name@example.com">
            <label for="url">영화URL</label>
        </div>


        <div class="input-group mb-3">
            <label class="input-group-text" for="inputGroupSelect01">별점</label>
            <select class="form-select" id="inputGroupSelect01">
                <option selected>--선택하기--</option>
                <option value="1">⭐</option>
                <option value="2">⭐⭐</option>
                <option value="3">⭐⭐⭐</option>
                <option value="4">⭐⭐⭐⭐</option>
                <option value="5">⭐⭐⭐⭐⭐</option>
            </select>
        </div>


        <div class="form-floating">
            <textarea class="form-control" placeholder="Leave a comment here" id="floatingTextarea2"
                      style="height: 100px"></textarea>
            <label for="floatingTextarea2">코멘트</label>
        </div>


        <div class="mybtns">
            <button type="button" class="btn btn-dark">기록하기</button>
            <button onclick="hey1()" type="button" class="btn btn-outline-dark">닫기</button>
        </div>



    </div>

    <div class="wrap">
            <div id="cards-box" class="row row-cols-1 row-cols-md-4 g-4">
               
            </div>
    </div>

</body>

</html>

 

03. 파이썬 시작하기

1) 파이썬을 설치한다는 것의 의미

일종의 번역팩을 설치한다고 생각하면 됩니다. 컴퓨터는 101010001 과 같은 언어만 알아듣는다고 했지요?

파이썬 문법으로 된 것을 101010001로 변환해줄 수 있도록, 번역 패키지를 설치하는 것입니다.

 

파일 → 새 프로젝트   위치(L) (파일 찾아서 선택)   중간에 있는 위치 (venv 잘 들어갔는지 확인) 기본 인터프리터(python 38 선택)   웰컴스크립트 생성 안하기   create    창 뜨면 이 창 선택함

 

venv 눈에 안 보이는 것 처럼 취급

 

phython 문법은 javascipt 보다 훨씬 직관적

 

04. 파이썬 기초공부

오른쪽 마우스 → 실행 클릭

1) 파이썬 기초 문법 (javascript랑 너무 비슷하다. 그래서 더 헷갈린다.)

변수 & 기본연산

a = 2
b = 3

print(a+b)

5

a = 'seonhyeong'
b = 'kim'

print(a+b)

seonhyeongkim

 

자료형

숫자, 문자 둘다 가능

 

리스트 형

a_list = ['사과', '배', '감']

print(a_list[2])

 

리스트에 추가하는거 javascript에서는 .push 였는데

phython에선 .append

a_list = ['사과', '배', '감']

a_list.append('수박')

print(a_list)

['사과', '배', '감', '수박']

 

딕셔너리 형

 

a_dict = {
    'name':'Seon', 'age':27
}

print(a_dict['name'])

Seon

 

함수

javascript는 function이지만  phython은 def를 쓴다

~이면은 콜론으로 나타내준다

return은 ~로 나를 변신시켜줘 하는것임

def sum(a,b):
    return a+b

result = sum(1,2)
print(result)

3

def sum(a,b):
    print('더하자')
    return a+b

result = sum(1,2)
print(result)

더하자
3

 

조건문

def is_adult(age):
    if age > 20:
        print('성인입니다')
    else:
        print('청소년입니다')

is_adult(25)

성인입니다

 

반복문 

이건 javascript와 꽤 다르다 javascript는 for(let i=0: i < rows.length; i++) 이게 반복문 만드는 법이었다.

fruits = ['사과','배','배','감','수박','귤','딸기','사과','배','수박']

for fruit in fruits:
    print(fruit)

이름은 뭐가되건 상관이 없다

fruits = ['사과','배','배','감','수박','귤','딸기','사과','배','수박']

for aaa in fruits:
    print(aaa)

사과



수박

딸기
사과

수박

 

javascript와 동일하게 조건 문에서 ~와 같다면 은 ==를 써준다

+= 더해준다

count 줄맞춤 제대로 안해줘서 오류가 났다

리스트 + 반복문 + 조건문

fruits = ['사과','배','배','감','수박','귤','딸기','사과','배','수박']

count = 0
for aaa in fruits:
    if aaa == '사과':
        count += 1

print(count)

2

 

리스트 안에 딕셔너리가 들어있다

리스트 + 딕셔너리 + 반복문 + 조건문

people = [{'name': 'bob', 'age': 20},
          {'name': 'carry', 'age': 38},
          {'name': 'john', 'age': 7},
          {'name': 'smith', 'age': 17},
          {'name': 'ben', 'age': 27}]

for person in people:
    if person['age'] > 20:
        print(person['name'])

carry
ben

 

05. 파이썬 패키지 설치하기

 

1) 파이썬 패키지(package) 설치하기

Python 에서 패키지는 모듈(일종의 기능들 묶음)을 모아 놓은 단위입니다.

이런 패키지 의 묶음을 라이브러리 라고 볼 수 있습니다.

지금 여기서는 외부 라이브러리를 사용하기 위해서 패키지를 설치합니다.

즉, 여기서는 패키지 설치 = 외부 라이브러리 설치!

 

1. 가상 환경(virtual environment) 이란? - 프로젝트별로 패키지들을 담을 공구함 

   이게 바로 venv다

2. pip(python install package) 사용 - requests 패키지 설치해보기

파일 → 설정 → 프로젝트: 프로젝트 명 → python 인터프리터 → + → 돋보기에서 검색 → 패키지 설치

 

06. 패키지 사용해보기

request(ajax와 비슷한 역할한다 자료를 가져와서 쓰게 해주는 역할)

처음에 이런걸 갖다 붙인다 ajax 쓸때 링크를 가져와서 붙여줘야하는 것 처럼

그리고 api  주소 붙이는 곳도 있다. ajax랑 유사 

라이브러리를 종류마다 사용법이 다 달라서 그때 그때 블로그 같은데에서 찾아봐야한다

import requests # requests 라이브러리 설치 필요

r = requests.get('http://spartacodingclub.shop/sparta_api/seoulair')
rjson = r.json()
print(rjson)

{'RealtimeCityAir': {'row': [{'ARPLT_MAIN': 'O3', 'CO': 0.4, 'IDEX_MVL': 31, 'IDEX_NM': '좋음', 'MSRDT': '201912052100', 'MSRRGN_NM': '도심권', 'MSRSTE_NM': '중구', 'NO ..............계속

 

리스트에 들어있는 딕셔너리 자료를 반복문으로 다 꺼내주고 조건문을 해서 해당되는 것만 꺼내주었다. 

rows = rjson['RealtimeCityAir']['row']
for row in rows:
     gu_mise = row['IDEX_MVL']
     gu_name = row['MSRSTE_NM']
     if gu_mise < 35:
         print(gu_name, gu_mise)

중구 31
용산구 -99
광진구 31
성동구 33
중랑구 34
동대문구 34
양천구 -99


07. 웹스크래핑(크롤링) 기초

패키지 추가 설치하기(beautifulsoup4)

크롤링 하게 해주는 패키지 bs4

기본 세팅

import requests
from bs4 import BeautifulSoup

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/rmovie.naver?sel=pnt&date=20210829',headers=headers)

soup = BeautifulSoup(data.text, 'html.parser')

 

bs4 쓰는 법

원하는 곳에 오른쪽 클릭 → 검사 → 해당 줄에 오른 쪽 클릭 복사   selector 복사 

#old_content > table > tbody > tr:nth-child(2) > td.title > div > a

이렇게 생긴애가 복사된다.

 

soup. select_one() 하고 괄호 안에 selector를 넣을 때 작은 따옴표 안 넣었다가 오류났었다.

title = soup.select_one('#old_content > table > tbody > tr:nth-child(2) > td.title > div > a')
print(title)

결과 <a href="/movie/bi/mi/basic.naver?code=186114" title="밥정">밥정</a>

 

문자만 나온다. 

print(title.text)

밥정

print(title['href'])

/movie/bi/mi/basic.naver?code=186114

print(title['title'])

밥정

 

제목 두개에서 selector를 복사해 온다.

#old_content > table > tbody > tr:nth-child(3) > td.title > div > a
#old_content > table > tbody > tr:nth-child(4) > td.title > div > a

tr까지 같다.

 

movies = soup.select('#old_content > table > tbody > tr')

for movie in movies:
    a = movie.select_one('td.title > div > a')
    print(a)

movies와 반복문을 돌린 movie 와는 차이가 없다. 

select_one 한 a를 구하기 위해 반복문을 미리 만들어 놓은 것 같다. 

 

None
<a href="/movie/bi/mi/basic.naver?code=186114" title="밥정">밥정</a>
<a href="/movie/bi/mi/basic.naver?code=171539" title="그린 북">그린 북</a>
<a href="/movie/bi/mi/basic.naver?code=174830" title="가버나움">가버나움</a>
<a href="/movie/bi/mi/basic.naver?code=192613" title="디지몬 어드벤처 라스트 에볼루션 : 인연">디지몬 어드벤처 라스트 에볼루션 : 인연</a>
<a href="/movie/bi/mi/basic.naver?code=151196" title="원더">원더</a>
<a href="/movie/bi/mi/basic.naver?code=144906" title="베일리 어게인">베일리 어게인</a>
<a href="/movie/bi/mi/basic.naver?code=175092" title="먼 훗날 우리">먼 훗날 우리</a>
<a href="/movie/bi/mi/basic.naver?code=169240" title="아일라">아일라</a>
<a href="/movie/bi/mi/basic.naver?code=157243" title="당갈">당갈</a>
<a href="/movie/bi/mi/basic.naver?code=196843" title="극장판 바이올렛 에버가든">극장판 바이올렛 에버가든</a>
None

결과는 None 이 섞인 영화 제목들이다

 

None을 없애는 두가지 방법 != 와 is not

if a != None:
    print(a)
if a is not None:
    print(a)

08. Quiz_웹스크래핑(크롤링) 연습

    1. 웹스크래핑 더 해보기 (순위, 제목, 별점)
#old_content > table > tbody > tr:nth-child(3) > td.title > div > a
#old_content > table > tbody > tr:nth-child(4) > td.title > div > a

#old_content > table > tbody > tr:nth-child(2) > td:nth-child(1) > img
#old_content > table > tbody > tr:nth-child(3) > td:nth-child(1) > img

#old_content > table > tbody > tr:nth-child(2) > td.point
#old_content > table > tbody > tr:nth-child(3) > td.point

movies = soup.select('#old_content > table > tbody > tr')

for movie in movies:
    a = movie.select_one('td.title > div > a')
    b = movie.select_one('td:nth-child(1) > img')
    c = movie.select_one('td.point')
    if a is not None:
        print(b['alt'], a.text,c.text)

 

순위와 평점 제목에서 각각 selector를 복사해서 붙여놓고

앞쪽에 반복되는 부분을 movies로 만들고

nth-child는 반복하면서 선택해주는 부분이니까 빼고 

뒤에 부분을 붙여넣어서 각각 지칭을 해준다

print할 때 ['alt']나 .text를 넣어서 필요한 정보만 가져온다. 

if a is not None:
    title = a.text
    rank = b['alt']
    star = c.text
    print(rank, title, star)

if 아래에서 상세 설정해주고 새로 이름 지어주고 프린트

a = movie.select_one('td.title > div > a')
if a is not None:
    title = a.text
    rank = movie.select_one('td:nth-child(1) > img')['alt']
    star = movie.select_one('td.point').text
    print(rank, title, star)

a만 만들어주고 title로 바꾸고 rank와 star은 바로 만들었다. 

결과

01 밥정 9.64
02 그린 북 9.59
03 가버나움 9.59
04 디지몬 어드벤처 라스트 에볼루션 : 인연 9.53
05 원더 9.52
06 베일리 어게인 9.52
07 먼 훗날 우리 9.52

09. DB개괄

1) 들어가기 전에 - DB는 왜 쓰는 것일까?

잘 찾아서 쓰려고

출판사, 장르, 제목 이런식으로  꽃힌 규칙같은 걸 Index라고 한다

 

2) 들어가기 전에 - DB의 두 가지 종류

SQL vs No-SQL

 

RDBMS(SQL):

행/열의 생김새가 정해진 엑셀에 데이터를 저장하는 것과 유사합니다.

데이터 50만 개가 적재된 상태에서, 갑자기 중간에 열을 하나 더하기는 어려울 것입니다.

그러나, 정형화되어 있는 만큼, 데이터의 일관성이나 / 분석에 용이할 수 있습니다.

ex) MS-SQL, My-SQL 등

 

No-SQL:

딕셔너리 형태로 데이터를 저장해두는 DB입니다.

고로 데이터 하나 하나 마다 같은 값들을 가질 필요가 없게 됩니다.

자유로운 형태의 데이터 적재에 유리한 대신, 일관성이 부족할 수 있습니다.

ex) MongoDB

 

3) 들어가기 전에 - DB의 실체에 관하여

우리가 쓰는 프로그램과 같은 것이랍니다.

즉, 내 컴퓨터에 게임도 설치하고, PPT도 설치하고, DB도 설치할 수 있는 것이죠.

요새는 Cloud 형태로 제공해주는 곳들이 많답니다.요새 트렌드임

유저가 몰리거나 / DB를 백업해야 하거나 / 모니터링 하기가 아주 용이하기 때문이죠!

우리도 DB 클라우드인 mongo DB Atlas 이용할 것이다.

 

10. mongoDB 시작하기

 

11. mongoDB 연결하기

pymongo , dnspython 패키지 다운로드

from pymongo import MongoClient
client = MongoClient('여기에 URL 입력')
db = client.dbsparta

 

url  자리에 connect 창에서 가져온 주소를 넣어준다.

doc = {'name':'bobby','age':21}
db.users.insert_one(doc)

자료 하나 넣으면 연결 끝

 

12. pymongo로 DB조작하기

들어간 자료 확인하려면 browse collections에 들어가서 보면 된다. 

여기까지 정리 다 해놨었는데 날라갔다. 빡친다

 

# 저장 - 예시
doc = {'name':'bobby','age':21}
db.users.insert_one(doc)

# 한 개 찾기 - 예시
user = db.users.find_one({'name':'bobby'})

# 여러개 찾기 - 예시 ( _id 값은 제외하고 출력)
all_users = list(db.users.find({},{'_id':False}))

# 바꾸기 - 예시
db.users.update_one({'name':'bobby'},{'$set':{'age':19}})

# 지우기 - 예시
db.users.delete_one({'name':'bobby'})

id 없애고 싶을 때 False를 쓰는대 첫글자가 꼭 대문자여야 한다. 

 

13. 웹스크래핑 결과 저장하기

import requests
from bs4 import BeautifulSoup

from pymongo import MongoClient
client = MongoClient('mongodb+srv://test:sparta@cluster0.nban6ul.mongodb.net/?retryWrites=true&w=majority')
db = client.dbsparta


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/rmovie.naver?sel=pnt&date=20210829',headers=headers)

soup = BeautifulSoup(data.text, 'html.parser')


movies = soup.select('#old_content > table > tbody > tr')

for movie in movies:
    a = movie.select_one('td.title > div > a')
    if a is not None:
        title = a.text
        rank = movie.select_one('td:nth-child(1) > img')['alt']
        star = movie.select_one('td.point').text
        doc = {
            'title':title,
            'rank':rank,
            'star':star
        }
        db.movies.insert_one(doc)

맨 위에 pymongo 패키지를 쓸거라는 내용을 복사 붙여넣기 해준다 .

doc에 딕셔너리 형태의 데이터를 만들어주는데

이때 내가 만들어놨던 자료들에는 따로 작은 따옴표를 붙이지 않고 그대로 써주었다. 

db.movies.insert_one()는 자료들을  movies라는 폴더를 새로 만들면서 그 안에 넣어준다. 

db = client.dbsparta 이것은 폴더가 들어가는 큰 폴더를 dbsparta라는 이름으로 만들어준다.

 

14. Quiz_웹스크래핑 결과 이용하기

1) find, update 연습하기 (delete는 연습 안할게요!)

(1) 영화제목 '가버나움'의 평점을 가져오기

user = db.movies.find_one({'title':'가버나움'})
print(user['star'])

 

9.59

(2) '가버나움'의 평점과 같은 평점의 영화 제목들을 가져오기

내가 쓴 답

user = db.movies.find_one({'title':'가버나움'})
user1 = db.movies.find_one({'star':user['star']})
print(user1['title'])

내가 처음 쓴 코드처럼  같은 평점인 것을 찾을 때 find_one을 써주면 하나만 찾아준다

그린 북

 

target_movie = db.movies.find_one({'title':'가버나움'})
target_star = target_movie['star']

movies = list(db.movies.find({'star':target_star}))

for movie in movies:
    print(movie['title'])

정답처럽 list를 만들어서 반복문으로 돌려주면

해당하는 모든게 list 형태로 나온다.

그린 북
가버나움

 

(3) '가버나움' 영화의 평점을 0으로 만들기

여기서  폴더이름을 고대로 users라고 해서 안 되다가 깨닫고 movies로 바꿔주었다.  

db.movies.update_one({'title':'가버나움'},{'$set':{'star':'0'}})

star이랑 연결된 숫자는 문자로 생각해서 작은 따옴표를 붙여야함 

 

15. 3주차 끝 & 숙제 설명

지니뮤직의 1~50위 곡을 스크래핑 해보세요.

1) 앞에서 두 글자만 끊기! text[0:2] 를 써보세요!

2) 순위와 곡제목이 깔끔하게 나오지 않을 거예요. 옆에 여백이 있다던가, 다른 글씨도 나온다던가.. 파이썬 내장 함수인  strip()을 잘 연구해보세

for music in musics:
    rank = music.select_one('td.number').text[0:2].strip()
    title = music.select_one('td.info > a.title.ellipsis').text.strip()
    artist = music.select_one('td.info > a.artist.ellipsis').text
    print(rank,title,artist)
1 바라만 본다 MSG워너비 (M.O.M)
2 Next Level aespa
3 신호등 이무진
4 Weekend 태연 (TAEYEON)
5 치맛바람 (Chi Mat Ba Ram) 브레이브걸스 (Brave girls)
6 Butter 방탄소년단
7 나를 아는 사람 MSG워너비 (정상동기)
8 Permission to Dance 방탄소년단
9 비 오는 날 듣기 좋은 노래 (Feat. Colde) 에픽하이 (EPIK HIGH)

mongoDB에 넣어주기

for music in musics:
    rank = music.select_one('td.number').text[0:2].strip()
    title = music.select_one('td.info > a.title.ellipsis').text.strip()
    artist = music.select_one('td.info > a.artist.ellipsis').text
    print(rank,title,artist)
    doc = {'rank': rank, 'title': title, 'artist': artist}
    db.musics.insert_one(doc)

 

다음시간에 배울 것

1,2주차에는 눈에 보이는 html, css, Javascript를 배웠다

3주차에는 눈에 보이는 것을 주는 것은 서버인데 이걸 만들 수 있는 언어 파이썬을 배웠다.

4.5 주차는 두개 다 같이 쓰는 것을 할 거다.