본문 바로가기

Python

[데이터분석] 1주차 강의노트

* 해당 자료는 스파르타코딩 데이터분석 종합반 수업 강의를 정리한 겁니다. 스파르타에서 제공한 데이터베이스를 사용했습니다.

맛보기

correlation 상관관계

- 인과관계와 상관관계는 다름

- 두 변수 관계가 '~할 확률(가능성)이 높다' 정도로 해석 가능

 

구글 Colab

- 구글에서 제공하는 개발 환경

- 인터넷과 구글 계정만 있으면 별도의 셋팅 없이도 언제든 파이썬을 사용할 수 있음

- 마지막 결과값만 출력하는 특성이 있다 -> 여러 개를 출력할 때는 print() 사용

- 출력 단축키는 shift + enter

- 주석을 작성할 때는 앞에 #를 붙임

 

파이썬 기초

1-1. 변수

- '=' 기호는 변수를 만드는 행위로, '할당한다'라고 표현

 

1-2. 자료형

1) 정수형

2) 실수형

3) 문자형

4) 리스트형

- 리스트의 순서는 0부터 시작한다. [0]은 첫 번째 값을 출력

- list에 뭔가를 추가할 때 append를 쓴다. ex) list1 = apppend(6)

- extend는 리스트와 리스트를 합칠 때 씀 ex) list1 = extend(list2) 

 

조건문/반복문

1) for문

- range(시작 숫자, 끝 숫자) : 끝 숫자는 포함하지 않고 숫자 리스트를 자동으로 만들어주는 함수

- 들여쓰기 즉 indent를 한 것만 반복된다

- 들여쓰기 단축키는 tab 또는 spacebar 4번

- for문 끝에 : (콜론) 붙여야 함

 

 

2) 비교연산자

 

3) if문, else문

if 1 == 1:
  # 조건문이 맞는 말일 때 실행되는 부분
  print('참이네요!')
else:
  # 조건문이 틀린 말일 때 실행되는 부분
  print('거짓이네요!')

 -> 출력값은 '참이네요!'

- for문처럼 if문의 조건에서 실행되는 코드는 들여쓰기(indentation) 후 작성해야 함

- else 뒤에는 어떠한 조건문도 붙이지 않는다

 

4) elif 

- 조건문이 한 개가 아닐 때 사용

- if와 else 사이에 들어감

- elif 뒤에는 조건문이 들어갈 수 있음. else 뒤에는 조건문 x. 바로 : 붙여야 함

- 조건문 뒤에는 반드시 : (콜론)이 들어가야 함

score = 85

if score > 90:
  print('학점이 A입니다')
elif score > 80:
  print('학점이 B입니다')
elif score > 70:
  print('학점이 C입니다')
else:
  print('학점이 F입니다')

 -> 이 경우 출력값은 '학점이 B입니다'

 

함수

def 함수이름(함수의 인자1, 함수의 인자2, ....):
	수행할 코드
	return 최종 결과
 
# 부피를 구하는 함수를 만든 것 뿐, 함수를 실행한 게 아님. 계산을 한 게 아니라 정의를 한 것!
def volume(width, height, length): # width, height, length 값이 있어야만 함수가 실행될 수 있다는 의미
  return width * height * length # return은 결과값을 나중에 또 사용할 수 있도록 하는 조치
print(volume(5, 8, 2))
 
- return을 해야 나중에 다른 변수에 결과값을 저장할 수 있음. print는 출력만 될 뿐 다른 변수에 저장을 할 수 있도록 돕는 명령어는 아니다.
 
