콘텐츠로 건너뛰기

[스파르타 웹 개발 종합] 파이썬으로 크롤링하고 DB에 저장하기(request, bs4, mongoDB 패키지 사용)

파이썬을 설치 한다는건? 컴퓨터가 해석할 수 있는 번역 패키지를 설치한다는 의미와 같음

함수 선언

def sum(num1,num2):
    print('num1+num2')
    return num1+num2

print(sum(2,3))

python은 중괄호가 없어. 들여쓰기로 판단함.

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

is_adult(30)
is_adult(10)

조건문

age = 30

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

반복문 – 반복문은 어차피 리스트랑 쓸 거 아니니. 간단하게 쓰자.

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

for fruit in fruits:
    print(fruit)
    
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:
print(person['name'], person['age'])

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

파이썬은 라이브러리가 방대하기로 유명함!

virtual environment: 각 프로젝트 별로 라이브러리를 설치 할 수 있게끔 만들어주는 공구함 같은 것.

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

패키지 추가하는 방법 (맥 기준)
preference – project – python interpreter – + 버튼 클릭 – 원하는 패키지 이름 검색 후 install

06. 패키지 사용해보기

01) requests 패키지 사용

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

r = requests.get('http://openapi.seoul.go.kr:8088/6d4d776b466c656533356a4b4b5872/json/RealtimeCityAir/1/99')
rjson = r.json()

print(rjson)
import requests # requests 라이브러리 설치 필요

r = requests.get('http://openapi.seoul.go.kr:8088/6d4d776b466c656533356a4b4b5872/json/RealtimeCityAir/1/99')
rjson = r.json()


gus = rjson['RealtimeCityAir']['row']

for gu in gus:
gu_name = gu['MSRSTE_NM']
gu_mise = gu['IDEX_MVL']
if(gu_mise>100):
print(gu_name,':', gu_mise)

02) 크롤링 패키지 사용

beautiful soup (bs4) 패키지 설치

# import
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.nhn?sel=pnt&date=20200303',headers=headers)

# beautiful soup 형태로 만들기
soup = BeautifulSoup(data.text, 'html.parser')

# 코딩 시작

크롤링이 가능한 이유는 뭘까? 인터넷 서버에서 받아온 자료를 가지고 원하는 자료를 솎아내는것을 크롤링이라고 함. 크롤링을 할 때는 기술적으로 딱 두 가지가 중요함
1) 요청하는 것 2) 요청해서 가지고 온 데이터 중 내가 원하는 데이터를 솎아내는 것

가져오고 싶은 태그 오른쪽 마우스 클릭 – copy – copy selector

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


# import
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.nhn?sel=pnt&date=20200303',headers=headers)

# beautiful soup 형태로 만들기
soup = BeautifulSoup(data.text, 'html.parser')

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

결과값

그린 북
그린 북
/movie/bi/mi/basic.nhn?code=171539

# import
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.nhn?sel=pnt&date=20200303',headers=headers)

# beautiful soup 형태로 만들기
soup = BeautifulSoup(data.text, 'html.parser')
trs = soup.select('#old_content > table > tbody > tr')

#가져오고 싶은 데이터:
#old_content > table > tbody > tr:nth-child(2) > td.title > div > a

for tr in trs:
    a_tag = tr.select_one('td.title > div > a')
    if a_tag is not None:
        title = a_tag.text
        print(title)

결과값

그린 북
가버나움
베일리 어게인
주전장
포드 V 페라리
아일라
원더
당갈
쇼생크 탈출
터미네이터 2:오리지널
보헤미안 랩소디
덕구
나 홀로 집에
월-E
살인의 추억
빽 투 더 퓨쳐
인생은 아름다워
매트릭스
라이언 일병 구하기
사운드 오브 뮤직
헬프
포레스트 검프
안녕 베일리
글래디에이터
위대한 쇼맨
센과 치히로의 행방불명
토이 스토리 3
어벤져스: 엔드게임
클래식
알라딘
헌터 킬러
죽은 시인의 사회
아이 캔 스피크
레옹
동주
반지의 제왕: 왕의 귀환
타이타닉
캐스트 어웨이
여인의 향기
집으로...
굿바이 마이 프랜드
서유기 2 - 선리기연
주토피아
두 교황
굿 윌 헌팅
클레멘타인
히든 피겨스
세 얼간이
쉰들러 리스트
울지마 톤즈

Process finished with exit code 0

# import
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.nhn?sel=pnt&date=20200303',headers=headers)

# beautiful soup 형태로 만들기
soup = BeautifulSoup(data.text, 'html.parser')
trs = soup.select('#old_content > table > tbody > tr')

for tr in trs:

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

print(rank, title, star)

결과값

