데이터 분석 - 1주차 수업

차승준·2022년 9월 15일
0

DBeaver와 달리, 따로 프로그램을 설치할 필요없이 구글 서비스 중 하나를 그대로 이용하면 된다고 한다.

Colab 접속 방법

연속 접속 제한시간이 1시간 반이고, 하루 12시간 밖에 접속하지 못하지만 충분하다.
구글로 로그인해서 들어가면 코드를 작성할 수 있다.

Control + enter : 코드 작동
print('hello world') : ' ' 안에 있는 문자열을 출력

드라이브에 해당 파일이 자동으로 저장된다.

**파이썬 기초**

변수와 기본연산

a = 3      # 3을 a에 넣는다
b = a      # a를 b에 넣는다
a = a + 1  # a+1을 다시 a에 넣는다

num1 = a*b # a*b의 값을 num1이라는 변수에 넣는다
num2 = 99 # 99의 값을 num2이라는 변수에 넣는다

# 변수의 이름은 마음대로 지을 수 있음!
# 진짜 "마음대로" 짓는 게 좋을까? var1, var2 이렇게?

식 다 써좋고 변수 선언한 뒤, 마지막에 그 변수를 적어넣어야만 출력된다는 것이 좀 불편하다. 계산기는 식만 쓰고 = 치면 바로 답이 나오는데.

리스트형

a_list = ['사과','배','감','수박']	#순서대로 0, 1, 2, 3

a_list[0]	# 사과가 출력.

a_list.append('귤')	# 자동으로 마지막에 붙음.

a_list[4]	# 귤이 출력.

중간 순서에 끼워 넣을 수 없나 했지만, 그런건 안 가르쳐주었다.

딕셔너리 형

a_dict = {'name':'bob','age':21}

a_dict['age']	# 21이 출력.

a_dict['height'] = 178

a_dict	# {}까지 그대로 나옴

리스트와 딕셔너리형의 조합

people = [{'name':'bob','age':20},{'name':'carry','age':38}]

# people[0]['name']의 값은? 'bob'
# people[1]['name']의 값은? 'carry'

person = {'name':'john','age':7}
people.append(person)

# people의 값은? [{'name':'bob','age':20}, {'name':'carry','age':38}, {'name':'john','age':7}]
# people[2]['name']의 값은? 'john'

슬슬 복잡해지지만, 딕셔너리는 반드시 {}만 사용한다는 것을 기억만 해두면 괜찮을 듯 하다.

함수

def f(x):
	return 2*x+3

혹은

def sum(a,b):
	return a+b

def mul(a,b):
	return a*b

result = sum(1,2) + mul(10,10)

# result라는 변수의 값은? 103

조건문

if age > 20:
	print('성인입니다')    # 조건이 참이면 성인입니다를 출력
else:
	print('청소년이에요')  # 조건이 거짓이면 청소년이에요를 출력

is_adult(30)

#성인입니다, 라고 출력된다.

반복문

ages = [20,30,15,5,10]

for age in ages:
	print(age)

### ages라는 리스트 안의 요소들을 age라고 정의하면서, 반복해서 print 출력한다. 줄 바꿔가며.

for age in ages:
	if age > 20:
		print('성인입니다')
	else:
		print('청소년이에요')
        
### 요소들이 그대로 print되는 대신, 요소가 20보다 크냐 작냐에 따라 print 되는 문구가 바뀐다.        

조건문 + 함수 + 반복문을 한번에 사용해본다면?

def check_adult(age):
	if age > 20:
		print('성인입니다')
	else:
		print('청소년이에요')

ages = [20,30,15,5,10]

for age in ages:
	check_adult(age)

def로 함수명이 check_adult인 함수를 선언(:)한 뒤, 그 함수 안에 조건문을 포함시키고 ages 리스트형 안에 있는 요소들을(암만 생각해도 따로 설명이 없었지만 ages라고 리스트를 하면 자동으로 age가 요소명이 되는 듯)반복물을 통해 check_adult 함수에 집어넣어 결과를 뽑아낸다.

SQL과 달리 벌써부터 복잡해진다. 다음부터 응용에 들어가는데.

업무자동화 - 스크래핑 실습

네이버 뉴스 긁어오기
아래의 주소에서 마우스 우클릭>검사를 통해 정보를 가져온다.
삼성전자 검색

HTML : 웹페이지를 구성하는 기복적인 뼈대. '태그'라는 것이 존재하며 이를 기준으로 Colab에서 기사를 긁어온다.

라이브러리 설치하기

pip install bs4 requests

이것은 한번 실행하면 더 실행할 필요가 없어 지워도 된다고 한다. . . 맞나? 늦게 정리해서 기억이 가물가물하네(메모의 중요성).

