파이썬을 이용한 머신러닝, 딥러닝 실전 개발 입문

Stella Kim·2021년 7월 20일
0

[책] Deep Learning

목록 보기
2/2
post-thumbnail

Deep Learning에 대해 공부하며 읽었던 책의 주요 내용을 요약하였다.

<책 정보>

제목: 파이썬을 이용한 머신러닝, 딥러닝 실전 개발 입문 _ 웹 크롤링과 스크레이핑부터 머신러닝.딥러닝까지 체계적으로 배우기
출간일자: 2017
저자: 쿠지라 히코우즈쿠에
출판사: 위키북스

01 머신러닝을 위한 데이터 처리

크롤링, 스크레이핑, 머신러닝

인터넷의 빅데이터

블로그와 SNS - 트렌드 분석, 인터넷 전자상거래 - 상품 데이터베이스, 금융 정보, 이미지 데이터, 행정 기관 정보 - 공개 데이터, 위키, 저작권이 없어진 작품, 머신러닝 데이터

스크레이핑, 크롤링, 데이터 가공

스크레이핑 - 웹 사이트에 있는 특정 정보를 추출하는 기술. 웹에 공개된 정보는 대부분 HTML 형식인데 불필요한 정보를 제거하고 필요한 정보만 가져오려면 사이트의 구조를 분석해야 함. 스크레이핑이라는 기술은 웹에서 데이터를 추출하는 것뿐만 아니라 그러한 구조를 분석하는 것도 포함됨.
크롤링 - 프로그램이 웹 사이트를 정기적으로 돌며 정보를 추출하는 기술. 크롤링하는 프로그램을 "크롤러" 또는 "스파이더"라고 함. 정기적으로 웹 사이트들을 돌아다니므로 항상 최신 정보를 유지할 수 있음.

머신러닝에 사용할 수 있는 데이터의 구조

웹에서 내려받은 HTML 데이터를 곧바로 머신러닝에 사용할 수 있는 것은 아님. 데이터의 구조를 분석하고 필요한 부분만 추출하는 과정 필요. 추출한 데이터를 어떻게 저장할 것인지도 중요한 문제. 머신러닝에 활용되는 대표적인 형식으로는 "쉼표로 구분하는 CSV 형식의 데이터", "계층을 통해 구조화할 수 있는 JSON, XML, YAML 형식의 데이터" 등이 있음.

02 크롤링과 스크레이핑

데이터 다운로드하기

웹상의 정보를 추출하는 방법

파이썬은 웹사이트에 있는 데이터를 추출하기 위해 "urllib 라이브러리"를 사용. 이 라이브러리를 사용하면 HTTP 또는 FTP를 사용해 데이터를 다운로드할 수 있음.

urllib.request를 이용한 다운로드

import urllib.request

url = "http://uta.pw/shodou/img/28/214.png"
savename = "test.png"

urllib.request.urlretrieve(url, savename)
print("저장되었습니다...!")

urlopen()으로 파일에 저장하는 방법

# 다운로드 --- (※1)
mem = urllib.request.urlopen(url).read()
# 파일로 저장하기 --- (※2)
with open(savename, mode="wb") as f:
    f.write(mem)

웹에서 데이터 추출하기

클라이언트 접속 정보 출력해보기 - request.urlopen() 메서드를 호출하고 read() 메서드를 사용해 데이터를 읽음. read() 메서드로 읽어 들인 데이터는 바이너리 데이터이기 때문에 decode() 메서드를 사용해 바이너리 문자열로 변환.
매개변수를 추가해 요청을 전송하는 방법 - 파이썬으로 요청 전용 매개변수 만들 때는 urllib.parse 모듈의 urlencode() 함수를 사용해 매개변수를 URL 인코딩함.
매개변수를 명령줄에서 지정하기 - 명령줄 매개변수를 추출할 때 사용하는 sys 모듈을 읽어들임. 명령줄 매개변수는 sys.argv에 리스트 형태로 들어오도록 함. sys.argv[0]에는 스크립트의 이름, sys.argv[1] 이후에는 명령줄 매개변수가 설정됨.

BeautifulSoup로 스크레이핑하기