ex) 직육면체 겉넓이 공식
def surface_area(width, height, length):
  return 2 * (width * height + width * length + height * length )
  print(surface_area(2, 4, 6)

 

판다스와 데이터프레임

패키지

- 누군가가 이미 만들어놓은 함수, 클래스 덩어리

- import 라는 명령어를 사용해서, 그저 가져오기만 하면 바로 사용 가능

- 판다스(Pandas)는 파이썬 데이터 분석을 위한 필수 패키지 중 하나

- 데이터프레임 : Pandas가 제공하는 표 (테이블) 형태의 구조. 행과 열로 구성된 2차원 테이블. 데이터를 읽어서 저장하고 연산하는 데 많이 사용

 
import pandas as '사용자가 정한 이름(pd)'
 
- as 는 약자를 설정하는 것
- 판다스에서는 주로 'pd'를 씀. 다른 설정을 쓰지 않음
 
# df란 이름의 데이터프레임을 생성합니다.
items = {'code' : [101, 102, 103, 104, 105, 106, 107, 108],
         '과목': ['수학', '영어', '국어', '체육', '미술', '사회', '도덕', '과학'],
         '수강생':[15, 15, 10, 50, 20, 50, 70, 10],
         '선생님': ['김민수','김현정','강수정', '이나리', '도민성', '강수진', '김진성', '오상배']}
df = pd.DataFrame(items)
df

- df.head(숫자) : 상위 (숫자)개의 행만 출력

- df.tail(숫자) : 하위 (숫자)개의 행만 출력

- df.sample(숫자) : 랜덤으로 (숫자)개의 행 출력

 

concat 함수

- concatenate : 합치다

- 데이터 프레임 여러 개를 합칠 때 사용

total_df = pd.concat([df, df2])
total_df

 

저장하기

total_df.to_csv('data.csv')

불러오기

new_df = pd.read_table('data.csv', sep=',')
new_df

- 맨 앞 열 unnamed 없애려면 저장을 할 때 'index = False'를 뒤에 붙이면 됨

total_df.to_csv('data.csv', index=False)

 

웹 이해하기

크롤링(crawling)

- 웹 페이지로부터 데이터를 추출하는 것

- 크롤링하는 소프트웨어는 '크롤러(crawler)'

 

HTML

- 웹 페이지는 HTML이라는 웹 문서로 구성돼 있다.

- HTML이란 텍스트 덩어리. 텍스트 덩어리로 이뤄진 웹 페이지를 예쁘게 만드는 건 CSS

- HTML은 태그(<></>)로 작성한다. 태그로 이름을 붙여야 문서를 가져올 때 'head에 있는 거 가져와'라고 할 수 있음

<div class="direct_area">
<a href="http://news.naver.com/" class="link_news" data-clk="newshome">네이버뉴스</a>
<a href="http://entertain.naver.com/home" class="link_direct" data-clk="entertainment">연예</a>
<a href="http://sports.news.naver.com/" class="link_direct" data-clk="sports">스포츠</a>
</div>

- div 태그. 안에 있는 세 개의 꺾쇄는 'div 태그 안에 있다'라고 표현함

 

선택자(Selector)

- 웹 페이지 안 특정 구성요소의 주소

- 선택자란 HTML 문서 내의 어떤 특정 태그들에 그룹이나 ID를 주는 기능

- 선택자는 주로 'id'와 'class'를 사용

- class는 속성이나 기능을 공유하는 유사한 성질의 객체들을 하나로 묶은 것

- class 내부에는 클래스 멤버와 기능의 구현 등 세부사항을 기술함

- 인스턴스(instance)는 클래스에 의해 만들어진 객체. ex) 클래스가 붕어빵 틀이라면 인스턴스는 붕어빵

* class와 인스턴스 더 알아보기

웹 스크래핑

패키지

- 이미 만들어져 있는 함수들의 묶음

- 파이썬에서는 '!pip install 패키지이름' 이라는 명령어를 통해 패키지 설치가 가능

- 설치 후에는 'from 패키지 이름 import 모듈'을 통해 패키지를 사용할 수 있음

- 이때 모듈이란 패키지 안에 저장된 함수 등을 말함

 

1) BeautifulSoup

- 파이썬으로 크롤링할 때 주로 사용하는 패키지는 BeautifulSoup. 이걸로 HTML이나 XML문서로부터 정보 추출이 가능함

- 인스턴스의 이름이 soup이므로 'soup.select(찾는 정보)'를 통해서 정보를 가져옴

  • soup.select('태그명') : 태그를 입력으로 사용할 경우
  • soup.select('.클래스명') : 클래스를 입력으로 사용할 경우
  • soup.select('#아이디') : ID를 입력으로 사용할 경우
  • soup.select('상위태그명 하위태그명') : 자손 관계 (어떤 태그 내부에 있는 모든 태그를 자손이라고 함)
  • soup.select('상위태그명 > 하위태그명') : 자식 관계 (어떤 태그 내부에 있는 태그 중 바로 한 단계 아래에 있는 태그를 자식이라고 함)
  • soup.태그명.get('속성명') : 해당 속성의 값을 가져옴. 속성이란 aaa = 'bbb' 형식 -> get('aaa') = bbb를 가져온다

2) Newspaper3k 

- 뉴스 데이터를 크롤링하기 위한 패키지

