본문 바로가기
항해99/사전 스터디

[항해99] 사전스터디 - 3주차 강의회고록

by junvely 2023. 2. 13.

🦄 사전 스터디 3주차 강의회고록

3일차, 오늘의 목표는 3주차 완강이다!

그동안 그토록 궁금해 하고 배우고 싶었던 파이썬과, 크롤링, DB 등 백엔드의 핵심 기능을 배울 수 있는 기회다!

반드시 완강해서 모두 습득하도록 하자😆


✨02/13 : 목표 : 사전스터디 3주차 완강

 

📒강의 노트 정리

01 오늘 배울 내용 & 설치

- 오늘 배울 것 : Python(서버), 크롤링(데이터 크롤링), mongoDB(데이터베이스)

- 문법 연습 후, 라이브러리 활용하여 네이버 영화목록 쫙 가져오기

- 파이썬 설치 => 3.8 체크

https://www.python.org/ftp/python/3.8.6/python-3.8.6-amd64.exe

- 윈도우일 경우 Git bash 설치

https://git-scm.com/

 

02 스파르타 피디아에 OpenAPI 붙여보기

- 지난 실습 API로 영화 리스트 만들기

http://spartacodingclub.shop/web/api/movie

- ✨별점 반복해서 찍어내기 => "문자열".repeat(횟수)

let star_image = "⭐".repeat(star);

 

 

03 파이썬 시작하기

1. 파일 생성

- hello.py

2. 확장프로그램 다운

  • 일종의 번역팩을 설치하는 것
  • 파이썬 문법으로 된 것을 컴퓨터가 알아들을 수 있는 101001로 변환해줄 수 있도록, 번역 패키지를 설치하는 것

