목차
[Python] 설치에 필요한 라이브러리
Pandas로 네이버 금융의 재무분석 정보를 가져오려고 합니다. Pandas의 장점은 데이터를 엑셀과 같은 양식으로 쉽게 관리하고 내부에 강력한 수학 함수들이 있어서 주식의 차트 분석이나 수학의 확률 분석 그리고 빅데이터로 데이터 분석을 하는 데 유용합니다.
네이버 파이넌스에서 정보를 가져올 것인데 해당 HTML의 정보를 테이블로 쉽게 정리해서 전달해주는 함수가 Pandas에 Html_read라는 함수가 있습니다.
저는 Visual Studio Code를 사용해서 Pandas를 설치했는데 Html_read 함수를 사용하기 위해 아래와 같이 추가적인 라이브러리를 설치해야합니다. 웹크롤링(web crawling)과 관련된 라이브러리로 Html_read함수가 해당 라이브러리를 가져와서 사용합니다.
pip install html5lib
pip install bs4
저는 위와 같이 BeautifulSoup4와 html5lib-1.1 을 설치 하였습니다. 만일 그외에 부족한 라이브러리가 있다면 아래와 같은 에러메세지를 띄우니 이를 참조해서 pip install 명령어로 설치하시면 됩니다.
에러 메세지>>
ImportError: BeautifulSoup4 (bs4) not found, please install it
[Python] Pandas로 네이버 금융 종목 분석 항목 가져오기 - encoding 에러 발생 해결
우선 가장 유명한 삼성전자의 재무정보를 가져와 보겠습니다.
아래 그림 처럼 삼성전자의 재무분석 주소는 "https://finance.naver.com/item/coinfo.naver?code=005930" 입니다.
여기서 005930은 삼성전자의 코드번호로 해당 번호만 변경하면 다른 기업의 재무정보를 가져올 수 있습니다. (사실 이부분은 나중에 다시 설명하겠지만 실제 재무정보를 가진 주소는 다릅니다.)
url 주소는 Naver 금융에서 한번씩 변경할 수 있기 때문에 한번씩 사이트를 방문해서 확인하는 작업이 필요 합니다.
목표는 Pandas 코드를 이용해서 아래 "포괄손익계산서"의 테이블 값을 가져오는 것입니다.
이제 파이썬의 Pandas의 read_html 함수를 사용해서 테이블 정보를 가져와서 print로 확인해 보겠습니다.
코드>>
import pandas as pd
tables = pd.read_html('https://finance.naver.com/item/coinfo.naver?code=005930')
print(f'Total tables: {len(tables)}')
print(tables)
결과>>
Total tables: 9
[ 0 1 2
0 ÀüÀÏ 70,200 70,200 °í°¡ 70,70070,700 (»óÇÑ°¡ 91,20091,200 ) °Å·¡·® 8,376,369 8,376,369
1 ½Ã°¡ 70,00070,000 Àú°¡ 70,00070,000 (ÇÏÇÑ°¡ 49,200 ) °Å·¡´ë±Ý 589,192 589,192 ¹é¸¸, 0 1
0 ½Ã°¡ÃÑ¾× 420Á¶ 2,727 ¾ï¿ø
1 ½Ã°¡ÃѾ׼øÀ§ ÄÚ½ºÇÇ 1À§
##이하 생략
3번째 라인 : 판다스의 read_html의 입력값으로 url 주소를 입력하였습니다. return값은 html의 정보를 테이블로 정리된 정보들이 갔습니다.
4번째 라인 : 삼성전자의 네이버금융 url 에서 나온 총 테이블의 개수는 9개로 나왔습니다.
5번째 라인 : 테이블의 정보를 불러왔는데 한글 부분이 깨짐을 알 수 있습니다. 해당 부분은 encoding 방법을 지정함으로서 해결할 수 있습니다. 일반적으로 한글 인코딩은 "euc-kr"을 사용하거나 "utf-8"을 사용하면 해결이 됩니다.
여기서는 euc-kr 인코딩이 적용되어서 euc-kr로 정보를 불러 오겠습니다.
코드 : encoding 적용>>
import pandas as pd
tables = pd.read_html('https://finance.naver.com/item/coinfo.naver?code=005930', encoding="euc-kr")
print(f'Total tables: {len(tables)}')
print(tables)
결과>>
Total tables: 9
[ 0 1 2
0 전일 70,200 70,200 고가 70,70070,700 (상한가 91,20091,200 ) 거래량 8,376,369 8,376,369
1 시가 70,00070,000 저가 70,00070,000 (하한가 49,200 ) 거래대금 589,192 589,192 백만, 0 1
0 시가총액 420조 2,727 억원
1 시가총액순위 코스피 1위
2 상장주식수 5969782550
3번째 라인 : encoding="euc-kr"을 사용해서 방금 발생했던 한글 깨짐 현상을 해결하였습니다.
결과를 보시면 왼쪽 부분이 index 번호로 다시 0이 시작되는 부분은 새로운 테이블이라고 생각하시면 됩니다.
[Python] Pandas로 네이버 금융 종목분석 항목 가져오기 - 업종 PER 찾기(Match 결과 없을 경우)
이번에는 read_html 함수의 match 속성값을 이용해서 아래 그림의 업종PER 정보를 가져올 것입니다. (빨간 점선)
우선 앞서 사용했던 코드와 url 주소로 match 속성을 이용해서 검색해보겠습니다.
코드>>
import pandas as pd
tables = pd.read_html('https://finance.naver.com/item/coinfo.naver?code=005930', encoding="euc-kr", match="업종PER")
print(f'Total tables: {len(tables)}')
print(tables)
결과>>
ValueError: No tables found matching pattern '업종PER'
다음과 같은 에러가 발생하였습니다. 화면에서는 "업종PER"이 있지만 판다스 프로그램 테이블에는 해당 내용이 없는 것이 었습니다. 그래서 사이트의 코드를 살펴 보았습니다.
크롬(chrome)에서 f12를 누르거나 마우스 오른쪽 클릭 후 "검사"를 누르면 위 그림의 오른쪽 화면처럼 페이지 소스를 확인할 수 있습니다. 제가 선택한 내용을 보면 iframe으로 또 다른 frame이 만들어 져있음을 알 수 있습니다. 그리고 해당 frame의 주소는 "https://navercomp.wisereport.co.kr/v2/company/c1010001.aspx?cmp_cd=005930" 로 나와 있습니다.
해당 주소를 직접 입력하여 확인하니 아래와 같은 화면을 확인할 수 있었습니다.
이제 해당 frame의 새로운 url을 얻었으므로 이 주소로 다시 코딩을 실행해 보겠습니다.
코드 : url 변경 코드>>
import pandas as pd
tables = pd.read_html('https://navercomp.wisereport.co.kr/v2/company/c1010001.aspx?cmp_cd=005930', encoding="euc-kr", match="업종PER")
print(f'Total tables: {len(tables)}')
print(tables)
결과>>
UnicodeDecodeError: 'euc_kr' codec can't decode byte 0xec in position 140: illegal multibyte sequence
이번에는 unicode 에러가 발생했습니다. 앞서 html에서는 euc-kr 인코딩 방식으로 되었던것이 해당 페이지에서는 적용되지 않습니다. 이번 페이지는 utf-8 인코딩을 사용하기 때문에 utf-8로 인코딩을 하겠습니다.
코딩 : utf-8 인코딩>>
import pandas as pd
tables = pd.read_html('https://navercomp.wisereport.co.kr/v2/company/c1010001.aspx?cmp_cd=005930', encoding="utf-8", match="업종PER")
print(f'Total tables: {len(tables)}')
print(tables)
결과>>
Total tables: 1
[ 0
0 삼성전자 005930 SamsungElec KOSPI : 전기전자 WICS ...
1 EPS 4,749 BPS 40,361 PER 14.83 업종PER 12.94 ...]
위 결과와 같이 업종PER이 포함된 PER을 가져왔습니다.
이번에는 match 되지 않은 전체결과 값을가져왔고 아래와 같이 나왔습니다.
결과>>
Total tables: 15
[ 0
0 삼성전자 005930 SamsungElec KOSPI : 전기전자 WICS ...
1 EPS 4,749 BPS 40,361 PER 14.83 업종PER 12.94 ..., 0 1
0 주가/전일대비/수익률 70,400원 / +200원 / +0.29%
1 52Weeks 최고/최저 96,800원 / 56,000원
2 액면가 100원
3 거래량/거래대금 8,395,450주 / 5,905억원
4 시가총액 4,202,727억원
5 52주베타 1.06
6 발행주식수/유동비율 5,969,782,550주 / 74.64%
7 외국인지분율 51.43%
8 수익률 (1M/3M/6M/1Y) -8.81%/ -11.67%/ -14.56%/ +17.14%, 신용등급 BOND CP
0 KIS NaN NaN
1 KR NaN NaN
2 NICE NaN NaN
3 NaN NaN NaN, 0
0 [기준: 2021.10.22], 주요주주 보유주식수(보통) 보유지분(%)
0 삼성생명보험 외 17인 삼성생명보험 외 17인 1.262564e+09 21.15
1 국민연금공단 5.783523e+08 9.69
2 BlackRock Fund Advisors 외 15인 BlackRock Fund A... 3.003911e+08 5.03
3 NaN NaN NaN, 주요지표 2020/12(A) 2021/12(E)
0 PER 18.33 12.29
1 PBR 1.79 1.64
2 PCR 7.32 6.54
3 EV/EBITDA 5.56 4.23
4 EPS 3,841원 5,728원
5 BPS 39,406원 42,805원
6 EBITDA 663,294.9억원 859,832.8억원
7 현금DPS 2,994원 1,668원
8 현금배당수익률 4.25% 2.37%
9 회계기준 연결 연결, Empty DataFrame
Columns: [어닝서프라이즈 * 단위: 억원, %, 어닝서프라이즈 * 단위: 억원, %.1, 어닝서프라이즈 * 단위: 억원, %.2, 어닝서프라이즈 * 단위: 억원, %.3]
Index: [], 0 1
0 밴드차트 밴드차트 주재무제표 K-IFRS(별도) K-IFRS(연결) K-GAAP(개별..., 0
1 2
0 Financial Summary 주재무제표 K-IFRS(별도) K-IFRS(연결) K-GAAP(개별) K-G... * 단위 : 억원, %, 배, 주 * 분기: 순액기준, 항목명
상세기준
0 CAPEX 유형자산의증가
1 FCF 영업활동으로인한현금흐름-CAPEX
2 이자발생부채 단기사채+단기차입금+유동성장기부채+단기금융부채+사채+장기차입금+장기금융부채
3 영업이익률 영업이익/매출액(수익)
4 순이익률 당기순이익/매출액(수익)
5 ROE (지배주주지분)당기순이익[당기]/((지배주주지분)자본총계[당기]+(지배주주지분)자본...
6 ROA 당기순이익[당기]/(자산총계[당기]+자산총계[전기]/2)
7 부채비율 부채총계/자본총계
8 자본유보율 (자본잉여금+이익잉여금)/자본금
9 EPS (지배주주지분)당기순이익*1000/수정평균발행주식수(보통주+우선주)
10 PER 보통주수정주가(기말)/EPS
11 BPS (지배주주지분)자본총계/수정기말발행주식수(보통주+우선주, 자사주차감)
12 PBR 보통주수정주가(기말)/BPS
13 수정DPS DPS에 자본금변동이벤트 시 수정계수가 발생하는 경우 수정계수를 적용
14 현금배당수익률 수정DPS/보통주수정주가(기말)
15 현금배당성향 현금배당액(전체)/(지배주주지분)당기순이익
16 발행주식수 보통주 기말발행주식수 (자본금 변동 이벤트 중 수정계수가 발생하는 경우 과거 데이터..., 0 1 2 3 4 5
0 NaN 전체 연간 분기 NaN NaN, 0 1 2 3 4 5
0 4.0 투자의견 목표주가(원) EPS(원) PER(배) 추정기관수
1 4.0 4.00 95652 5728 12.29 23, 제공처 최종일자 목표가 직전목표가 변동률(%) 투자의견 직전투자의견
0 유안타 21/10/20 107000 107000 0.00 Buy Buy
1 SK 21/10/20 90000 108000 -16.67 매수 매수
2 신한금융투자 21/10/19 96000 96000 0.00 매수 매수
3 IBK투자 21/10/15 90000 100000 -10.00 매수 매수
4 상상인 21/10/15 82000 90000 -8.89 중장기주가상승 단기주가보합
5 이베스트투자 21/10/12 87000 95000 -8.42 Buy Buy
6 대신 21/10/12 95000 95000 0.00 Buy Buy
7 하이투자 21/10/12 89000 92000 -3.26 Buy Buy
8 키움 21/10/12 95000 95000 0.00 BUY BUY
9 한국투자 21/10/12 100000 100000 0.00 매수 매수
10 삼성 21/10/12 100000 100000 0.00 BUY BUY
11 현대차 21/10/12 100000 100000 0.00 BUY BUY
12 유진투자 21/10/12 93000 100000 -7.00 BUY BUY
13 KB 21/10/12 100000 105000 -4.76 BUY BUY
14 미래에셋 21/10/12 82000 100000 -18.00 Trading Buy 매수
15 DB금융투자 21/10/12 100000 100000 0.00 Buy Buy
16 NH투자 21/10/08 95000 95000 0.00 Buy Buy
17 한화투자 21/10/08 105000 105000 0.00 Buy Buy
18 케이프투자 21/10/08 105000 105000 0.00 BUY BUY
19 KTB투자 21/10/08 95000 95000 0.00 BUY BUY
20 하나금융투자 21/09/15 101000 101000 0.00 BUY BUY
21 흥국 21/08/18 97000 97000 0.00 BUY BUY
22 메리츠 21/07/29 96000 96000 0.00 Buy Buy, 0 1
0 추정실적 컨센서스 주재무제표 K-IFRS(별도) K-IFRS(연결) K-GAAP(개별) K-G..., 0 1 2 3 4
0 NaN 연간 분기 NaN NaN]
결과를 보시면 아시겠지만 "펀더멘털"이나 "Finanacial Summary" 와 같은 테이블 값이 빠져 있음을 알 수 있습니다. 그리고 "투자자별 매매동향" 등 DB 분석에서 자바스크립트로 가져오는 정보들은 읽을 수가 없었습니다.
디버깅 결과 확인된 바로는 해당정보들은 pandas에서 user-agent 없이 값을 보내기 때문에 네이버 서버에서 이상 접근으로 확인하고 차단한 것으로 파악됩니다.
이 부분은 beautifulsoup에서도 나온 문제로 bs에서는 user-agent를 직접 설정해서 해결할 수 있었습니다. pandas에서는 안타깝게도 해당 기능을 지원하지 않아 다음 포스트에서 bs4로 데이터를 가져와서 pandas에서 정리하는 내용에 대해 다시 다뤄 보겠습니다.
'파이썬(Python) > pandas' 카테고리의 다른 글
[Python] Pandas 이동평균 함수 사용법 (Rolling) (2) | 2021.11.10 |
---|---|
[Python] 코스피 1년 차트 그리기(Pandas, Matplotlib) (0) | 2021.10.30 |
[Python] 코스피, 코스닥 값 불러와서 분석하기(pandas) (0) | 2021.10.28 |
[Python] Pandas DataFrames이란? 선언, 데이터 찾기, 정렬하기 예제(find, sort) (0) | 2021.10.26 |
[Python] Pandas Series란? 선언방법, 합치기 (append) (0) | 2021.10.23 |