공대생

스파르타코딩 3주차 본문

스터디/스파르타코딩

스파르타코딩 3주차

상수나무 2021. 7. 20. 09:01

[수업 목표]

  1. 파이썬 기초 문법을 안다.
  2. 원하는 페이지를 크롤링 할 수 있다.
  3. pymongo를 통해 mongoDB를 제어할 수 있다.

1. Python

파이썬 가상환경 생성하기

가상환경을 생성하는 이유?

-> 집에서는 버전 3의 opencv를 쓰는데 회사에서는 버전 2의 opencv를 쓰라고 하면 이 두 라이브러리를 한 컴퓨터에 동시에 설치해버리면 충돌남

그래서 프로젝트마다 가상환경을 만들어줌으로써 프로젝트 안에서만 해당 라이브러리를 사용하도록 하는 것.

 

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

 

가상환경 생성하기

file -> new project

*Base interpreter를 파이썬으로 설정.

필자의 경우 처음에 가상환경을 만들 때 노트북에 미리 깔려있던 anaconda 가상환경을 생성해서 나중에 라이브러리를 설치할 때 에러가 났음

파이썬 패키지 설치하기

패키지? 라이브러리? → Python 에서 패키지는 모듈(일종의 기능들 묶음)을 모아 놓은 단위이다. 이런 패키지의 묶음을 라이브러리 라고 볼 수 있다. 지금 여기서는 외부 라이브러리를 사용하기 위해서 패키지를 설치한다. 즉, 여기서는

패키지 설치 = 외부 라이브러리 설치!

 

패키지 설치하기

file -> setting -> project -> python interpreter -> + -> 라이브러리 검색 ->install package

패키지 사용해보기

(아래 방법으로 서울시 대기 OpenAPI에서, 중구의 NO2 값을 가져올 수 있음)

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

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

print(rjson['RealtimeCityAir']['row'][0]['NO2'])

 

2. 웹크롤링(스크래핑)

사용 라이브러리: bs4 안의 BeautifulSoup

requests: 웹에서 html코드를 받아옴

BeautifulSoup: 받아온 코드 중에 필요한 정보만 걸러냄

 

웹크롤링 기본세팅

import requests
from bs4 import BeautifulSoup

# 타겟 URL을 읽어서 HTML를 받아오고,
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)

# HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦
# soup이라는 변수에 "파싱 용이해진 html"이 담긴 상태가 됨
# 이제 코딩을 통해 필요한 부분을 추출하면 된다.
soup = BeautifulSoup(data.text, 'html.parser')

#############################
# (입맛에 맞게 코딩)
#############################
  • select / select_one

영화 제목을 가져와보기!

태그 안의 텍스트를 찍고 싶을 땐 → 태그.text

태그 안의 속성을 찍고 싶을 땐 → 태그['속성']

 

크롬 개발자도구를 참고하는 방법

  1. 원하는 부분에서 마우스 오른쪽 클릭 → 검사
  2. 원하는 태그에서 마우스 오른쪽 클릭
  3. Copy → Copy selector로 선택자를 복사할 수 있음

EX) 예를 들어 영화의 제목만 주루룩 따오고 싶을 경우

-> 각 제목에 들어가서 html코드를 복붙해보면 다음과 같이 나옴

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

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

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

 

-> #old_content > table > tbody > tr 이걸 select하면 영화제목을 다 select해오는 것임

trs = soup.select('#old_content > table > tbody > tr') #select는 결과가 리스트로 나옴

EX) 웹스크래핑 더 해보기 (순위, 제목, 별점)

import requests
from bs4 import BeautifulSoup

# URL을 읽어서 HTML를 받아오고,
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)

# HTML을 BeautifulSoup이라는 라이브러리를 활용해 검색하기 용이한 상태로 만듦
soup = BeautifulSoup(data.text, 'html.parser')

# select를 이용해서, tr들을 불러오기
movies = soup.select('#old_content > table > tbody > tr')