3. git bash 터미널 

  • 터미널이 뭔가요?
    • 사용자가 텍스트로 명령어를 입력하면, 결과를 텍스트로 화면에 출력해주는 도구
  • Q. 터미널은 어디에 사용하나요?
    • 파이썬 라이브러리를 설치하고, 파이썬 프로젝트를 실행하는데 사용
  • Q. 왜 사용하나요?
    • 명령어를 적어 작동시키는 것이 빠르고 편리하기 때문
    • 요새는 GUI(눈에 보이는 아이콘으로 상호작용하는 방식)이 잘 되어 있어 사용하는 경우가 줄어들고 있지만, 코딩할 때는 명령어를 입력하는 방식을 자주 보게 될 것

 

  •  Ctrl + `(백틱) : 터미널 단축키

- configure terminal setting에서 git bash 기본설정으로 바꿈

print('hello world')

입력 후 마우스 우클릭 '파이썬에서 터미널 실행'  => 단축키 F5, Ctrl+F5 = >터미널에 뜸

rksk7@DESKTOP-1QH9FU9 MINGW64 ~/OneDrive/바탕 화면/sparta (main)
$ C:/Users/rksk7/AppData/Local/Programs/Python/Python38/python.exe "c:/Users/rksk7/OneDrive/바탕 화면/sparta/python/hello.py"
hello world

 

 

04 파이썬 기본문법

1. 변수, 자료형

- 변수타입 생략, 바로 입력

a = 3      # 3을 a에 넣는다
b = a      # a를 b에 넣는다
a = a + 1  # a+1을 다시 a에 넣는다

num1 = a*b # a*b의 값을 num1이라는 변수에 넣는다
num2 = 99 # 99의 값을 num2이라는 변수에 넣는다

3. 함수 

- 변수타입 생략, def 함수명() : 로 선언

def hey(): #함수선언
    print('헤이!')
 
hey() #터미널 헤이!출력
# 리턴문
def sum(a,b,c):
    return a+b+c

result = sum(1,2,3)

print(sum(1,2,3)) // 6
print(result) // 6

 

 

05 파이썬 반복문 조건문

1. 조건문

age =15

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

 

2. 반복문

fruits = ['사과','배','감','귤']

for fruit in fruits:
	print(fruit)

# 사과, 배, 감, 귤 하나씩 찍힘

반복문 + 조건문

ages=[5,10,13,23,25,9]

for a in ages :
    if a > 20 :
        print('성인입니다')
    else:
        print('청소년입니다')

 

 

06 파이썬 패키지 시작하기

1. 가상환경 venv 설치

가상환경(virtual environment)은
같은 시스템에서 실행되는 다른 파이썬 응용 프로그램들의 동작에 영향을 주지 않기 위해, 
파이썬 배포 패키지들을 설치하거나 업그레이드하는 것을 가능하게 하는 격리된 실행 환경

프로젝트 별로 여러가지 라이브러리를 모아놓는 패키지 폴더라고 보면 된다.

 

1) 파이썬 폴더 경로 확인

rksk7@DESKTOP-1QH9FU9 MINGW64 ~/OneDrive/바탕 화면/sparta/python (main)

2) 파이썬 인터프리터 버전 확인 => 3.8.6~ (글로벌)

3) 가상환경 venv 설치 (git bash에서 설치해야 함)

$ python -m venv venv

4) 가상환경 venv 활성화

- 파이썬 인터프리터 변경 => 3.8 venv'venv' 클릭 후 새 터미널 열기

$ source "c:/Users/rksk7/OneDrive/바탕 화면/sparta/python/venv/Scripts/activate"
(venv) // 경로에 (venv)가 붙음

- 앞으로 라이브러리를 venv에서 설치하고 가져다 쓰겠다는 뜻

 

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

$ pip insall requests

 

 

07 패키지(라이브러리) 사용해보기

1. Requests 라이브러리 사용해보기 + List/Dictionary/함수/If/For문 연습

- Requests = Fetch를 사용해 서버에 데이터를 요청하는 것과 같은 역할

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

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

rows = rjson['RealtimeCityAir']['row']

for a in rows :
    gu_name = a['MSRSTE_NM']
    gu_mise = a['IDEX_MVL']
    print(gu_name,gu_mise)

 

지금까지 정리 (파이썬 설치)

파이썬 설치 - 확장프로그램 설치 - 파일생성 - 가상환경 venv 설치 - venv 활성화 - 새 터미널 열기 - pip로 requests 설치 - 작업(F5)

 

 

✨08 웹스크래핑(크롤링) 기초

- 네이버 영화 페이지 크롤링하기

https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&date=20210829

- 우선 가상환경(venv)인지 확인 => 새 터미널 (venv) , 인터프리터 확인

$ source "c:/Users/rksk7/OneDrive/바탕 화면/sparta/python/venv/Scripts/activate"
(venv)

 

1. 라이브러리 설치(beautifulsoup4) - 웹에 접속=(requests), 데이터를 솎아냄=(beautifulsoup)

pip install bs4

2. 크롤링 기본 셋팅(기본 포맷)

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)
 
 # html을 가져옴
soup = BeautifulSoup(data.text, 'html.parser')
print(soup)

print 결과 => html을 가져옴

 

3. 영화 페이지에서 원하는 요소 검사 하여 copy select하기

# tr을 카피한 결과 > 반복됨
#old_content > table > tbody > tr:nth-child(2)
#old_content > table > tbody > tr:nth-child(3)
# tr 안의 제목
#old_content > table > tbody > tr:nth-child(3) > td.title > div > a

trs = soup.select('#old_content > table > tbody > tr')
for tr in trs:
    a = tr.select_one('td.title > div > a')
    print(a) # 제목들만 솎아 나옴

그 중 None이란 데이터가 있음 => tr에서 a를 찾는데, 없을 경우 None이 나옴 => 걸러주기

trs = soup.select('#old_content > table > tbody > tr')
for tr in trs:
    a=tr.select_one('td.title > div > a')
    if a is not None : # a가 None이 아니면
        print(a.text) # a.text를 출력

None이 아닌 제목들만 출력 됨

 

4. 순위와 별점도 출력해 보기

trs = soup.select('#old_content > table > tbody > tr')
for tr in trs:
    a = tr.select_one('td.title > div > a')
    if a is not None : # a가 None이 아니면
        title = a.text
        rank = tr.select_one('td:nth-child(1) > img')['alt']
        star = tr.select_one('td.point').text

        print(rank, title, star)

이와같이 다른 언어에서는 웹을 크롤링하기가 쉽지 않지만, 파이썬은 라이브러리가 굉장히 잘 만들어져 있어 웹을 크롤링하기 좋다.

- 코드 전체보기

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')

trs = soup.select('#old_content > table > tbody > tr')
for tr in trs:
    a = tr.select_one('td.title > div > a')
    if a is not None : # a가 None이 아니면
        title = a.text
        rank = tr.select_one('td:nth-child(1) > img')['alt']
        star = tr.select_one('td.point').text

        print(rank, title, star)

 

+자바스크립트 객체 접근에서 유효한 문자열은 무엇이 있을까?

 

10 DB 개괄

- DB를 쓰는 이유 : 데이터를 잘 쌓고 잘 찾아서 가져오기 위해 사용

- DB의 종류에는 두가지가 있다.

 

1. RDBMS(SQL) - 엑셀형 - MY SQL 

- 장점 : 사람이 실수할 일이 적다. 데이터가 안들어오면 알려줌 => 정해진 틀, 데이터 변화가 잘 없을경우, 좀 더 빠르게 가져옴, 대기업

행/열의 생김새가 정해진 엑셀에 데이터를 저장하는 것과 유사합니다. 데이터 50만 개가 적재된 상태에서, 갑자기 중간에 열을 하나 더하기는 어려울 것입니다. 그러나, 정형화되어 있는 만큼, 데이터의 일관성이나 / 분석에 용이할 수 있습니다. ex) MS-SQL, My-SQL 등

2. No-SQL(Not Only SQL) - 자유형 - MongoDB

- 장점 : 데이터가 언제 어떻게 변경될지 모름,  정해진 틀이 부적합 할 경우, 스타트업(보통 NO-SQL에서 틀이 잡히면 MY-SQL로 넘어가는 경우가 많다)

딕셔너리 형태로 데이터를 저장해두는 DB입니다. 고로 데이터 하나 하나 마다 같은 값들을 가질 필요가 없게 됩니다. 자유로운 형태의 데이터 적재에 유리한 대신, 일관성이 부족할 수 있습니다. ex) MongoDB

 

- 최근 트렌드는 직접 내 컴퓨터에서 DB를 사용하지 않고, 인터넷 클라우드 환경의 DB를 빌려서 많이 사용한다.

=> 최신 클라우드 서비스인 mongoDB Atlas를 사용해 볼 것

 

11 MongoDB 시작하기

1. MongoDB-Atlas 가입 => username, password create => add entry 

접속 준비 완료

 

 

12 mongoDB 연결하기

1. Python에서 MongoDB 조작하려면 라이브러리 dnspython, pymongo가 필요

$ pip install dnspython
$ pip install pymongo

2. 파일 생성

- pymongo 기본 코드

from pymongo import MongoClient
client = MongoClient('여기에 URL 입력') # mongoDB 주소 사이트에서 가져오기
db = client.dbsparta

 

3.  MongoDB 주소 가져오기

4. URL에 복사한 mongoDB주소 입력

from pymongo import MongoClient
client = MongoClient('mongodb+srv://junvely:<password>@cluster0.38f4se1.mongodb.net/?retryWrites=true&w=majority')
db = client.dbsparta

<password>에 설정했던 user 비밀번호 입력

- 여기까지가 라이브러리를 불러온 것

 

5.  mongoDB에 데이터 넣기 => 객체를 넣어주면 됨

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

# DB에 데이터 넣기
doc = {
    'name' : '영수',
    'age' : 24,
}
db.users.insert_one(doc)

- mongoDB => Browser Collections 클릭

- users 콜렉션 안에 데이터가 들어가 있는 것을 확인할 수 있음

 

13 pymongo로 DB조작하기

1. DB에 데이터 넣기 - insert_one()

# 'users'라는 collection에 {'name':'bobby','age':21}를 넣습니다.
db.users.insert_one({'name':'영희','age':30})
db.users.insert_one({'name':'철수','age':20})
db.users.insert_one({'name':'john','age':30})

2. DB에서 데이터 가져오기 - .find() / .find_one()

all_users = list(db.users.find({},{'_id':False})) #({}는 조건, {'_id':False})는 id 정보는 안보겠다는 뜻

print(all_users[0])         # 0번째 결과값을 보기
print(all_users[0]['name']) # 0번째 결과값의 'name'을 보기

for a in all_users:      # 반복문을 돌며 모든 결과값을 보기
    print(a)
    
#{'name': '영수', 'age': 24}
#{'name': '영희', 'age': 30}
#{'name': '철수', 'age': 20}

- 유저 정보 하나만 가져오기

user = db.users.find_one({})
print(user)

#{'_id': ObjectId('63e9de706e01bad448746613'), 'name': '영수', 'age': 24}

3. DB 정보 수정하기 - .update_one({찾을 데이터}, {'$set' : {변경할 데이터}})

db.users.update_one({'name':'영수'},{'$set':{'age':19}})

user = db.users.find_one({'name':'영수'})
print(user)
# {'name': '영수', 'age': 19}

4. DB 정보 삭제하기 - .delete_one() > 거의 안 씀

db.users.delete_one({'name':'영수'}) # 영수 데이터 삭제됨

 

5. 요약

# 저장 - 예시
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'})

 

 

14 웹 스크래핑 결과 저장하기

1. 웹 스크래핑 했던 결과 DB에 저장하기

import requests
from bs4 import BeautifulSoup
from pymongo import MongoClient
client = MongoClient('mongodb+srv://junvely:test@cluster0.38f4se1.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')

trs = soup.select('#old_content > table > tbody > tr')
for tr in trs:
    a = tr.select_one('td.title > div > a')
    if a is not None : # a가 None이 아니면
        title = a.text
        rank = tr.select_one('td:nth-child(1) > img')['alt']
        star = tr.select_one('td.point').text
        doc = {
            'title':title,
            'rank':rank,
            'star' : star,
        }
        # 주의! 라인을 따라 입력해야 if 안에 있는 내용이 된다.
        # 여러 번 실행하면 여러번 들어감
        db.movies.insert_one(doc)

 

15 QUIZ 웹 스크래핑 결과 이용하기

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

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

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

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

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

# 리스트기 때문에 for문으로 출력
for a in movies: 
    print(a['title'])

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

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

 

 

16 숙제 : 지니 뮤직의 1위~50위 스크래핑

- 지니뮤직 사이트 : 순위 / 곡 제목 / 가수를 스크래핑

https://www.genie.co.kr/chart/top200?ditc=M&rtm=N&ymd=20210701

 

+ 힌트

0) 출력 할 때는 print(rank, title, artist) 하면 됩니다!

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

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

 

알게된 점

1. text[0:2] => 텍스트 중 0~2까지만 출력해 준다.

2. 파이썬 공백 제거 => 양쪽공백(.strip()), 왼쪽공백(.Istrip), 오른쪽공백(.rstrip)

3.❗.text나 속성등으로 크롤링 했는데, 'NoneType'일 경우, 대부분 html까지는 불러오는데 성공하지만

     불러온 html이 None이라 html.text나 속성값을 불러올 수 없는 경우가 많다.

     이때는 위에서 .text나 속성등을 빼고 우선 html만 불러온 후,

     if a is not None : 조건문으로 None을 한 번 걸러주고 a.text을 출력하면 불러올 수 있다.

for tr in trs :
    title = tr.select_one('td.title > div > a') #.text 생략 후
    if title is not None : # None 걸러주고
        text = title.text # 다시 출력

+ 답안(DB까지 생성했음)

import requests
from bs4 import BeautifulSoup
from pymongo import MongoClient
client = MongoClient('mongodb+srv://junvely:test@cluster0.38f4se1.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://www.genie.co.kr/chart/top200?ditc=M&rtm=N&ymd=20210701',headers=headers)

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

trs = soup.select('#body-content > div.newest-list > div > table > tbody > tr')
for tr in trs :
    rank = tr.select_one('td.number').text[0:2].strip()
    title = tr.select_one('td.info > a.title.ellipsis').text.strip()
    singer = tr.select_one('td.info > a.artist.ellipsis').text.strip()
    print(rank,title,singer)
    doc={
        'rank' : rank,
        'title' : title,
        'singer' : singer,
    }
    db.musics.insert_one(doc)
music = list(db.musics.find({"singer":"아이유 (IU)"},{'_id':False}))
print(music)

 

 

✅ 느낀점

3일차, 오늘도 3주차 완강에 성공했다! 🙌

Python이나 DB 등 서버쪽이 궁금하고 너무 배우고 싶다가도, 백엔드쪽 언어는 왠지 모르게 굉장히 복잡하고 어려울 것 같다는 두려움이 있어 한 번도 도전해 보지 못했었는데 이번 강의에서 생각보다 너무 쉽게 배울 수 있어서 굉장히 흥미롭고 재밌었다.

말로만 들었지 한 번도 접해보지 못했던 Python으로 내가 크롤링을 하고 원하는 정보를 받아와 DB까지 연결해 데이터를 넣는게 가능하다는 것이 나에겐 너무나 신기한 경험이었다. 오히려 알고있던 자바스크립트 보다도 훨씬 흥미롭고 재미를 느껴 백엔드 쪽은 이렇게 데이터를 가공하는데에 굉장히 큰 묘미가 있다는 것을 새삼 깨달았다.

또 프론트를 공부하며 항상 데이터는 어떻게 크롤링 되고, 어떻게 가공되어 DB에 들어가게 되는가에 대한 막연한 궁금증이 있었는데 너무나 쉽게 라이브러리로 가능했다는 것이 놀라웠다... 물론 데이터를 가공하는데는 상당히 복잡한 과정이 필요하겠지만 지금의 나로는 이정도 만으로도 굉장히 만족스럽고 흥미로운 경험이었다. 이번 계기로 Python이나 서버 쪽 공부에도 관심이 생겼고 여유가 된다면 풀스택 프로젝트도 많이 만들어 보고 싶다!!😆

 

✖️보완할 점, 아쉬운 점 

데이터 크롤링에서 계속해서 'NoneType' object has no attribute 'text'이 나올 때마다 너무 멘붕이 왔다...😢 

어디서부터 어떻게 잘못된 것인지 감이 안와서 계속 반복해서 'NoneType'을 경험했는데, 계속되는 시도 끝에 결국 html이 None이기 때문에 그 안의 .text나 속성 들을 가져올 수 없다는 것을 알 수 있었다.

앞으로는 당황하지 않고, 이 점을 꼭 기억하고 if a is not None 으로 None을 반드시 걸러주도록 해야겠다!

실습 외 여러 사이트에서도 수시로 크롤링 하는 연습을 반복해 까먹지 않도록 하자!😆