크롤링 기본 코드와 select_one, select

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://search.naver.com/search.naver?where=news&ie=utf8&sm=nws_hty&query=삼성전자',headers=headers)

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

###requests 로 정보를 가져와서 → BeautifulSoup으로 분석하기 좋게 만든 것이다.

a = soup.select_one('#sp_nws1 > div.news_wrap.api_ani_send > div > a')
a['href']
a.text

### a 태그의 'href'란 태그의 내용만 출력(href에는 링크가 있다).
### a 태그의 text 형식만 출력.

마지막 두줄은 print()로 가두어야만 링크 주소와 텍스트 내용이 같이 출력된다.

_기사 제목 가져오기_
lis = soup.select('#main_pack > section > div > div.group_news > ul > li')

ul라는 태그 안에 li태그가 잔뜩 있다. 해서 soup.select()안에 li의 우클릭>copy selet한 것을 넣는다. 그리고 그 안에서 기사가 있는 a태그를 가져온다.

lis[0].select_one('a.news_tit')	#class에 'news_tit'가 있는 a라는 뜻.

a태그 전부 긁고 싶다면 반복문으로 정리한다.

lis = soup.select('#main_pack > section > div > div.group_news > ul > li')

for li in lis:
  a = li.select_one('a.news_tit')
  print(a.text, a['href'])

윗 코드의 select문 대신 반복문으로 정리한 코드를 넣으면,

전기 먹는 공룡 삼성전자, 탄소 중립·RE100 뒤늦게 동참 https://imnews.imbc.com/replay/2022/nwdesk/article/6408118_35744.html
삼성전자, 2050년 탄소중립·RE100 가입 선언… 7兆 투자해 환경경영 달성 https://biz.chosun.com/it-science/ict/2022/09/15/2FXXPFQ3BZDZNLCCTT7YUUW47Q/?utm_source=naver&utm_medium=original&utm_campaign=biz
삼성전자, 7대 제품 소비전력 30% 낮춘다 http://www.newsis.com/view/?id=NISX20220915_0002013567&cID=13001&pID=13000
돈 들어도 친환경 간다…삼성, 탄소중립 대전환 선언 https://www.wowtv.co.kr/NewsCenter/News/Read?articleId=A202209150245&t=NNv
삼성전자 한종희·경계현 "탄소중립 위해 초격차 기술혁신 속도" https://www.yna.co.kr/view/AKR20220915148300003?input=1195m
한전, 삼성전자와 손잡고 전력공급 인프라 확충 나서 http://www.edaily.co.kr/news/newspath.asp?newsid=02938886632460448
[단독] 삼성전자, 공법 바꾸고도 불량 세탁기 1만 4천대 팔아 https://news.sbs.co.kr/news/endPage.do?news_id=N1006898056&plink=ORI&cooper=NAVER
삼성전자 “2050 탄소중립 실현…친환경 대전환” http://news.heraldcorp.com/view.php?ud=20220915000483
삼성전자 ‘RE100’ 선언…재생에너지 조달은 어떻게? https://news.kbs.co.kr/news/view.do?ncd=5556492&ref=A
한화솔루션, 삼성전자와 유럽 에너지 위기 해결 맞손 http://news.mk.co.kr/newsRead.php?no=814998&year=2022

이렇게 출력된다.

함수를 통해 특정 키워드(삼성전자)만 바꿔서 다른 뉴스를 볼 수 있다.

def get_news(keyword):
  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(f'https://search.naver.com/search.naver?where=news&ie=utf8&sm=nws_hty&query={keyword}',headers=headers)

  soup = BeautifulSoup(data.text, 'html.parser')
  lis = soup.select('#main_pack > section > div > div.group_news > ul > li')

  for li in lis:
    a = li.select_one('a.news_tit')
    print(a.text, a['href'])

get_news('삼성전자'), 라고 치면 위의 함수가 실행된다.

이렇게 스크립을 긁으면 이제 엑셀로 저장하고자 한다.

엑셀 - openpyxl 라이브러리 설치하기

pip install openpyxl

엑셀 파일 만들기

from openpyxl import Workbook

wb= Workbook()
sheet = wb.active

sheet['A1'] = '안녕하세요!'

wb.save("샘플파일.xlsx")
wb.close()

이러면 왼쪽 상단의 맨 아래 '파일' 아이콘을 누르면, 샘플 파일이라는 이름으로 저장된 엑셀 파일을 확인할 수 있다.
A1 시트에 '안녕하세요!'가 적혀있다.

반대로, 엑셀 파일을 올려서 읽어보자
엑셀 파일 읽기

import openpyxl
wb = openpyxl.load_workbook('샘플파일.xlsx')
sheet = wb['Sheet']

