본문 바로가기
들은 강의

[웹개발 입문 강의] [Python] mongoDB, pymongo, Crawling

by hotdog7778 2023. 6. 8.

스파르타 코딩클럽 웹개발 종합반 인강 - 공부 기록

 

수강 시작 ~ 

2023. 06. 06 ~ 

 

https://github.com/hotdog7778/sparta

 


데이터 베이스

데이터베이스 : 데이터를 잘 쌓고 잘 가져올 수 있게 하는 프로그램

1. DB 개괄

  • SQL :
    • RDBMS
    • 이미 정해진 틀에 데이터를 넣는다.
    • 장점 : 사람의 실수를 줄일 수 있다.
  • NoSQL :
    • Not Only SQL
    • 정해진 틀이 없어 자유도가 높다. ex) 사람1은 나이,이름 / 사람2는 나이,키,전화번호
    • 장점 : 비즈니스의 유연성

 

2. mongoDB 시작하기

무료 클라우드 몽고DB 사용

https://account.mongodb.com/account/register

웹에서 데이터베이스 생성, 유저 생성, 퍼블릭 접근 허용까지 완료 했다.

 

3. 내컴퓨터 — 몽고DB 연결하기

두개의 라이브러리가 필요합니다.

  • pymongo
  • dnspyton
pip install pymongo
pip install dnspython

mongodb Atlas에서 connect URL을 찾는다.

pymongo 라이브러리를 이용해서 파이썬으로 몽고DB에 connect 한다.

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

doc = {
    'name':'영수',
    'age':24
}

db.users.insert_one(doc)

저 코드를 네번 실행했더니 DB로 데이터가 네번 들어갔다.

영수영수영수영수

 

4. pymongo로 DB조작하기

find & insert & update & delete

# pymongo 라이브러리로 몽고DB에 붙는 방법
from pymongo import MongoClient
client = MongoClient('mongodb+srv://<user>:<pass>@cluster0.zlnt7r2.mongodb.net/?retryWrites=true&w=majority')
db = client.dbsparta

# 데이터를 insert 하자.
doc = {
    'name':'영희',
    'age':30
}
db.users.insert_one(doc)

# 데이터를 전부 가져오자
all_users = list(db.users.find({},{'_id':False}))
for a in all_users:
    print(a)

# 데이터를 하나만 가져오자
user = db.users.find_one({})
user = db.users.find_one({},{'_id':False})
print(user)

# 데이터를 수정 해보자
db.users.update_one({'name':'영수'},{'$set':{'age':19}}) # 영수의 age를 19로 바꾸기

# 데이터를 삭제 해보자
db.users.delete_one({'name':'영수'})

실습 하면서 깃허브에 올리고 있는데 아무래도 몽고DB의 아이디와 패스워드가 코드에 그대로 올라가다보니 바로 보안이 취약하다고 메일이 온다. 인강 듣는 동안은 그냥 사용하고 프로젝트를 해볼때는 이부분도 방법을 찾아야겠다.

 

pymongo 코드 요약

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

 

 

5. 크롤링 한 것들을 DB에 저장 하기

저번에 만든 크롤링 코드에 더해서

DB에 저장까지 해보자.

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

import requests
from bs4 import BeautifulSoup

URL = "<https://movie.daum.net/ranking/reservation>"
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,headers=headers)
soup = BeautifulSoup(data.text, 'html.parser')

video_list = soup.select("#mainContent > div > div.box_ranking > ol > li")
for v in video_list:
  # print(v)
  rank = v.select_one(".rank_num").text
  title = v.select_one(".tit_item").text.strip("\\n")
  rate = v.select_one(".txt_grade").text
  # print(rank, title, rate)
  doc = {
    'title':title,
    'rank':rank,
    'rate':rate
  }
  db.movies.insert_one(doc)

목록에 있는 영화를 다 긁어와서 몽고DB의 users 말고 movies에 영화제목, 순위, 평점을 저장한다.

 

 

