파이썬(Python)/pandas

[Python] Pandas로 네이버 금융 재무분석 항목 가져오기(에러해결 추가)

끄적끄적아무거나 2021. 10. 23. 20:51
반응형

 

목차

     

     

     

     


     

     

     

    [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에서 정리하는 내용에 대해 다시 다뤄 보겠습니다.

    반응형