BeautifulSoup는 어디까지나 HTML과 XML을 분석해주는 라이브러리임. BeautifulSoup 자체에는 다운로드 기능이 없음.

BeautifulSoup 기본 사용법

from bs4 import BeautifulSoup

html = """
<html><body>
  <h1>스크레이핑이란?</h1>
  <p>웹 페이지를 분석하는 것</p>
  <p>원하는 부분을 추출하는 것</p>
</body></html>
"""

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

h1 = soup.html.body.h1
p1 = soup.html.body.p
p2 = p1.next_sibling.next_sibling

분석 대상 HTML을 지정한 후 BeautifulSoup 인스턴스를 생성. 첫 번째 매개변수에 HTML을 지정하고 두 번째 매개변수에는 분석할 분석기의 종류를 지정.

id로 요소를 찾는 방법 - id를 지정해 요소를 추출한 후 find() 메서드에 "id=<값>" 형태로 매개변수를 지정해 요소를 검색.
여러 개의 요소 추출하기 - find_all() 메서드를 사용해 추출. 추출한 모든 요소를 for 구문으로 반복 처리.
DOM 요소의 속성에 대해 - DOM(Document Object Model)이란 XML 또는 HTML의 요소에 접근하는 구조를 나타냄. DOM 요소의 속성이란 태그 이름 뒤에 있는 각 속성을 말함.

urlopen()과 BeautifulSoup 조합하기

from bs4 import BeautifulSoup
import urllib.request as req
url = "http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp"
# urlopen()으로 데이터 가져오기 --- (※1)
res = req.urlopen(url)
# BeautifulSoup으로 분석하기 --- (※2)
soup = BeautifulSoup(res, "html.parser")
# 원하는 데이터 추출하기 --- (※3)
title = soup.find("title").string
wf = soup.find("wf").string

CSS 선택자 사용하기 - soup.select_one(<선택자>)는 CSS 선택자로 요소 하나를 추출. soup.select(<선택자>)는 CSS 선택자로 요소 여러 개를 리스트로 추출.

CSS 선택자

웹 브라우저로 HTML 구조 확인하기

HTML 구조를 확인할 때는 웹 브라우저가 제공하는 개발자 도구를 사용하는 것이 좋음.

원하는 요소 선택하기 - 개발자 도구 왼쪽 위에 있는 요소 선택 아이콘 클릭하고 페이지에서 조사하고 싶은 요소를 클릭. HTML 구조를 확인했으면 태그를 선택한 상태로 마우스 오른쪽 버튼을 클릭하여 팝업 메뉴에서 [Copy > Copy selector]를 클릭하면 선택한 요소의 CSS 선택자가 클립보드에 복사됨.

CSS 선택자 자세히 알아보기

선택자 기본 서식

서식설명
*모든 요소를 선택
<요소 이름>요소 이름을 기반으로 선택
.<클래스 이름>클래스 이름을 기반으로 선택
#<id 이름>id 속성을 기반으로 선택

선택자들의 관계를 지정하는 서식

서식설명
<선택자>, <선택자>쉼표로 구분된 여러 개의 선택자를 모두 선택
<선택자> <선택자>앞 선택자의 후손 중 뒤 선택자에 해당하는 것을 모두 선택
<선택자> > <선택자>앞 선택자의 자손 중 뒤 선택자에 해당하는 것을 모두 선택
<선택자> + <선택자>같은 계층에서 바로 뒤에 있는 요소 선택
<선택자1> ~ <선택자2>선택자1부터 선택자2까지의 요소를 모두 선택

선택자 속성을 기반으로 지정하는 서식

서식설명
<요소>[<속성>]해당 속성을 가진 요소를 선택
<요소>[<속성>=<값>]해당 속성의 값이 지정한 값과 같은 요소를 선택
<요소>[<속성>~=<값>]해당 속성의 값이 지정한 값을 단어로 포함(띄어쓰기로 구분해서 완전히 포함)하고 있다면 선택
<요소>[<속성>=<값>]
<요소>[<속성>^=<값>]해당 속성의 값이 지정한 값으로 시작하면 선택
<요소>[<속성>$=<값>]해당 속성의 값이 지정한 값으로 끝나면 선택
<요소>[<속성>*=<값>]해당 속성의 값이 지정한 값을 포함하고 있다면 선택