- 인터넷 뉴스 기사의 url을 전달해주면 뉴스 기사의 제목과 텍스트를 추출함

# newspaper라는 패키지로부터 Article이라는 모듈을 임포트
from newspaper import Article
# 파싱할 뉴스 기사 주소
url = https://n.news.naver.com/mnews/article/030/0002881076?sid=101
# 언어가 한국어이므로 language='ko'로 설정
article = Article(url, language='ko')
# 뉴스 제목과 본문을 찾아내는 분석!
article.download()
article.parse()

 

# 뉴스 제목 추출
print(article.title)
# 뉴스 본문 추출
print(article.text)

 

뉴스 크롤링

url

- 웹페이지에 접근하는 주소

- 네이버 뉴스의 경우 url 자체에 정보값이 담겨 있음 -> 특정 정보를 크롤링하려면 url 먼저 분석해야 한다

https://news.naver.com/main/list.nhn?mode=LSD&mid=sec&sid1=105&date=20200430&page=2

- &sid1=숫자 : 숫자는 뉴스가 속한 카테고리 번호. 105는 IT/과학

- &date=날짜 : 게시 날짜

- &page=번호 : 몇 페이지인지

- 작은 사각형이 큰 사각형의 자손들. 즉, 내부 태그들

- 이 구조를 파악하면 BeautifulSoup의 select()를 사용해 url을 받아올 수 있음

- 개발자 도구를 여는 단축키 : F12(window), Command + Option + I (Mac)

 

네이버 뉴스 크롤링 순서

* 기초 작업 : 4개의 패키지를 임폴트 해준다

import requests
import pandas as pd
from newspaper import Article
from bs4 import BeautifulSoup
  1. 네이버 뉴스 페이지에서, 각각의 뉴스가 가진 URL을 리스트 형태로 만들어서 저장해놓는다.
  2. 각각의 뉴스가 가진 URL 에 접근하면 제목과 본문 내용이 표시가 될텐데, 그 제목과 본문 내용을 newspaper3k 패키지를 이용해서 크롤링을 진행한다.
  3. 크롤링을 할 때마다 크롤링 되어온 내용을 데이터프레임에 계속 이어붙인다.
  4. 크롤링이 끝났다면, 정보가 저장되어있는 데이터프레임을 csv 파일로 저장한다.

 

변수 이용해 url 변환하기

# page_num은 페이지번호, code는 카테고리, date는 날짜
page_num = 1
code = 101
date = 20200506

- 문자열은 더하면 이어붙이기가 된다
- 그러나, 문자열과 숫자는 더할 수 없다 -> 숫자를  str()함수를 이용해 문자열로 바꿔주는 작업을 해야한다.

url = 'https://news.naver.com/main/list.nhn?mode=LSD&mid=sec&sid1='+str(code)+'&date='+str(date)+'&page='+str(page_num) 
print(url)

 

HTML 소스 코드 가져오기

- requests 패키지의 get 모듈 이용

- Header에 User Agent 정보를 넣어서 크롤링 차단 우회하기 (참고)

- 유저 정보를 추가한 경우에는 url 뒤에 headers=headers 추가

news = requests.get(url, headers=headers)
news.content

- 페이지 수, 카테고리, 날짜는 설정해야 함. urlist= []는 기사의 url을 저장하기 위한 빈 리스트

# 크롤링할 페이지 수, 카테고리, 날짜
def make_urllist(page_num, code, date): 
  # 각각 기사들이 가진 url을 저장하기 위한 빈 리스트를 하나 만들어놓는다.
  urllist= []

- 1페이지부터 page_num까지 정해진 페이지만큼 같은 행위를 반복하기 때문에 range함수를 넣은 for문을 써준다

for i in ragne(1, page_num + 1):

- 함수 입력으로 된 변수들로 주소를 조합한다. 

url = 'https://news.naver.com/main/list.nhn?mode=LSD&mid=sec&sid1='+str(code)+'&date='+str(date)+'&page='+str(i)

- requets 패키지의 모듈(함수)을 호출하고, 'import 패키지이름' 으로 임포트했다면 '패키지이름.모듈이름' 으로 모듈을 호출

news = requests.get(url, headers=headers)
news.content

- BeautifulSoup 모듈로 HTML 페이지 분석

soup = BeautifulSoup(news.content, 'html.parser')