01 그린 북 9.60
 02 가버나움 9.59
 03 베일리 어게인 9.52
 04 주전장 9.52
 05 포드 V 페라리 9.51
 06 아일라 9.49
 07 원더 9.49
 08 당갈 9.47
 09 쇼생크 탈출 9.44
 010 터미네이터 2:오리지널 9.43
 11 보헤미안 랩소디 9.42
 12 덕구 9.41
 13 나 홀로 집에 9.41
 14 월-E 9.41
 15 살인의 추억 9.40
 16 빽 투 더 퓨쳐 9.40
 17 인생은 아름다워 9.39
 18 매트릭스 9.39
 19 라이언 일병 구하기 9.39
 20 사운드 오브 뮤직 9.39
 21 헬프 9.39
 22 포레스트 검프 9.39
 23 안녕 베일리 9.39
 24 글래디에이터 9.39
 25 위대한 쇼맨 9.38
 26 센과 치히로의 행방불명 9.38
 27 토이 스토리 3 9.38
 28 어벤져스: 엔드게임 9.38
 29 클래식 9.38
 30 알라딘 9.38
 31 헌터 킬러 9.37
 32 죽은 시인의 사회 9.37
 33 아이 캔 스피크 9.37
 34 레옹 9.37
 35 동주 9.37
 36 반지의 제왕: 왕의 귀환 9.37
 37 타이타닉 9.36
 38 캐스트 어웨이 9.36
 39 여인의 향기 9.36
 40 집으로… 9.36
 41 굿바이 마이 프랜드 9.35
 42 서유기 2 - 선리기연 9.35
 43 주토피아 9.35
 44 두 교황 9.35
 45 굿 윌 헌팅 9.35
 46 클레멘타인 9.35
 47 히든 피겨스 9.35
 48 세 얼간이 9.35
 49 쉰들러 리스트 9.34
 50 울지마 톤즈 9.34

DB에 데이터 저장하기

크롤링한 데이터를 DB에 저장해보자 – MongoDB와 Robo 3T를 사용해서

MongoDB는 데이터베이스다. 눈에 보이지 않게 실행됨. Robo 3T는 MongoDB의 데이터 베이스를 눈에 보여주는 프로그램

  1. Mongo DB 설치 확인

http://localhost:27017/ 에 접속했을 때 아래와 같은 화면이 뜨면 정상적으로 설치 된 것

2. Robo 3T에 connection 생성

create 버튼 눌러서 이름만 원하는대로 변경해주면 됨. 그 후 connect

옆으로 새기) DB에 대해서

DB의 역할: DB를 쓰는 이유는 데이터를 잘 가져다 쓰려고. 서점에서 책을 잘 찾으려고 책장에 꽂아 놓는것과 같이

데이터베이스의 종류 2가지: SQL과 NoSQL
1) SQL (RDBMS) : 엑셀과 비슷함. 학생들의 이름/전화번호/주소를 저장한다고 할 때, 전화번호가 없는 학생의 전화번호 칸은 비워두는 형식. 행과 열이 사전에 정의되어 있음. 중간에 변경하기가 쉽지 않음. 데이터가 일관적이기 때문에, 데이터를 분석하거나 추출하는것은 쉬움.
ex) MySQL, MSSQL, Oracle


2) NoSQL (No SQL): 딕셔너리 형태로 데이터를 저장하는 DB. 각각 이름/전화번화/주소를 저장하는 칸이 지정되어 있는것이 아니고, 있는 데이터만 명시해서 저장함. 자유로운 형태의 데이터 적재에 유리한 대신, 일관성이 부족할 수 있음. 앞으로 저장할 데이터가 추가/삭제가 빈번하게 바뀔 수 있는 스타트업에서 많이 사용 함.
ex) MongoDB

파이썬에서 MongoDB 사용하기 – pymongo로 DB 조작하기

pymongo: python에서 mongoDB를 조작할 수 있는 라이브러리

pymongo 설치

pycharm – preference – project – python interpreter – + – pymongo 검색 – install package

pymongo 기본 코드

from pymongo import MongoClient
client = MongoClient('localhost', 27017)
db = client.dbsparta

# 코딩 시작

DB 연결하기 & insert

# DB에서 중요한것은 insert / find / update / delete

# pymongo import
from pymongo import MongoClient

#localhost에 연결
client = MongoClient('localhost', 27017)

#dbsprata DB에 접속. 없으면 자동 생성
db = client.dbsparta


#insert 할 dictionary 정의
doc = {'name':'bobby','age':21}

#db안에 users라는 collection에 insert해
db.users.insert_one(doc)

#find – age가 21인 데이터들 찾기 (데이터에 몇명 더 추가해 놓음)

