스파르타 코딩클럽 3주차

BYEONGMIN CHOI·2022년 5월 2일
0

WIL(Week I Learned)

목록 보기
3/8

python, 크롤링(crawling), DB(pymongo를 통한 mongoDB)

파이썬 패키지(package)

패키지? 라이브러리?
Python 에서 패키지는 모듈(일종의 기능들 묶음)을 모아 놓은 단위 
이런 패키지 의 묶음을 라이브러리 라고 볼 수 있음. 
즉, 여기서는 패키지 설치 = 외부 라이브러리 설치!
가상 환경(virtual environment) 이란? - 프로젝트별로 패키지를 담을 공구함
가상환경(virtual environment)은
같은 시스템에서 실행되는 다른 파이썬 응용 프로그램들의 동작에 영향을 주지 않기 위해, 
파이썬 배포 키지들을 설치하거나 업그레이드하는 것을 가능하게 하는 격리된 실행 환경 입니다.
pip(python install package) 사용 - requests 패키지 설치
앱을 설치할 때 앱스토어/플레이스토어를 가듯이, 새로운 프로젝트의 라이브러리를 가상환경(공구함)에 설치하려면 pip 를 이용
  • project interpreter 화면에서 + 버튼을 누르면 아래 창이 뜹니다!
  • requests를 검색

패키지 사용해보기

Requests 라이브러리 사용해보기 + List/Dictionary/함수/If/For문 연습
  • 서울시 대기 OpenAPI에서, 중구의 미세먼지 값을 가져오기

      import requests # requests 라이브러리 설치 필요
    
      r = requests.get('http://spartacodingclub.shop/sparta_api/seoulair')
      rjson = r.json()
  • 모든 구의 IDEX_MVL값을 찍기

    import requests # requests 라이브러리 설치 필요
    
    r = requests.get('http://spartacodingclub.shop/sparta_api/seoulair')
    rjson = r.json()
    
    gus = rjson['RealtimeCityAir']['row']
    
    for gu in gus:
        print(gu['MSRSTE_NM'], gu['IDEX_MVL'])
    
  • IDEX_MVL 값이 60 미만인 구만 찍기

    import requests # requests 라이브러리 설치 필요
    
    r = requests.get('http://spartacodingclub.shop/sparta_api/seoulair')
    rjson = r.json()
    
    gus = rjson['RealtimeCityAir']['row']
    
    for gu in gus:
        if gu['IDEX_MVL'] < 60:
            print (gu['MSRSTE_NM'], gu['IDEX_MVL'])

웹스크래핑(크롤링) 기초

웹스크래핑 해보기
> 	네이버영화 페이지 웹스크래핑
    # 크롤링할 페이지 - 네이버 페이지
    # https://movie.naver.com/movie/sdb/rank/rmovie.naver?sel=pnt&date=20210829
  • 패키지 추가 설치(beautifulsoup4)
bs4
  • 크롤링 기본 셋팅
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.naver?sel=pnt&date=20210829',headers=headers)

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

#############################
# (입맛에 맞게 코딩)
#############################
   
  • select / select_one의 사용법

    영화 제목을 가져오기

    태그 안의 텍스트를 찍고 싶을 땐 \rightarrow 태그.text
    태그 안의 속성을 찍고 싶을 땐 \rightarrow 태그['속성']

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.naver?sel=pnt&date=20210829',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:
        # a의 text를 찍어본다.
        print (a_tag.text) 
  • beautifulsoup 내 select에 미리 정의된 다른 방법들
# 선택자를 사용하는 방법 (copy selector)
soup.select('태그명')
soup.select('.클래스명')
soup.select('#아이디명')

soup.select('상위태그명 > 하위태그명 > 하위태그명')
soup.select('상위태그명.클래스명 > 하위태그명.클래스명')

# 태그와 속성값으로 찾는 방법
soup.select('태그명[속성="값"]')