# movies (tr들) 의 반복문을 돌리기
for movie in movies:
    # movie 안에 a 가 있으면,
    a_tag = movie.select_one('td.title > div > a')
    if a_tag is not None:
        rank = movie.select_one('td:nth-child(1) > img')['alt'] # img 태그의 alt 속성값을 가져오기
        title = a_tag.text                                      # a 태그 사이의 텍스트를 가져오기
        star = movie.select_one('td.point').text                # td 태그 사이의 텍스트를 가져오기
        print(rank,title,star)

위의 코드를 실행시키면 다음 화면의 결과처럼 나옴

순위, 제목, 평점

3. DB 이용하기

DataBase의 종류

RDBMS(SQL) -> 정해진 규격이나 크기가 있음

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

ex) MS-SQL, My-SQL 등

 

No-SQL -> 정해진 규약없이 테이블마다 새로 만듬

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

ex) MongoDB

 

*이 프로젝트에서는 데이터베이스로 No-SQL 중 대표적인 mongoDB를 사용하였고 이 데이터베이스 내부를 보기 위한 GUI프로그램으로 robo 3T를 이용하였다. 

 

pymongo로 DB 조작하기

(1) pymongo 라이브러리 설치

(2) pymongo 기본코드

from pymongo import MongoClient
client = MongoClient('localhost', 27017) #내 컴터에 돌아가고 있는 DB에 접속
db = client.dbsparta

# 코딩 시작

(3) DB연결하기 & DB 이용하기

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

DB연동한 main.py 코드

import requests
from bs4 import BeautifulSoup

from pymongo import MongoClient
client = MongoClient('localhost', 27017) #내 컴터에 돌아가고 있는 DB에 접속
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) #requests로 html을 받아온 것

soup = BeautifulSoup(data.text, 'html.parser') #bs4로 솎아내기 좋은 형태로 받아옴

trs = soup.select('#old_content > table > tbody > tr') #select는 결과가 리스트로 나옴

for tr in trs:
a_tag = tr.select_one('td.title > div > a') #tr에서 제목인 부분 찾기
c_tag = tr.select_one('td.point')
if a_tag is not None: #사이트에서 빈칸은 None타입이기 때문에 빼고 처리
rank = tr.select_one('td:nth-child(1) > img')['alt']
title = a_tag.text
star = c_tag.text #평점
doc = {
'rank':rank,
'title':title,
'star':star
}
db.movies.insert_one(doc)

'''
title = soup.select_one('#old_content > table > tbody > tr:nth-child(2) > td.title > div > a') #그린북의 위치를 알려줌

print(title)
#title.text: 태그 안에 있는 텍스트만 가져옴
#title['href']: 태그의 속성을 가져옴
'''

4. 숙제(geine 차트 크롤링)

import requests
from bs4 import BeautifulSoup

from pymongo import MongoClient
client = MongoClient('localhost', 27017) #내 컴터에 돌아가고 있는 DB에 접속
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=20200403&hh=23&rtm=N&pg=1',headers=headers) #requests로 html을 받아온 것

soup = BeautifulSoup(data.text, 'html.parser') #bs4로 솎아내기 좋은 형태로 받아옴

trs = soup.select('#body-content > div.newest-list > div > table > tbody > tr') #select는 결과가 리스트로 나옴

for tr in trs:
a_tag = tr.select_one('td.info > a.title.ellipsis') # tr에서 제목인 부분 찾기
rank = tr.select_one('td.number').text[0:2].strip()
title = a_tag.text.strip()
artist = tr.select_one('td.info > a.artist.ellipsis').text

print(rank, title, artist)

'''
strip() 함수
띄어쓰기(' '), 탭('\t'), 엔터('\n') 까지, 포괄적으로 이야기하는 whitespace를 제거하는 함수.

문자열의 끝에 .strip()을 붙이면,
문자열의 '맨앞'과, '맨뒤' 의 whitespace가 제거가 된다. 단, 중간중간의 whitespace는 제거가 되지 않는다.
'''

#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(2) > 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.number

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

'스터디 > 스파르타코딩' 카테고리의 다른 글

스파르타코딩 2주차  (0) 2021.07.11
스파르타코딩 1주차  (0) 2021.07.09
Comments