위치 또는 상태를 지정하는 서식

서식설명
<요소>:root루트 요소
<요소>:nth-child(n)n번째 자식 요소
<요소>:nth-last-child(n)뒤에서부터 n번째 자식 요소
<요소>:nth-of-type(n)n번째 해당 종류의 요소
<요소>:first-child첫 번째 자식 요소
<요소>:last-child마지막 번째 자식 요소
<요소>:first-of-type첫 번째 해당 종류의 요소
<요소>:last-of-type마지막 번째 해당 종류의 요소
<요소>:only-child자식으로 유일한 요소
<요소>:only-of-type자식으로 유일한 종류의 요소
<요소>:empty내용이 없는 요소
<요소>:lang(code)특정 언어로 code를 지정한 요소
<요소>:not(s)s 이외의 요소
<요소>:enabled활성화된 UI 요소
<요소>:disabled비활성화된 UI 요소
<요소>:checked체크돼 있는 UI요소를 선택

링크에 있는 것을 한꺼번에 내려받기

한꺼번에 다운받는 데 필요한 처리 내용

BeautifulSoup과 CSS 선택자만으로는 링크에 있는 것을 한꺼번에 다운받을 수 없음. a 태그의 링크 대상이 상대 경로일 수 있기 때문에 추가적인 처리가 필요. 또한 링크를 재귀적으로 다운받아야 함.

상대 경로를 전개하는 방법

상대 경로를 전개할 때는 urllib.parse.urljoin()을 사용. 이 함수를 사용하면 a 태그의 href 속성에 지정돼 있는 경로를 절대 경로로 쉽게 변환할 수 있음.

재귀적으로 HTML 페이지를 처리하는 방법

(1) HTML을 분석
(2) 링크를 추출
(3) 각 링크 대상에 다음과 같은 처리
(4) 파일을 다운받음
(5) 파일이 HTML이라면 재귀적으로 (1)로 돌아가서 순서를 처음부터 실행

03 고급 스크레이핑

로그인이 필요한 사이트에서 다운받기

HTTP 통신

웹 브라우저와 웹 서버는 HTTP라고 불리는 통신 규약(프로토콜)을 사용해 통신. HTTP 통신은 브라우저에서 서버로 요청(request)하고, 서버에서 브라우저로 응답(response)할 때 어떻게 할 것인지를 나타내는 규약. 기본적으로 무상태 통신. 무상태 통신이란 같은 URL에 여러 번 접근해도 같은 데이터를 돌려주는 통신을 나타냄. 즉, 이전에 어떤 데이터를 가져갔는지 등에 대한 정보를 전혀 저장하지 않는 통신.

쿠키 - 웹 브라우저를 통해 사이트에 방문하는 사람의 컴퓨터에 일시적으로 데이터를 저장하는 기능. 1개의 쿠키에 저장할 수 있는 데이터의 크기는 4096바이트로 제한됨. 또한 HTTP 통신 헤더를 통해 읽고 쓸 수 있음. 변경하면 문제가 생길 수 있는 비밀번호 등의 정보를 저장하기에는 알맞지 않아 세션이라는 구조를 사용하게 됐는데, 데이터를 저장한다는 점은 쿠키와 동일하지만 서버에 데이터를 저장함으로 인해 제한이 없다는 것이 차이점.
requests 사용해보기 - 사이트의 기본 형태 분석, 로그인 과정 분석

웹 브라우저를 이용한 스크레이핑

웹 브라우저 원격 조작에 사용하는 Selenium

웹 브라우저를 원격 조작할 때 사용하는 도구로 Selenium이 있는데, 일반적으로 웹 애플리케이션 테스트를 자동화할 때 사용하지만 스크레이핑할 때도 유용하게 사용할 수 있음. Selenium을 이용하면 자동으로 URL을 열고 클릭할 수 있으며, 스크롤하거나 문자를 입력하는 등의 다양한 조작을 자동화할 수 있음. 또한 화면을 캡처해서 이미지로 저장하거나 HTML의 특정 부분을 꺼내는 것도 가능.

