개인공부

개발공부 13일차 [웹스크래핑(크롤링), DB]

stella0905 2023. 2. 7. 11:53

라이브러리

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

gu_name, gu_mise값만 추출해서 반복문으로 볼 수 있음

크롤링 : 웹에 접속해서 데이터를 솎아내어 가지고옴

오른쪽 하단에 ‘venv’:venv 로 잘 열려있는지 확인

잘 열려있다면 터미널에 (venv)가 있는지 확인

없다면 터미널 → 새터미널 눌러주면 생김

라이브러리를 가져올때 : 터미널에 pip install (가져올 라이브러리 이름) 치기

 

requests - 요청하다

beautifulsoup - 솎아내다

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

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

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

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:
    print(a.text)

1. 크롤링 할 페이지에서 가져올 글에 검사로 tr을 먼저 찾아

    #old_content > table > tbody > tr:nth-child(2)

    #old_content > table > tbody > tr:nth-child(3) \

    이중 공통되는 #old_content > table > tbody > tr 공통되는 걸 변수trs에 찾는다.

    (공통되는걸 찾을때는 tr에 우클릭으로 Copy → CopySelector로 가져올 수 있다)

2. trs를 반복문으로 불러온다.

3. tr안에서 내가 가져올

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

    공통되는 td.title > div > a를 찾는다.

4. 찾은 td에 ——— 도 포함이 되어있어 None으로 표시되는데

    if a is not None: 을 써서 None이 아닌것만 text로 불러온다.

 

 

응용하기

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

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

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

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:
    title = a.text
    rank = tr.select_one('td:nth-child(1) > img')['alt']
    star = tr.select_one('td.point').text
    print(rank, title, star)

a는 이미 찾았기때문에 title 변수를 만들어 a.text로 넣어준다.

rank, star도 동일한 방식으로 가져오고 마지막에 원하는 순서로 찍으면 완성

⬇️결과값 

 

------------------------------------------------------------------------------------------

 

데이터베이스 - DB

SQl - 이미 정해진 칸에 넣는거임.

    이미 정해져 있어 사람이 틀릴 리 없음 / 후에 변하지 않는다는 가정으로 / 빨리 가져올 수 있음 (대기업같은 경우)

NoSQl (Not only SQL) - 정형화된 틀이 아님 / 데이터를 내 마음대로 저장할 수 있음

    (스타트업이 주로 사용) 저장할 틀이 변경될일이 많을 경우

 

mongoDB Atlas - 클라우드

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

doc = {
  'name':'영수',
  'age':24
}
db.users.insert_one(doc)

db.users.insert_one(doc) ← 여기에 users는 소그룹이름 이라고 생각해도 됨

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}))
#{'_id':False}를 사용하는 이유는 _id의 값을 출력하지 않기 위해서다.

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

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

mongoDB에 자료 넣는 방법 복습

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


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:
    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
    }
    db.movies.insert_one(doc)
  1. 기존 영화 목록에 상단에 몽고디비에 연결될 수 있도록 넣어준다.
  2. Dictionary를 만들어서 넣어줘야함 doc = {}
  3. 마지막으로 insert해주기 위해 movies라는 소그룹명을 만들고 넣어줌.

 

위 내용을 가지고 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},{'_id':False}))
for a in movies:
  print(a['title'])
  1. 변수 movie에서 가버나움의 star값을 target_star라는 변수라고 해놓는다.
  2. 변수 movies로 소그룹movies에 star값이 target_star이 동일한 것만 가지고 온다.
  3. 마지막으로 반복문으로 타이틀만 가지고온다.

 

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

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

 

숙제

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=20210701',headers=headers)

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

#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.info > a.title.ellipsis
#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) > td.info > a.artist.ellipsis
trs = soup.select('#body-content > div.newest-list > div > table > tbody > tr')
for tr in trs:
  a = tr.select_one('td.info > a.title.ellipsis')
  title = a.text.strip()
  rank = tr.select_one('td.number').text[0:2].strip()
  artist = tr.select_one('a.artist.ellipsis').text.strip()
  print(rank,title,artist)

text[0:2]는 텍스트에 2번째 글자 까지만 나오게 한다.

strip()은 글자의 공백이 없게 나오게 한다.

 

크롤링 강의를 처음봤을땐 어..?싶었고 일단 다 보고서 강의를 다시 멈추면서 하나하나 적어가면서 다시 보니깐 이해가 갔고 생각보다 재밌었다. 

마지막 숙제에서는 진짜 구글링을 아직 할 줄 모르니까 제대로된 답도 안나오고 '그냥 강의에 답을 볼까..?' 싶었다가 꾹참았다.

시간은 좀 걸렸지만 스스로 하고 맞은걸 보니 넘나 뿌듯...하다..