# 한 개만 가져오고 싶은 경우
soup.select_one('위와 동일')
  • 항상 정확하지는 않으나, 크롬 개발자도구를 참고할 수 있음
    1. 원하는 부분에서 마우스 오른쪽 클릭 \rightarrow 검사
    2. 원하는 태그에서 마우스 오른쪽 클릭
    3. Copy \rightarrow Copy selector로 선택자를 복사하여 사용

웹스크래핑 연습

웹스크래핑 연습(순위, 제목, 별점)

  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)  # headers : 사람이 요청하는 것?

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

  music_list = soup.select('#body-content > div.newest-list > div > table > tbody > tr')
  for music in music_list:
      title = music.select_one('td.info > a.title.ellipsis').text.strip()
      artiest = music.select_one('td.info > a.artist.ellipsis').text
      if '19금' in title:
          title = '19금 ' + title.lstrip('19금').strip()
      rank = music.select_one('td.number').text[0:2].strip()
      print(rank, title, artiest)

DB개괄

Database 두 가지 종류
👉 Database에는, 크게 두 가지 종류가 있습니다.

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

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

mongoDB

mongoDB - Atlas 가입

1) Allow Access from Anywhere 클릭 → Add IP address 클릭
2) Username, Password를 아래와 같이 입력 → Create Database User 클릭
3) Choose a connection method 클릭

mongoDB 연결하기

mongoDB - Atlas 연결
  1. 패키지 설치
    pymongo, dnspython
  1. mongoDB Atlas 화면에서 Connect application 클릭

pymongo로 DB 조작하기

1) pymongo로 mongoDB 조작하기
  • DB연결하기 & 데이터 넣기
# 'users'라는 collection에 {'name':'bobby','age':21}를 넣습니다.
db.users.insert_one({'name':'bobby','age':21})
db.users.insert_one({'name':'kay','age':27})
db.users.insert_one({'name':'john','age':30})
  • 모든 결과 값을 보기
# 모든 데이터 뽑아 보기
all_users = list(db.users.find({},{'_id':False}))

print(all_users[0])         # 0번째 결과값을 보기
print(all_users[0]['name']) # 0번째 결과값의 'name'을 보기

for user in all_users:      # 반복문을 돌며 모든 결과값을 보기
    print(user)
  • 특정 결과 값 뽑아 보기
user = db.users.find_one({'name':'bobby'})
print(user)
  • 수정하기
# 오타가 많으니 이 줄을 복사해서 씁시다!
db.users.update_one({'name':'bobby'},{'$set':{'age':19}})

user = db.users.find_one({'name':'bobby'})
print(user)
  • 삭제하기(거의 사용하지 않음)
db.users.delete_one({'name':'bobby'})

user = db.users.find_one({'name':'bobby'})
print(user)
  • 요약
# 저장 - 예시
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 저장 연습
  • 이전 네이버 영화 순위를 크롤링한 후 mongoDB에 저장
import requests
from bs4 import BeautifulSoup

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

# 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.naver?sel=pnt&date=20210829',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 태그 사이의 텍스트를 가져오기
        doc = {
            'rank': rank,
            'title': title,
            'star': star
        }
        db.movies.insert_one(doc)

3주차 마지막 연습

지니뮤직의 1~50위 곡을 스크래핑
  • 지니 뮤직 사이트의 순위/곡 제목/ 가수를 스크래핑하여 print 함
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)  # headers : 사람이 요청하는 것?

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

music_list = soup.select('#body-content > div.newest-list > div > table > tbody > tr')
for music in music_list:
    title = music.select_one('td.info > a.title.ellipsis').text.strip()
    artiest = music.select_one('td.info > a.artist.ellipsis').text
    if '19금' in title:
        title = '19금 ' + title.lstrip('19금').strip()
    rank = music.select_one('td.number').text[0:2].strip()
    print(rank, title, artiest)
  • 결과

profile
스스로 성장하는 개발자가 되겠습니다.

0개의 댓글