화면 없는 웹 브라우저 "PhantomJS" - 화면 없이 명령줄에서 사용할 수 있는 웹 브라우저. 레이아웃 엔진으로 WebKit 사용.

웹 사이트를 이미지로 캡처해보기

from selenium import webdriver
url = "http://www.naver.com/"

browser = webdriver.PhantomJS()
browser.implicitly_wait(3)
browser.get(url)
browser.save_screenshot("Website.png")
browser.quit()

Selenium으로 스크레이핑하는 방법

Selenium으로 DOM 요소를 선택하는 방법

DOM 내부에 있는 여러 개의 요소 중 처음 찾아지는 요소를 추출:

메서드 이름설명
find_element_by_id(id)id 속성으로 요소를 하나 추출
find_element_by_name(name)name 속성으로 요소를 하나 추출
find_element_by_css_selector(query)CSS 선택자로 요소를 하나 추출
find_element_by_xpath(query)XPath를 지정해 요소를 하나 추출
find_element_by_tag_name(name)태그 이름이 name에 해당하는 요소를 하나 추출
find_element_by_link_text(text)링크 텍스트로 요소를 하나 추출
find_element_by_partial_link_text(text)링크의 자식 요소에 포함돼 있는 텍스트로 요소를 하나 추출
find_element_by_class_name(name)클래스 이름이 name에 해당하는 요소를 하나 추출

DOM 내부에 있는 모든 요소 추출:

메서드 이름설명
find_elements_by_css_selector(query)CSS 선택자로 요소를 여러 개 추출
find_elements_by_xpath(query)XPath를 지정해 요소를 여러 개 추출
find_elements_by_tag_name(name)태그 이름이 name에 해당하는 요소를 여러 개 추출
find_elements_by_class_name(name)클래스 이름이 name에 해당하는 요소를 여러 개 추출
find_elements_by_partial_link_text(text)링크의 자식 요소에 포함돼 있는 텍스트로 요소를 여러 개 추출

Selenium으로 요소 조작하기

DOM 요소에 적용할 수 있는 메서드와 속성:

메서드 또는 속성설명
clear()글자를 입력할 수 있는 요소의 글자를 지움
click()요소를 클릭
get_attribute(name)요소의 속성 중 name에 해당하는 속성의 값 추출
is_displayed()요소가 화면에 출력되는지 확인
is_enabled()요소가 활성화돼 있는지 확인
is_selected()체크박스 등의 요소가 선택된 상태인지 확인
screenshot(filename)스크린샷 찍음
send_keys(value)키를 입력
submit()입력 양식을 전송
value_of_css_property(name)name에 해당하는 CSS 속성의 값 추출
id요소의 id 속성
location요소의 위치
parent부모 요소
rect크기와 위치 정보를 가진 딕셔너리 자료형 리턴
screenshot_as_base64스크린샷을 Base64로 추출
screenshot_as_png스크린샷을 PNG 형식의 바이너리로 추출
size요소의 크기
tag_name태그 이름
text요소 내부의 글자

Selenium 드라이버 조작

PhantomJS 전용 드라이버의 메서드와 속성:

메서드 또는 속성설명
add_cookie(cookie_dict)쿠키 값을 딕셔너리 형식으로 지정
back() / forward()이전 페이지 또는 다음 페이지로 이동
close()브라우저 닫음
current_url현재 URl을 추출
delete_all_cookies()모든 쿠키를 제거
delete_cookie(name)특정 쿠키를 제거
execute(command, params)브라우저 고유의 명령어 실행
execute_async_script(script, *args)비동기 처리하는 자바스크립트 실행
execute_script(script, *args)동기 처리하는 자바스크립트 실행
get(url)웹 페이지 읽어들임
get_cookie(name)특정 쿠키 값 추출
get cookies()모든 쿠키 값을 딕셔너리 형식으로 추출
get_log(type)로그를 추출(browser/driver/client/server)
get_screenshot_as_base64()base64 형식으로 스크린샷 추출
get_screenshot_as_file(filename)스크린샷을 파일로 저장
get_screenshot_as_png()PNG 형식으로 스크린샷의 바이너리 추출
get_window_position(windowHandle='current')브라우저의 위치 추출
get_window_size(windowHandle='current')브라우저의 크기 추출
implicitly_wait(sec)최대 대기 시간을 초 단위로 지정해서 처리가 끝날 때까지 대기
quit()드라이버를 종료시켜 브라우저 닫음
save_screenshot(filename)스크린샷 저장
set_page_load_timeout(time_to_wait)페이지를 읽는 타임아웃 시간을 지정
set_script_timeout(time_to_wait)스크립트의 타임아웃 시간을 지정
set_window_position(x,y,windowHandle='current')브라우저의 위치 지정
set_window_size(width, height, windoHandle='current')브라우저의 크기 지정
title현재 페이지의 타이틀 추출