sheet['A1'].value	#A1 위치의 시트 읽기
for row in sheet.rows:
  print(row[0].value, row[1].value, row[2].value)	#모든 시트 읽기

첫 줄을 빼고 읽고 싶다면 sheet 선언문과 A1 위치 시트 일기 명령문 사이에

new_rows = list(sheet.rows)[1:]

를 넣으면 된다.

. . . 슬슬 머리가 복잡하다. 같은 row인데 어느 것은 가로 줄이고, 어니 것은 세로줄이니 원.
아니 row를 대체 어디서 가져온거지?
대부분 기본 코드 그대로 긁어와서 그냥 그때그때 찾아보는 수 밖에 없다.

이제 엑셀문을 통해기사를 스크래핑 결과를 저장해보자.

import requests
from bs4 import BeautifulSoup

from openpyxl import Workbook

wb = Workbook()
sheet = wb.active

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(f'https://search.naver.com/search.naver?where=news&ie=utf8&sm=nws_hty&query=삼성전자',headers=headers)

soup = BeautifulSoup(data.text, 'html.parser')
lis = soup.select('#main_pack > section > div > div.group_news > ul > li')

for li in lis:
  a = li.select_one('a.news_tit')
  row = [a.text, a['href']]
  sheet.append(row)

wb.save("샘플파일.xlsx")
wb.close()

더 나아가 특정 keyword에 대한 기사를 스크립하여 엑셀로 저장하는 함수로 만들고,

def make_news_excel(keyword):
  wb = Workbook()
  sheet = wb.active

  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(f'https://search.naver.com/search.naver?where=news&ie=utf8&sm=nws_hty&query={keyword}',headers=headers)

  soup = BeautifulSoup(data.text, 'html.parser')
  lis = soup.select('#main_pack > section > div > div.group_news > ul > li')

  for li in lis:
    a = li.select_one('a.news_tit')
    row = [a.text, a['href']]
    sheet.append(row)

  wb.save(f"{keyword}.xlsx")
  wb.close()

반복문으로 여러 개의 파일을 저장할 수 있다.

keywords = ['삼성전자','LG전자','현대자동차','SK']

for keyword in keywords:
  make_news_excel(keyword)

날짜도 추가해보다.

from datetime import datetime

datetime.today().strftime("%Y-%m-%d")

한 다음에

def make_news_excel(keyword):
  wb = Workbook()
  sheet = wb.active

  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(f'https://search.naver.com/search.naver?where=news&ie=utf8&sm=nws_hty&query={keyword}',headers=headers)

  soup = BeautifulSoup(data.text, 'html.parser')
  lis = soup.select('#main_pack > section > div > div.group_news > ul > li')

  for li in lis:
    a = li.select_one('a.news_tit')
    row = [a.text, a['href']]
    sheet.append(row)

  today = datetime.today().strftime("%Y-%m-%d")

  wb.save(f"{today}_{keyword}.xlsx")
  wb.close()

특정 폴더(명:news)에 저장하고 싶다면 아래처럼 바꾸자.

 wb.save(f"news/{today}_{keyword}.xlsx")
  wb.close()

파일이 너무 많으면? 압축해서 다운 받자!

!zip -r /content/files.zip /content/news

압축파일이 엑셀처럼 저장되어 있을 것이다.

추가.
파일명 전체 바꾸기

import os

path = '/content/news'
names = os.listdir(path)

for name in files:
  print(name)

파일명을 테스트하고

name = '2022-04-04_삼성SDI.xlsx'
name.split('.')[0] + '(뉴스).xlsx'

파일명을 변경한다.

import os

path = '/content/news'
names = os.listdir(path)

for name in names:
  new_file = name.split('.')[0] + '(뉴스).xlsx'
  os.rename(path+'/'+name,path+'/'+new_file)

정리하면 이렇게 되고.

_이미지 다운받기_
import urllib.request

url = 'https://ssl.pstatic.net/imgfinance/chart/item/area/year3/005930.png'
urllib.request.urlretrieve(url, "samsung.jpg")

005930.png 숫자에 따라 다른 이미지를 받을 수 있다.
이것은 종목코드라고 불리며, 해서 이 부분을 변수로 바꾸고

import openpyxl
import urllib.request

wb = openpyxl.load_workbook('관리종목.xlsx')
sheet = wb['종목']

new_rows = list(sheet.rows)[1:]

for row in new_rows:
  url = f'https://ssl.pstatic.net/imgfinance/chart/item/area/year3/{row[1].value}.png'
  urllib.request.urlretrieve(url, f"imgs/{row[0].value}.png")

이와 같이 코드를 짠다.

profile
멋진 개발자가 되고 싶어요.

0개의 댓글