03. 웹 개발 종합반 3주차

코이그·2023년 2월 18일

항해99

목록 보기
3/54

python

가상환경 사용법: python3 -m venv venv -> venv 인터프리터 선택 -> 터미널 띄우기

웹 스크래핑 (크롤링)

웹 스크래핑: 웹 페이지로부터 원하는 정보를 추출하는 기법.
API가 별도로 제공되지 않지만 웹 페이지로는 정보가 제공되는 서비스에서 웹 스크래핑을 이용하여 원하는 정보를 획득할 수 있음.

기본 세팅: 가상환경 상태에서 pip install bs4. (Beautiful Soup)

사용 예시 코드)

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

# 웹에서 원하는 엘리먼트에 우클릭, 검사 -> copy -> copy selector
a = soup.select_one(
    '#old_content > table > tbody > tr:nth-child(3) > td.title > div > a')

# a에 담긴 <a href="/movie/bi/mi/basic.naver?code=171539" title="그린 북">그린 북</a> 중에 텍스트 부분만 가져오기
print(a.text)
# a에 담긴 <a href="/movie/bi/mi/basic.naver?code=171539" title="그린 북">그린 북</a> 중에 href 부분만 가져오기
print(a['href'])

# old_content > table > tbody > tr:nth-chid(2)
# old_content > table > tbody > tr:nth-chid(3)
trs = soup.select('#old_content > table > tbody > tr')  # tr들이 리스트로 저장됨

for tr in trs:
	# tr에서 <a href="/movie/bi/mi/basic.naver?code=OOOOOO" title="OOO">OOO</a> 가져오기
    title = tr.select_one('td.title > div > a')
    if title is not None:
        #old_content > table > tbody > tr:nth-child(2) > td:nth-child(1) > img
        ranking = tr.select_one('td').img['alt']
        #old_content > table > tbody > tr:nth-child(2) > td.point
        point = tr.select_one('td.point').text
        print(ranking, title.text, point) # 전체 제목들 가져오기

Database

정의

데이터베이스: 통합하여 관리되는 데이트의 집합체.

  • 중복된 데이터 삭제
  • 자료의 구조화
  • 효율적인 처리

데이터베이스는 응용 프로그램과는 다른 별도의 미들웨어에 의해 관리됨.
이러한 미들웨어를 데이터베이스 관리 시스템(DBMS: Database Management System)이라고 함.

특징

  1. 사용자의 질의에 대해 즉작적 처리와 응답이 이루어짐.
  2. 생성, 수정, 삭제를 통해 항상 최신 데이터 유지.
  3. 사용자가 원하는 데이터를 동시에 공유할 수 있음.
  4. 사용자가 원하는 데이터를 주소가 아닌 내용에 따라 참조할 수 있음.
  5. 응용 프로그램과 DB는 독립되어 있으므로 데이터의 논리적 구조와 응용 프로그램은 별개로 동작됨.

SQL

SQL (Structured Query Language): DB에서 데이터를 정의, 조작, 제어하기 위해 사용되는 언어.

SQL 구분

  1. DDL (Data Definition Language)
    • DB나 테이블 등을 생성, 삭제, 혹은 구조 변경을 위한 명령어 (CREATE, ALTER, DROP)
  2. DML (Data Manipulation Language)
    • DB에 저장된 데이터의 처리, 조회, 검색을 위한 명령어 (INSERT, UPDATE, DELETE, SELECT 등)
  3. DCL (Data Control Language)
    • DB에 저장된 데이터의 관리를 위해 데이터의 보안성 및 무결성 등을 제어하는 명령어 (GRANT, REVOKE 등)

NoSQL

No - Not Only.

SQL vs NoSQL

SQL의 장점:

  • 틀이 정해져 있음.
  • 데이터의 일관성 / 분석에 용이.
  • 빠름.

NoSQL의 장점:

  • 틀이 없기 때문에 자유로운 형태로 데이터 관리 가능.

MongoDB

시작하기

  1. 회원가입
  2. Build a Database
  3. CREATE (FREE)
  4. Create Cluster
  5. Username, Password (sparta, test) -> Create User
  6. IP Address (0.0.0.0) -> Finish and Close
  7. Go to Database

python <-> mongoDB

기본 세팅: 가상환경 상태에서 pip install pymongo dnspython
pymongo 기본 코드)

from pymongo import MongoClient
client = MongoClient('mongodb+srv://sparta:test@cluster0.gsiejtz.mongodb.net/?retryWrites=true&w=majority') # mongoDB에서 connect -> connect your application -> driver: python 3.6 or later -> copy
db = client.dbsparta

mongoDB의 데이터: 딕셔너리

doc = {
	'name': '영수',
    'age': 24
}

데이터 삽입

db.users.insert_one(doc) # users: 데이터베이스 (dbsparta) 내부에 콜렉션이라는 단위
db.users.insert_one({'name': 'bobby', 'age': 21})

=> pymongo.errors.ServerSelectionTimeoutError

데이터 검색/추출 (일괄)

all_users = list(db.users.find({}, {'_id': False})) # 데이터마다 _id값이 자동으로 생기는데 데이터 추출 시 누락시킬 수 있는 방법

for user in all_users:
	print(user) # print(user['name'] / user['age'])