# DB에서 중요한것은 insert / find / update / delete

# pymongo import
from pymongo import MongoClient
#localhost에 연결
client = MongoClient('localhost', 27017)
#dbsprata DB에 접속. 없으면 자동 생성
db = client.dbsparta

same_ages = list(db.users.find({'age':21},{'_id':False}))

for person in same_ages:
    print(person)

결과값

{'name': 'bobby', 'age': 21} {'name': 'Lucy', 'age': 21}

모든 값 다 가져오고 싶을 경우

same_ages = list(db.users.find({},{'_id':False}))

특정 값 하나만 가져오고 싶을 경우

user = db.users.find_one({'name':'bobby'})
print(user)

업데이트

# name이 bobby인 데이터의 age를 19로 변경
db.users.update_one({'name':'bobby'},{'$set':{'age':19}})

삭제하기

#name이 bobby인 data를 삭제
db.users.delete_one({'name':'bobby'})

요약

# pymongo import
from pymongo import MongoClient

#localhost에 연결
client = MongoClient('localhost', 27017)

#dbsprata DB에 접속. 없으면 자동 생성
db = client.dbsparta


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

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

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

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

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

크롤링 코드에 응용하기

# import
import requests
from bs4 import BeautifulSoup

# pymongo import, connect to localhost, dbsprta DB
from pymongo import MongoClient

client = MongoClient('localhost', 27017)
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.nhn?sel=pnt&date=20200303', headers=headers)

# beautiful soup 형태로 만들기
soup = BeautifulSoup(data.text, 'html.parser')
trs = soup.select('#old_content > table > tbody > tr')

for tr in trs:

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

        print(rank, title, star)
        
        #DB 저장을 위한 dictionary 정의
        doc = {
            'rank': rank,
            'title': title,
            'star': star
        }

        #movies collection에 데이터 삽입
        db.movies.insert_one(doc)

익숙해지기 _ Quiz. 웹스크래핑(웹크롤링) 결과 이용하기

  1. 영화 매트릭스의 평점 가져오기
  2. ‘매트릭스’의 평점과 같은 평점의 영화 제목들을 가져오기
  3. 매트릭스 영화의 평점을 0으로 변경하기
# pymongo import
from pymongo import MongoClient
#localhost에 연결
client = MongoClient('localhost', 27017)
#dbsprata DB에 접속. 없으면 자동 생성
db = client.dbsparta

# title이 매트릭스인 영화의 평점 출력
movie_matrix = db.movies.find_one({'title':'매트릭스'})
target_star = movie_matrix['star']
print(movie_matrix)

# 매트릭스와 평점이 같은 영화들의 타이틀을 출력
target_movies = list(db.movies.find({'star':target_star},{'_id':False}))
for target in target_movies:
    print(target['title'])

# 매트릭스의 평점을 '0'으로 변경
db.movies.update_one({'title':'매트릭스'},{'$set':{'star':'0'}})
star_matrix = db.movies.find_one({'title':'매트릭스'})['star']
print(star_matrix)

숙제 – 지니뮤직 사이트에서 1~50위 곡을 스크래핑 하기

순위 / 곡 제목 / 가수를 스크래핑 하기

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

지니 뮤직 사이트

https://www.genie.co.kr/chart/top200?ditc=D&ymd=20210201&hh=23&rtm=N&pg=1

# 스파르타 웹 개발 종합반 3주차
# 지니 뮤직 순위 차트 스크래핑 하기 - 순위, 곡 이름, 아티스트 이름 출력
# 2021.02.06

# import
import requests
from bs4 import BeautifulSoup

# pymongo import, connect to localhost, dbsprta DB
from pymongo import MongoClient

client = MongoClient('localhost', 27017)
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=D&ymd=20210201&hh=23&rtm=N&pg=1', headers=headers)

# beautiful soup 형태로 만들기
soup = BeautifulSoup(data.text, 'html.parser')
list_trs = soup.select('#body-content > div.newest-list > div > table > tbody > tr')

# 가져오고 싶은 데이터 형식:
#rank
#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.number

#title
#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.info > a.title.ellipsis

#artist
#body-content > div.newest-list > div > table > tbody > tr:nth-child(1) > td.info > a.artist.ellipsis


for tr in list_trs:
    td_number = tr.select_one('td.number')
    #.contents로 0번째 child만 읽어옴. 첫번째 child에 rank 값이 있음.
    rank = td_number.contents[0]
    #strip(): Remove spaces at the beginning and at the end of the string:
    rank = rank.strip()

    td_info = tr.select_one('td.info')
    title = td_info.select_one('a.title.ellipsis').text
    title = title.strip()

    artist = td_info.select_one('a.artist.ellipsis').text
    print(rank, title, artist)

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다