2023.01.13 개발일지 - pymongo로 DB 조작

클로이🖤·2023년 1월 13일
0

Web-developer

목록 보기
17/22
post-thumbnail

DB 연결하기, 데이터 넣기

# 'users'라는 collection에 {'name':'지은','age':21}를 넣습니다.
doc = {
  'name':'서은',
  'age':29
}

db.users.insert_one(doc)

doc = {
  'name':'은지',
  'age':31
}

db.users.insert_one(doc)

터미널에서 파일 실행하기하고 mongoDB 사이트에 가서 확인해 보면

이런 식으로 users 안에 데이터가 2개 더 들어간 것을 확인할 수 있다. 이제 모든 데이터를 가지고 오는 것 부터 해보자.

#모든 데이터 가져오기
all_users = list(db.users.find({},{'_id':False}))

#반복문 돌려서 모든 데이터 가져오기
for users in all_users:
  print(users)


이렇게 코드 작성하고 실행하면 데이터들이 쭉 나오는 것을 확인 할 수 있다.

이제는 데이터를 수정해보자.

db.users.update_one({'name':'지은'},{'$set':{'age':28}})

name이 '지은'인 데이터를 찾아서 age를 28로 바꾸라는 코드. 마찬가지로 저장 - 터미널에서 파이썬 파일 실행하고 db 사이트에 가서 확인해보면

이렇게 name이 지은인 값이 28로 바뀐 것을 확인할 수 있다. 데이터를 삭제하려면

db.users.delete_one({'name':'서은'})

코드를 실행하면 된다. update랑 크게 차이 없어보임. 아래는 코드 모음.

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

이제 정말 기본적인 내용을 배워봤으니까, 전에 네이버 영화 스크래핑 해온 내용을 db에 넣어보도록 하겠다.

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:
  movie = tr.select_one('td.title > div > a')
  
  if movie is not None:
    title = movie.text
    rank = tr.select_one('td > img')['alt']
    rate = tr.select_one('td.point').text
    print(rank, title, rate)

이 hello.py 파일에 mongoDB를 사용하기 위해 아래 코드를 파일 맨 위에 붙여넣어 줬다.

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

if문을 살짝 수정해줬다. title, rank, rate가 들어갈 doc 딕셔너리를 하나 만들어주고 값을 넣어줬다. 그리고 아까 배웠던 insert를 사용해야 되기 때문에 db.users.insert_one(doc) 이걸 가져와서 살짝 수정. users 안에 영화가 들어가긴 좀 그러니까 movies 라는 소그룹을 하나 만들어서 insert.

  if movie is not None:
    title = movie.text
    rank = tr.select_one('td > img')['alt']
    rate = tr.select_one('td.point').text
    doc = {
      'title':title,
      'rank':rank,
      'rate':rate
    }
    db.movies.insert_one(doc)

저장하고 실행하면 터미널에는 결과가 나오지 않지만 db페이지에서 확인해보면
이렇게 movies라는 컬렉션이 생성되고 그 안에 값들이 저장되어 있는 것들을 확인할 수 있다.

여기서 영화들 중에 '가버나움' 이라는 영화 값을 출력하려면 어떻게 코드를 작성해야 할까? user = db.users.find_one({'name':'bobby'}) 이 예시 코드를 사용해서 작성하면 될 것 같아서 영상 멈춰놓고 혼자 해봤다.

movie = db.movies.find_one({'title':'가버나움'}, {'_id':False})

print(movie)


원하던 값이 출력된 것을 확인 할 수 있다. (나 .. 조금 대견할지도..?)

이번에는 가버나움과 같은 평점인 영화를 출력하는 코드를 작성해보자.

movie = db.movies.find_one({'title':'가버나움'}, {'_id':False})
target_rate = movie['rate']

all_movies = list(db.movies.find({'rate':target_rate},{'_id':False}))

for same in all_movies:
  print(same['title'])

target_star = movie['rate'] => 가버나움이랑 평점을 target_star로 설정해주고 all_movies = list(db.movies.find({'rate':target_star},{'_id':False})) => 영화 리스트에서 값을 target_rate와 동일한 값을 출력하는 all_movies 변수 작성. for same in all_movies: print(same['title']) 으로 반복문 돌려서 all_movies의 title만 출력. 그럼 이렇게 title만 출력이 된다.

가버나움의 평점을 0으로 바꾸고 싶다면 ?

movie = db.movies.find_one({'title':'가버나움'}, {'_id':False})

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

print(movie['rate'])

간단하게 update 코드 사용해서 가버나움의 rate를 0으로 업데이트 하고, 업데이트 되었는지 확인하기 위해서 rate를 print 해줬다.

이렇게 0이 출력되는 것을 확인할 수 있다 !

과제

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

결과는 이렇게 깔끔하게 순위, 제목, 가수 이렇게 나와야 한다. 가보자구~

스크래핑을 하기 위해서는 bs4 사용해줘야 하기 때문에 genie.py 파일을 만들고 아래 코드를 붙여넣어 준다. (네이버 영화 스크래핑 때와 동일)

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://www.genie.co.kr/chart/top200?ditc=M&rtm=N&ymd=20221201',headers=headers)

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

사이트로 가서, 일단 제목을 가져와보기 위해 1위인 사건의 지평선 txt 위에서 오른쪽 마우스 클릭 -inspect 하면 개발자도구 창이 나타난다. 저 파란색 부분에서 오른쪽 마우스 - copy - copy selector 하면
#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.info > a.title.ellipsis
그리고 바로 밑에 윤하 라고 가수 이름이 나와있는 쪽에서 똑같이 copy selector 해주기 결과는
#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.info > a.artist.ellipsis

순위도 보기 위해서 1에서 inspect 해서 copy selector 해주면
#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.number

그럼 여기서 우리는
#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) 까지가 동일한 걸 확인할 수 있다.

trs = soup.select('#body-content > div.newest-list > div > table > tbody > tr') 코드를 작성해서 trs를 반복문을 돌려보자.

제목은 title이라는 변수명으로 tr에서 select_one (하나를 가져와 줄건데) tr 아래의 td.info > a.title.ellipsis 의 text를 가져와야 하고 가수도 td.info > a.artist.ellipsis 의 text, 순위도 td.number에서 text를 가져와 준다. 여기까지 작성하고 코드를 돌려보자.

이렇게 난리가 난다 .. 아까 첫번째 힌트를 보면

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

라고 했으니 이걸 사용해서 순위를 작성하면 뒤에 상승, 유지 라고 적힌 내용들이 안나올 거 같다. 적용해보면

음 ,, 상승이나 유지 글자는 안나오지만 여전히 줄이 안맞고 엉망진창 ;; 그럼 여기서 두번째 힌트 !

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

이걸 title이랑 rate에 붙여보면 ... ?

우리가 원하던 결과대로 깔끔하게 출력이 되는 것을 확인할 수 있다 !!!!! 과제 끝 T^T!!!!

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://www.genie.co.kr/chart/top200?ditc=M&rtm=N&ymd=20221201',headers=headers)

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

trs = soup.select('#body-content > div.newest-list > div > table > tbody > tr')

for tr in trs:
  title = tr.select_one('td.info > a.title.ellipsis').text.strip()
  artist = tr.select_one('td.info > a.artist.ellipsis').text
  rate = tr.select_one('td.number').text[0:2].strip()

  print(rate, title, artist)
profile
front-end developer

0개의 댓글