왕초보 시작반 3주차

이지훈·2021년 7월 24일
0

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

파이썬은 매우 직관적인 언어!

들여쓰기에도 주의해야한다.

변수, 자료형은 1주차에 기록한 것과 같음

함수

수학문제에서
f(x) = 2*x+3
y = f(2)
y의 값은? 7
파이썬에서
def f(x):
	return 2*x+3
print(f(2))
입력시 값은 7

반복문
파이썬에서의 반복문은, 리스트의 요소들을 하나씩 꺼내쓰는 형태입니다.

fruits = ['사과','배','감','귤']

for fruit in fruits:
	print(fruit)

# 사과, 배, 감, 귤 하나씩 꺼내어 찍힙니다.
# 무조건 리스트와 함께 쓰입니다.

가상환경

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

== 서로 다른 프로젝트에서 서로 다른 패키지를 사용할 경우에
가상환경을 통해 프로젝트별로 영향을 받지 않는 환경을 만들 수 있음

웹스크래핑(크롤링)

시작하기에 앞서 크롤링 기본 세팅을 해준다.

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의 차이

select로 가져올 경우 결과값이 리스트로 저장된다.
select_one으로 가져올 경우 문서의 처음부터 시작하여 조건에 맞는 하나를 찾게 된다.

뒤에 .text를 쓸 경우
select는 여러개의 값이 있기 때문에 for문을 통해 접근 후 써줘야 하며
select_one의 경우 하나만 가져오기 때문에 바로 .text를 쓸 수 있다.


크롤링 연습문제
본인이 짠 완성 코드

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

튜터님의 경우 마지막 rank['alt']에서 ['alt']를
rank = tr.select_one('td:nth-child(1) > img')뒤에 붙여주고

prink(rank, title, star)로 좀 더 깔끔한(?) 코드를 짜셨다.


데이터베이스(DB)의 종류

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

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

pymongo 코드

# insert 데이터 넣기 / find 찾기 / update 업데이트 / delete 삭제

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

웹스크래핑 퀴즈

Q1.
martrix = db.movies.find_one({'title':'매트릭스'})
print(martrix['star'])

Q2.
same_rank = list(db.movies.find({'star':'9.39'},{'_id':False}))
for name in same_rank:
    print(name['title']) 
=====================
{'star':'9.39'}라고 입력하기보다 Q1. 값의 martrix['star']를 변수(samestar) 로 지정해주고 {'star':samestar}로 했으면 더 좋았을듯하다. 
9.39의 값은 바뀔 수가 있으므로!

들여쓰기를 제대로 못하고, for문 사용하는 것을 까먹어서 헤맸다.

Q3.
db.movies.update_one({'title':'매트릭스'},{'$set':{'star':'0'}})
=====================

3주차 숙제

genie = soup.select('#body-content > div.newest-list > div > table > tbody > tr')

for top50 in genie:
    rank = top50.select_one('td.number').text.strip()
    title = top50.select_one('td.info > a.title.ellipsis').text.strip()
    artist = top50.select_one('td.info > a.artist.ellipsis').text
    print(rank, title, artist)

여기까지 해보고 rank 부분이 strip()으로도 안되는 것을 알아서 이것저것 찾아보았다.
자식태그 제거를 참고한 뒤
나도 span 태그부터 없애면 되겠다 해서
rank = top50.selectone('td.number').span.decompose().text를 붙여 사용해봤는데
_AttributeError: 'NoneType' object has no attribute 'text'
에러가 나왔고 이는 검색되어지는 값이 없으면 나오는 에러라고 한다.
그래서 rank = top50.select_one('td.number').span.decompose() 까지만 적고 결과값을 보니 None만 뜨는 것이었다.

후에 뭐라고 찾아봐야할지 몰라서 해설영상을 봤는데
"파이썬 문자열 자르기"라고 검색하는 걸 보고 찾아봤다.
...띠용..

50은 2개의 숫자니까 .text[0:2]로 0번째에서 2번째까지 잘라줬는데 1~9까지는 공백이 생겨서
뒤에 .strip을 붙여 공백을 없애줬다.

최종코드

genie = soup.select('#body-content > div.newest-list > div > table > tbody > tr')

for top50 in genie:
    rank = top50.select_one('td.number').text[0:2].strip()
    title = top50.select_one('td.info > a.title.ellipsis').text.strip()
    artist = top50.select_one('td.info > a.artist.ellipsis').text
    print(rank, title, artist)
profile
기록!

0개의 댓글