[2024.09.30] 필수 온라인 강의 Part2 파이썬 라이브러리 활용 CH05 웹 데이터 수집 라이브러리(BeautifulSoup)
- 웹 크롤링이란?
- 인터넷 상에 존재하는 데이터를 자동으로 수집하는 행위
- 데이터 분석가에게 데이터를 탐색하고 원하는 조건에 맞는 데이터를 직접 수집/저장하기 위한 목적으로 사용
1. 웹 페이지 정보 가져오기 : 파이썬 Requests 라이브러리 사용
2. HTML 소스를 파싱(분석)하여 원하는 정보 얻기 : 파이썬 BeautifulSoup 라이브러리 사용
- 기본 개념
1. 브라우저로 접속하고 싶은 주소(url) 입력
2. 브라우저가 해당 주소의 서버에게 "페이지 구성 정보를 줘:라고 요청(request)
3. 웹 서버는 구성에 필요한 코드(html) 형태로 전달 (response)
4. 브라우저는 서버가 전달해준 정보(html)을 해석해서 사용자 화면을 보여줌 - BeautifulSoup : 웹 데이터 수집 라이브러리
- HTML 및 XML에서 데이터를 쉽게 처리하는 파이썬 라이브러리
- HTML은 태그로 이루어져있고, 공백과 변화하는 소스가 많음 : 오류가 있을 가능성 높음
-> BeautifulSoup를 이용하여 오류를 잡아서 고친 후 데이터 전달됨
- pip install beautifulsoup4
- from bs4 import BeautifulSoup
- https://www.crummy.com/software/BeautifulSoup/bs4/doc/ 에서 참고 - HTML 코드 작성
html = """
<html>
<body>
<h1 id = 'title'>Selena 파이썬 라이브러리 활용!</h1>
<p id = 'body'>오늘의 주제는 웹 데이터 수집</p>
<p class = 'scraping'>삼성전자 일별 시세 불러오기</p>
<p class = 'scraping'>이해 쏙쏙 Selena 수업!</p>
</body>
<html>
"""
- HTML 파싱
- soup = BeautifulSoup (html, 'html.parser')
- html을 파이썬에서 읽을 수 있게 파싱(파이썬 객체로 변환)
- html이라는 변수에 저장한 html 소스코드를 .parser를 붙여 변환
# BeautifulSoup 함수를 이용하여 soup 객체 생성
# html이라는 변수에 저장한 html 소스코드를 .parser를 붙여 변환
soup = BeautifulSoup(html, 'html.parser')
- BeautifulSoup 데이터를 텍스트로 변환
for text in soup:
print(text)
- soup : soup의 데이터를 모두 가져와서 텍스트로 반환
- soup.contents : soup의 데이터를 모두 가져와서 리스트로 반환
- soup.stripped_strings : 공백도 함께 제거하여 텍스트로 반환
for text in soup:
print(text)
<html>
<body>
<h1 id="title">Selena 파이썬 라이브러리 활용!</h1>
<p id="body">오늘의 주제는 웹 데이터 수집</p>
<p class="scraping">삼성전자 일별 시세 불러오기</p>
<p class="scraping">이해 쏙쏙 Selena 수업!</p>
</body>
<html>
</html></html>
for stripped_text in soup.stripped_strings: # 공백도 함께 제거하여 텍스트로 반환
print(stripped_text)
Selena 파이썬 라이브러리 활용!
오늘의 주제는 웹 데이터 수집
삼성전자 일별 시세 불러오기
이해 쏙쏙 Selena 수업!
- Find 함수
scraping = soup.find(class_='scraping')
scraping.string
- find 함수는 id, class, element 등을 검색 가능
- find : 조건에 해당하는 첫 번째 정보만 검색 : 클래스 이름을 알 경우, class_ 형태로 사용
title = soup.find(id='title') # id 값이 'title'인 조건에 해당하는 첫 번째 정보만 검색
print(title)
scraping = soup.find(class_='scraping') # class 값이 'scraping'인 조건에 해당하는 첫 번째 정보만 검색 # 클래스 이름을 알 경우, class_ 형태로 사용
print(scraping)
- find_all : 조건에 해당하는 모든 정보 검색
scraping_all = soup.find_all(class_='scraping') # class 값이 'scraping'인 조건에 해당하는 모든 정보 검색
print(scraping_all)
- string : 태그 내부의 텍스트만 출력
scraping.string # 태그 내부의 텍스트만 출력
- BeautifulSoup 웹 크롤링 3단계 과정
1. Request : 웹 페이지의 URL 이용해서 HTML 문서를 요청. 첫 번째 단계인 Request를 위해 import urllib.request 불러오기
import requests # 웹 페이지의 URL을 이용해서 HTML 문서를 요청하기 위해 필요한 라이브러리
2. Response : 요청한 HTML 문서를 회신
3. Parsing : 태그 기반으로 파싱(일련의 문자열을 의미 있는 단위로 분해)
- 네이버 금융에 접속하여 실습하기
- F12(개발자도구) URL 찾기
1. 네이버 금융 홈페이지 접속 : https://finance.naver.com/
2. 삼성전자(code : 005930) 검색
3. 시세 메뉴 클릭 후 URL 확인 : https://finance.naver.com/item/main.naver?code=005930
4. 키보드 F12(개발자도구) 클릭 > 메뉴 Elements 클릭 > 키보드 Ctrl과 F (검색 단축키) 클릭 > '일별 시세' 검색 > scr 값 복사
: src="/item/sise_day.naver?code=005930"
1번 단계. Request 진행하기
- 웹 ㅔ이지의 URL을 이용해서 HTML 문서를 요청
- requests.get(stock_url, headers = headers) : url 값을 파라미터 값으로 입력, 해당 사이트는 반드시 헤더 저어보를 요구하기 때문에 파라미터 값을 헤더 입력
1. url 저장
- stock_url = 'https://finance.naver.com//item/sise_day.naver?code=005930'
- stock_url이라는 변수에 네이버 금융 사이트의 삼성전자 시세 정보가 담긴 URL 저장
2. header라는 변수에 넣어주기
- header에 User-Agent를 넣어줄것.
- user-agent란, 웹 크롤링을 진행하면 종종 페이지에서 아무것도 받아오지 못하는 경우 발생!
이유는 대부분 서버에서 봇을 차단하기 때문 : 이걸 해결 해주는 것 : 디폴트 값으로 이용하는 게 좋음
- user-agent 확인 사이트 : http://www.useragentstring.com/
# header에 user-agent 값 저장
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'}
- 웹 페이지의 URL 이용해서 HTML 문서를 요청
requests.get(stock_url, headers = headers)
- URL 값을 파라미터 값으로 입력
- 해당 사이트는 반드시 헤더 정보를 요구하기 때문에 파라미터 값으로 헤더 입력
2번 단계. Response
- 요청한 HTML 문서를 회신 : response 변수에 요청한 HTML 문서를 회신하여 저장
response = requests.get(stock_url, headers = headers)
- 서버에서 요청을 받아 처리한 후, 요청자에게 응답 줌
- HTML 코드 형태
3번 단계. Parsing
- 태그 기반으로 파싱(일련의 문자열을 의미 있는 단위로 분해)
soup = BeautifulSoup(response.text, 'html.parser')
- html을 파이썬에서 읽을 수 있게 파싱(파이썬 객체로 변환)
- Response.text에 저장한 html 소스코드를 .parser를 붙여 변환
- parser는 파이썬의 내장 메소드
- 반복구문으로 일별 종가 구현 : 200일 동안의 일별 종가 정보 가져오는 반복문 구현
- 반복문 코드 설명
1) 200일 일별 종가 정보는 1 Page 당 10일의 일별 종가 정보 담겨있어서 20 Page 필요
2) 일별 종가 담긴 URL과 Header 정보로 requests.get 함수 구현
3) 요청한 HTML 문서를 회신하여 response 변수에 저장
4) BeautifulSoup함수로 HTML을 읽을 수 있도록 파싱하여 soup 변수에 저장
5) Page 개수만큼 20번 반복
- "tr" 태그 조건에 해당하는 모든 정보를 검색하여 parsing_list 변수에 저장
6) 1 Page 당 10일의 일별 종가 정보 담겨있어서 10번 반복
- "td" 태그의 align가 "center"인 값들 중 0번째 조건에 해당하는 정보 검색하여 출력
- "td" 태그의 class가 "num"인 값들 중 0번째 조건에 해당하는 정보 검색하여 출력
# 200일 동안의 일별 종가 정보 가져오는 반복문(1페이지 당 10일 정보 담겨있음)
for page in range(1, 21):
print (str(page))
# url + page 번호 합치기
stock_url = 'http://finance.naver.com/item/sise_day.nhn?code=005930' +'&page='+ str(page)
# header 정보
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'}
# request : 웹 페이지의 URL, header 이용해서 HTML 문서 요청
# response : 요청한 HTML 문서 회신
response = requests.get(stock_url, headers = headers)
# parsing : HTML을 읽을 수 있도록 파싱
# soup 변수에 BeautifulSoup의 객체 생성
soup = BeautifulSoup(response.text, 'html.parser')
# "tr" 태그 조건에 해당하는 모든 정보 검색
parsing_list = soup.find_all("tr")
# None 값은 걸러주기 위한 변수 생성
isCheckNone = None
# 페이지당 일별 종가 출력하기 위한 반복문 <들여쓰기 주의>
for i in range(1, len(parsing_list)):
if(parsing_list[i].span != isCheckNone):
print(parsing_list[i].find_all("td", align="center")[0].text,
parsing_list[i].find_all("td", class_="num")[0].text)
# None 값은 걸러주기 위한 조건문 <들여쓰기 주의>
# .span()는 매치된 문자열의 (시작, 끝)에 해당하는 튜플을 돌려주는 함수
# parsing_list[i] : i번째 parsing_list, i 번째 "tr" 태그 값
# .find_all("td", align="center")[0].text : "td" 태그의 align가 "center"인 값들 중 0번째 값
# .find_all("td", class_="num")[0].text : "td" 태그의 class가 "num"인 값들 중 0번째 값
- Pandas를 이용한 웹데이터 수집
1) Pandas 라이브러리와 Requests 라이브러리 이용
2) 200일 일별 종가 정보는 1 Page 당 10일의 일별 종가 정보 담겨있어서 20 Page 필요
3) 일별 종가 담긴 URL과 Header 정보로 requests.get 함수 구현
4) pandas.read_html 함수를 통해 HTML 불러와서 파싱
5) concat 함수를 이용하여 dataframe 끝에 추가하고 싶은 요소를 추가하여 dataframe 리턴
6) dropna 함수를 통해 결측 값 제거
import pandas as pd # pandas 라이브러리
import requests # requests 라이브러리
stock_data = pd.DataFrame() # 빈 데이터프레임을 생성하여 이후 각 페이지에서 가져온 데이터를 추가
# code = 회사 코드, page = 일별 시세 테이블의 페이지 수 (200 행의 데이터 불러오려면 20 페이지 입력)
for page in range(1, 21): # 1. 페이지 순회
stock_url = 'http://finance.naver.com/item/sise_day.nhn?code=005930' +'&page='+ str(page)
# header 정보
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'}
response = requests.get(stock_url, headers = headers) # response : 요청한 HTML 문서 회신
# request : 웹 페이지의 URL, header 이용해서 HTML 문서 요청
df_page = pd.read_html(response.text, header=0)[0] # 2. response.text로 응답을 주면 HTML 코드이기 때문에 read_html로 불러오기
# 3. concat() : 여러 DataFrame을 하나로 결합할 때 사용
stock_data = pd.concat([stock_data, df_page], ignore_index=True)
# 주의!! : pandas 2.0.0 버전 이후부터 'append()' Method가 완전히 제거되었기 때문에 더 이상 작동하지 않음. concat() 사용
stock_data = stock_data.dropna() # 4. 결측값 행 제거(for문 외부에 위치하도록 들여쓰기 주의)
stock_data
- Pandas 일별 시세 테이블 구현 코드 설명
: pandas 2.0.0 버전 이후부터 'append()' Method가 완전히 제거되었기 때문에 더 이상 작동
1. 1부터 20까지 순회하는 for문
-데이터를 가져올 웹 페이지 주소에 `&page=`와 숫자를 붙여 1 페이지부터 20 페이지까지의 데이터를 가져오기 위한 것.
2. `pd.read_html(response.text, header=0)[0]` 코드를 세부적으로 설명.
먼저 `pd.read_html()`는 HTML 페이지의 모든 표를 읽어서 각 표를 DataFrame 객체로 저장한 리스트를 반환.
`response.text`는 HTML 내용을 문자열로 변환하여 가져옵니다. `header=0`는 첫 번째 행을 열 이름으로 사용한다는 의미.
즉, 표의 첫 번째 행이 데이터프레임의 열 이름이 됩니다. `[0]`는 이 리스트에서 첫 번째 DataFrame 객체를 선택하는 것을 의미
HTML 문서에 여러 개의 표가 있을 수 있기 때문에, 일반적으로 원하는 표를 선택하기 위해 인덱스를 사용.
3. 현재 stock_data 데이터프레임과 df_page 데이터프레임을 결합.
`ignore_index=True`는 기존 인덱스를 무시하고 새로운 연속적인 인덱스를 생성함
4. 데이터프레임에 있는 누락값을 제거. 이는 데이터를 추가로 분석하기 전에 데이터를 정리하는 일반적인 작업
'Study > Python' 카테고리의 다른 글
파이썬 라이브러리 활용 프로젝트 - 파이썬 개념 용어 이해 (1) | 2024.10.07 |
---|---|
파이썬 라이브러리 활용 프로젝트 - 파이썬 환경 세팅하기 (7) | 2024.10.07 |
파이썬 라이브러리 - Seaborn(데이터 시각화) (0) | 2024.09.30 |
파이썬 라이브러리 - Matplotlib (데이터 시각화) (0) | 2024.09.30 |
파이썬 라이브러리 - Pandas (데이터 자료 처리 라이브러리) (1) | 2024.09.27 |