# 해당 페이지에 있는 각각의 뉴스를 news_list 라는 리스트로 저장
# type06_headline이라는 ul 태그 안에 li 태그 안에 dl 태그 안에 문서의 세부 정보 즉, 기사의 url 정보가 담겨 있었음
 news_list = soup.select('.type06_headline li dl')
    news_list.extend(soup.select('.type06 li dl'))
-> 띄어쓰기 자체가 내부에 있는 태그를 갖고 오라는 의미
-> extend 함수는 리스트를 이어 붙일 때 사용
 
- 뉴스 리스트에 있는 각 뉴스로부터 a 태그인 <a href ='주소'> 에서 '주소'만을 가져온다.
for line in news_list:
        urllist.append(line.a.get('href'))
  return urllist

- 헷갈리지 않게 code를 key, 실제 카테고리를 value로 가지는 dictionary를 만들자

- 이제 idx2word라는 딕셔너리를 통해서 이 코드 번호가 무슨 카테고리인지 바로 확인 가능

# 파이썬의 dictionarys는 선언 할 때는 'key' : 'value'의 형태로 선언
idx2word = {'101' : '경제', '102' : '사회', '103' : '생활/문화', '105' : 'IT/과학'}

# 선언 후에는 key 값을 넣으면 맵핑되어져 있는 value 값이 리턴됨
idx2word['101']

- 무언가를 저장하려면 반드시 빈 리스트 또는 빈 데이터베이스가 필요. ex) text_list = []

# url과 카테고리를 알려주면 url로부터 본문을 추출하여 데이터프레임을 생성하는 함수.
def make_data(urllist, code):
  # 본문을 저장하기 위한 빈 리스트를 만들어놓는다.
  text_list = []
  
  for url in urllist:
    article = Article(url, language='ko')
    article.download()
    article.parse()
    text_list.append(article.text)

  df = pd.DataFrame({'news': text_list})
  df['code'] = idx2word[str(code)] 
  return df

- 여러 카테고리 뉴스를 크롤링 할 때는 카테고리 코드를 저장한 리스트를 만들어 주면 됨

code_list = [102, 103, 105]

- make_total_data 함수를 만들어서 make_urllist 함수와 make_data 함수를 호출하고 각 코드의 뉴스를 수집해서 데이터프레임에 저장한다.

df = make_total_data(2, code_list, 20200506)

 

음원 사이트 순위 크롤링

  • 지니뮤직의 1~50위 곡 스크래핑하기
  • 순위, 곡 제목, 가수 순으로 스크래핑

- BeautifulSoup4(bs4) 설치 후 BeautifulSoup 모듈 임포트

- BeautifulSoup 인스턴스 생성. 두 번째 매개변수는 분석할 분석기(parser)의 종류. 이 경우 'html.parser'

- soup.select 함수 활용해서 <tr> 태그 전체를 가져오고 for문을 이용해서 곡 정보를 하나씩 print

- selector 복사해서 바로 붙여 넣기

trs = soup.select('#body-content > div.newest-list > div > table > tbody > tr:nth-child(1)')

- tr:nth-child(1)은 tr이 붙은 요소 중에서 첫 번째 요소를 가져오라는 의미

- but, 모든 요소를 가져와야 하므로 tr만 남긴다

for tr in trs:
  title = tr.select_one('td.info > a.title.ellipsis').text
  print(title)

- tr 안에서 찾는 거니까 'td.info' 앞에 나온 건 중복되는 거니까 지워도 됨

- .text를 붙이면 a태그는 지워지고 문자에 해당하는 내용만 남는다.

- 결과값에서 공백이 너무 많을 때는 strip() 함수를 쓰면 공백이 다 지워짐. strip은 띄어쓰기 제거하는 함수

for tr in trs:
  title = tr.select_one('td.info > a.title.ellipsis').text.strip()
  print(title)

- 순위(rank)와 가수(artist)도 동일한 방식으로 하되, 순위에서 첫번째 숫자값만 남기려면 text[0:2]

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

 

회고

KEEP - 정리하면서 내 언어로 써야 이해됨
- 실습은 반드시 직접 해볼 것!
PROBLEM - 한 번에 다 들어야 흐름이 안 끊긴다. 시간을 들여서 한번에 몰아쳐야..
- 알파벳 철자 틀리는 경우가 은근 많다
- 코드 스니펫 복붙만 하지 말고 왜 그게 쓰이는지 이해해야 함
TRY 참고자료로 제공되는 wiki 문서 검토