데이터 검색/추출 (개별)

user = db.user.find_one({}) # 매개변수로 딕셔너리 짝을 넣어 원하는 조건의 데이터 추출 가능 (예: {'name': 'bobby'} -> name이 bobby인 데이터 추출
print(user)

데이터 수정

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

데이터 삭제

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

웹 스크래핑 결과 저장

# 위의 코드에 이어서
for tr in trs:
	# tr에서 <a href="/movie/bi/mi/basic.naver?code=OOOOOO" title="OOO">OOO</a> 가져오기
    title = tr.select_one('td.title > div > a')
    if title is not None:
        title = title.text
        #old_content > table > tbody > tr:nth-child(2) > td:nth-child(1) > img
        rank = tr.select_one('td').img['alt']
        #old_content > table > tbody > tr:nth-child(2) > td.point
        point = tr.select_one('td.point').text

        doc = {
            'title': title,
            'rank': rank,
            'point': point
        }

        db.movies.insert_one(doc) # movies라는 콜렉션에 doc 저장

실습

1. '가버나움'의 평점 가져오기

from pymongo import MongoClient
import certifi, requests

ca = certifi.where()

# mongoDB에서 connect -> connect your application -> driver: python 3.6 or later -> copy
client = MongoClient(
    'mongodb+srv://sparta:test@cluster0.gsiejtz.mongodb.net/?retryWrites=true&w=majority', tlsCAFile=ca)
db = client.dbsparta

point = db.movies.find_one({'title': '가버나움'})['point']

print(point)

2. '가버나움'의 평점과 같은 평점의 영화 제목들 가져오기

from pymongo import MongoClient
import certifi
import requests

ca = certifi.where()

# mongoDB에서 connect -> connect your application -> driver: python 3.6 or later -> copy
client = MongoClient(
    'mongodb+srv://sparta:test@cluster0.gsiejtz.mongodb.net/?retryWrites=true&w=majority', tlsCAFile=ca)
db = client.dbsparta

point = db.movies.find_one({'title': '가버나움'})['point']

movies = db.movies.find({'point': point})

for movie in movies:
    print(movie['title'])

3. '가버나움'의 평점을 0으로 수정하기

from pymongo import MongoClient
import certifi
import requests

ca = certifi.where()

# mongoDB에서 connect -> connect your application -> driver: python 3.6 or later -> copy
client = MongoClient(
    'mongodb+srv://sparta:test@cluster0.gsiejtz.mongodb.net/?retryWrites=true&w=majority', tlsCAFile=ca)
db = client.dbsparta

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

print(db.movies.find_one({'title': '가버나움'}))

숙제

from bs4 import BeautifulSoup  # 데이터를 가져오기 위한 라이브러리
import requests  # 웹에 접속하기 위한 라이브러리

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)
songs = soup.select('#body-content > div.newest-list > div > table > tbody > tr')

for song in songs:
    rank = song.select_one('td.number').text[0:2]
    title = song.select_one('td.info > a.title.ellipsis').text.strip()
    artist = song.select_one('td.info > a.artist.ellipsis').text.strip()
    
    print(rank, title, artist)

TIL

python <-> mongoDB에서 발생한 오류

윈도우 데스크탑에서 실습했을 때는 오류가 뜨지 않았지만 맥북에서 실습을 진행했을 때 위 오류가 떴었다. week 03를 데스크탑에서 진행했고 week 04를 맥북에서 진행했을 때 저 오류가 떴기 때문에 뭔가 놓친 부분이 있나 싶어서 week 03 부분을 맥북에서 다시 실습해보았다. 하지만 똑같이 오류가 떴었고 오류메세지를 검색한 결과 이미 이전에 수강생 분께서 질문한 글이 있어서 들어가봤더니 다양한 오류메세지들과 해당 해결 방법이 나와있었다. 검색의 중요성을 다시 한 번 깨달았다.

  • 추가로 윈도우와 맥을 동기화(?)하기 위해 iCloud+를 결제하고 VSCode의 모든 프로젝트를 공유하기로 했다.

pymongo.errors.ServerSelectionTimeoutError 에러.
이유: 사용하고 있는 인터넷 환경에 따라 보안 관련 추가 설정을 해주어야할 때가 있음.
해결 방법)
1. certifi 패키지 설치 (pip install certifi).
2. import certifi, ca = certifi.where() MongoClient 함수의 2번째 매개변수로 tlsCAFile=ca 추가.

from pymongo import MongoClient
**import certifi**

**ca = certifi.where()**

client = MongoClient('mongodb+srv://sparta:test@cluster0.gsiejtz.mongodb.net/?retryWrites=true&w=majority', **tlsCAFile=ca**) # mongoDB에서 connect -> connect your application -> driver: python 3.6 or later -> copy
db = client.dbsparta

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

그렇다면 certifi는 정확히 무얼 하는 패키지인가?

PyPI에서의 certifi 패키지에 대한 설명이다.

Certifi provides Mozilla’s carefully curated collection of Root Certificates for validating the trustworthiness of SSL certificates while verifying the identity of TLS hosts. It has been extracted from the Requests project.

where() 함수는 설치되어 있는 CA(Certificate Authority)를 참조할 때 사용한다.

profile
COYG🔴⚪

0개의 댓글