6. DB에서 원하는 데이터 가져오기

의도. "슈가: 로드 투 디데이"와 평점이 같은 영화의 제목들 가져오기

  • "슈가: 로드 투 디데이"의 평점 가져오기
  • 평점을 변수 선언(target_rate)
  • find를 사용해서 target_rate 와 똑같은 평점의 영화를 전부 찾기.
  • all_movies에 평점이 같은 모든 영화를 저장
  • 반복문으로 모든 영화에서 title 즉, 제목만 print로 찍기.
from pymongo import MongoClient
client = MongoClient('mongodb+srv://<user>:<pass>@cluster0.zlnt7r2.mongodb.net/?retryWrites=true&w=majority')
db = client.dbsparta 

# 내 몽고DB 에서 영화 "슈가: 로드 투 디데이"의 평점 가져오기
movie = db.movies.find_one({'title':'슈가: 로드 투 디데이'})
# print(movie) # {'_id': ObjectId('6481c4d56e01ed539bffcdd7'), 'title': '스즈메의 문단속', 'rank': '16', 'rate': '7.3'}
# print(movie['rate']) # 7.3

# "슈가: 로드 투 디데이"와 평점이 같은 영화의 제목들 가져오기
target_rate = movie['rate']

# 내가 만든 똥
# all_movies = list(db.movies.find({},{'_id':False}))
# for a in all_movies:
#     if a['rate'] == target_rate:
#         print(a['title'])

# 강의에서 한거
all_movies = list(db.movies.find({'rate':target_rate},{'_id':False}))
for a in all_movies:
	print(a['title'])

# "슈가: 로드 투 디데이" 평점을 0으로 만들기
# db.movies.update_one({'title':'슈가: 로드 투 디데이'},{'$set':{'rate':0}})
# print(movie) # 확인

 

7. 알아서 크롤링해서 DB에 데이터 insert 하기

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

Q2. 순위 / 곡 제목 / 가수를 스크래핑 하면 됩니다.

지니뮤직 사이트
<https://www.genie.co.kr/chart/top200?ditc=M&rtm=N&ymd=20230101>

힌트)
0) 출력 할 때는 print(rank, title, artist) 하면 됩니다!
1) 앞에서 두 글자만 끊기! text[0:2] 를 써보세요!
2) 순위와 곡제목이 깔끔하게 나오지 않을 거예요. 옆에 여백이 있다던가, 다른 글씨도 나온다던가.. 파이썬 내장 함수인 strip()을 잘 연구해보세요!

크롤링해서 몽고DB에 insert 까지 해봤음.

########################## DB 연결 정보 ##########################
from pymongo import MongoClient
client = MongoClient('mongodb+srv://<user>:<pass>@cluster0.zlnt7r2.mongodb.net/?retryWrites=true&w=majority')
db = client.dbsparta 

########################## 크롤링 ##########################
import requests
from bs4 import BeautifulSoup

# Q1. 지니뮤직의 1~50위 곡을 스크래핑 해보세요.
# Q2. 순위 / 곡 제목 / 가수를 스크래핑 하면 됩니다.
URL = "https://www.genie.co.kr/chart/top200?ditc=M&rtm=N&ymd=20230101"
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, headers=headers)
soup = BeautifulSoup(data.text, 'html.parser')

trs = soup.select('#body-content > div.newest-list > div > table > tbody > tr')                         
#print(title.text.strip()) # Ditto
for tr in trs:
    # 순위 number
    # 곡제목 title ellipsis
    # 가수명 artist ellipsis

    rank = tr.select_one('.number').text[0:2].strip()
    song = tr.select_one('.title').text.strip()
    singer = tr.select_one('.artist').text
    print(rank,song,singer)

########################## DB로 insert ##########################

    doc = {
        'rank':rank,
        'song':song,
        'singer':singer
    }
    db.genieTop50.insert_one(doc)

 

별거 아니지만 내 DB에 뉴진스가 있다니 뿌듯합니다.