자바스크립트 실행해보기

Selenium이 굉장히 다양한 기능을 제공하지만 원하는 기능이 없을 수 있음. 이럴 때는 execute_script() 메서드를 사용해 자바스크립트 코드 실행할 수 있음.

웹 API로 데이터 추출하기

웹 API

웹 API는 어떤 사이트가 가지고 있는 기능을 외부에서도 쉽게 사용할 수 있게 공개한 것을 의미. 일밙벅으로 HTTP 통신을 사용하는데, 클라이언트 프로그램은 API를 제공하는 서버에 HTTP 요청을 보냄. 그러면 서버가 이러한 요청을 기반으로 XML 또는 JSON 형식 등으로 응답.

웹 API를 제공하는 이유

대부분의 뒙 서비스는 정보를 웹사이트를 통해 제공하는데, 이러한 정보는 크롤리으이 표적이 됨. 따라서 어차피 크롤링될 것이라면 차라리 웹 API를 미리 제공해서 서버의 부담을 줄이는 것. 또한 웹 API를 제공해서 상품을 알리거나 구매할 기회를 더 많이 주는 경우도 있음.

웹 API의 단점 - 웹 API 제공자의 사정으로 인해 웹 API가 없어지거나 사양 변경이 일어날 수 있음.

cron을 이용한 정기적인 크롤링

정기적인 크롤링

주식, 환율, 날씨 예보 등과 같이 주기적으로 변경되는 데이터를 사용할 때는 정기적으로 데이터를 크롤링해야 함. macOS와 리눅스에서는 "cron(크론)"이라는 데몬 프로세스를 사용해 정기적으로 데이터를 크롤링할 수 있음.

정기 실행의 장점 - 데이터 수집과 같은 애플리케이션에서 필요한 정기적인 처리 / 로그, 백업과 같은 시스템에서 필요한 정기적인 처리 / 시스템이 제대로 동작하고 있는지 정기적으로 감시하는 처리

매일 환율 정보 저장하기

from bs4 import BeautifulSoup
import urllib.request as req
import datetime

url = "http://info.finance.naver.com/marketindex/"
res = req.urlopen(url)

soup = BeautifulSoup(res, "html.parser")

price = soup.select_one("div.head_info > span.value").string
print("usd/krw", price)

t = datetime.date.today()
fname = t.strftime("%Y-%m-%d") + ".txt"
with open(fname, "w", encoding="utf-8") as f:
	f.write(price)

데이터 소스의 서식과 가공

웹의 다양한 데이터 형식

텍스트 데이터와 바이너리 데이터

데이터 포맷은 크게 "텍스트 데이터"와 "바이너리 데이터"로 나눌 수 있음. "텍스트 데이터"라는 것은 일반적으로 텍스트 에디터로 편집할 수 있는 데이터 포맷을 나타냄. 주로 일반적인 자연 언어와 숫자 등으로 구성됨. 반면 "텍스트 데이터" 외의 데이터를 "바이너리 데이터"라고 부르는데, 문자와 상관 없이 데이터를 사용할 수 있는 데이터 영역을 활용. 바이너리 데이터는 데이터를 효율적으로 저장할 수 있는 데이터 형식.

profile
취업 준비 용으로 사용했던 기술 블로그입니다. 이제는 업로드 거의 안 할지도..

0개의 댓글