본문 바로가기
Programming/Code Archive

미국 주식 재무제표 크롤링으로 배우는 파이썬 Selenium 기초

by 지표덕후 2022. 5. 8.

웹 크롤링(혹은 웹 스크래핑)을 하는 여러 가지 방법 중에 파이썬 셀레니움을 활용하는 방식은 난이도가 좀 있는 편입니다. 저 역시 가급적 Selenium 없이 크롤링 하는 걸 선호하지만 어떤 유형의 사이트들은 데이터를 먼저 로드하고 나서야 스크래핑 할 수 있기 때문에 셀레니움 없이 스크래핑 하기가 어렵습니다. 

 

저도 웹 스크래핑 관련된 게시물을 몇 개 올렸는데 그 중 가장 유입량이 많은 게시물이 인스타그램 해시태그 크롤링이었습니다. 그 작업도 셀레니움을 활용하는 방식인데, 셀레니움에 대한 기초도 언급 않고 코드만 나열해둔 그 게시물을 몇 분이나 이해했을지... 죄책감이 들어 금번 포스팅을 작성하게 됐어요.

 

 

[파이썬Python] 인스타그램 해쉬태그(#) 검색결과 크롤링하기

★ 댓글로 주신 의견 반영하여 코드는 지속적으로 수정하고 있습니다.  수정된 부분은 아래 본문에 일일이 표시해두었으니 참고해주세요.  댓글 주신 모든 분들 감사합니다. 코딩의 결과 기본

mokeya.tistory.com

 

이 포스팅에서는 미국 주식 하는 분들이 즐겨 참고하는 사이트인 모닝스타(http://financials.morningstar.com/)에서 상장기업의 재무제표를 크롤링하는 상황을 가정하여 Selenium 패키지 활용법의 기초를 설명하려 합니다.

 

여기 이 제무재표를 크롤링할 예정

 

 

 

크롤링 준비


필요한 툴은 파이썬(Python)과 크롬드라이버(ChromeDriver), 셀레니움(Selenium) 세 가지입니다. 파이썬은 다 설치되어 있으실 테니, 크롬드라이버만 아래 참고해서 설치해주세요.

 

1) 내 크롬 브라우저의 버전을 확인합니다(크롬이 설치되어 있지 않다면 설치해야 합니다).
     크롬 브라우저 우상단의 메뉴 > 도움말 > Chrome 정보 메뉴에서 내 크롬의 버전을 확인할 수 있습니다.

 

2) 아래 링크로 들어가서 내 버전과 OS에 맞는 크롬 웹드라이버를 다운로드합니다.

 

ChromeDriver - WebDriver for Chrome - Downloads

Current Releases If you are using Chrome version 102, please download ChromeDriver 102.0.5005.27 If you are using Chrome version 101, please download ChromeDriver 101.0.4951.41 If you are using Chrome version 100, please download ChromeDriver 100.0.4896.60

chromedriver.chromium.org

3) 다운 받은 압축파일의 내용물을 파이썬 기본폴더(=코드파일 .py가 저장되는 폴더)에 압축 해제합니다.

 

 

 

스크래핑 코드 작성의 기초


01 selenium 라이브러리 설치

pip install selenium

 

 

02 필요한 라이브러리 호출

from selenium import webdriver
from selenium.webdriver.common.by import By
from bs4 import BeautifulSoup
import time
import re

 

 

03 애플(AAPL) 재무제표 페이지 열기

driver = webdriver.Chrome('chromedriver.exe')를 실행하면 크롬이 열립니다. driver 인스턴스(객체)에는 여러 가지 메소드가 내포되어 있는데 .get() 메소드를 통해 지정된 url로 접속할 수 있습니다. sleep()은 괄호 안에 있는 파라미터를 통해 해당 초수만큼 파이썬 동작을 멈춥니다. 웹사이트의 콘텐츠가 완전히 로드된 후에 스크래핑 하도록 제어하기 위해 삽입하는 코드입니다.

driver = webdriver.Chrome('chromedriver.exe')
url = 'http://financials.morningstar.com/income-statement/is.html?t=AAPL&region=usa&culture=en-US'
driver.get(url)
time.sleep(2)

 

 

04 재무제표 페이지의 개발자도구 뒤지기

▼ 크롤링 하려는 재무제표 페이지에서 F12를 누르면 아래 화면처럼 개발자도구가 사이드메뉴로 나타납니다. 여기 사이드 메뉴의 좌상단의 화살표를 클릭한 후에,

 

▼ 그럼 다음 스크래핑 하려는 데이터에 마우스를 갖다 대면 아래와 같이 블록이 씌워지면서 개발자 도구에 해당 데이터의 CSS element가 지정되는데요. 다행히 모닝스타의 재무제표는 여러 연도의 수치가 행 단위로 묶여 있습니다. 셀 단위로 크롤링 안 해도 된다는말이죠. 이 블록에 마우스 오른쪽 클릭하면, 

 

▼ 여러 가지 메뉴가 뜹니다. Copy > Copy XPath를 누르면 해당 행의 XPath가 메모리에 저장됩니다.

 

▼ 그래서 각 계정의 XPath를 아래와 같이 정리해둡니다.

revenue = '//div/div[@id="data_i1"]' #this is the xpath
cost_of_revenue = '//*[@id="data_i6"]'
gross_profit = '//*[@id="data_i10"]'
operating_income = '//*[@id="data_i30"]'
income_before_taxes = '//*[@id="data_i60"]'
net_income = '//*[@id="data_i80"]'
eps_basic = '//*[@id="data_i84"]'
eps_diluted = '//*[@id="data_i84"]'
wgt_avg_shs_outstand_basic = '//*[@id="data_i85"]'
wgt_avg_shs_outstand_diluted = '//*[@id="data_i86"]'
EBITDA = '//*[@id="data_i90"]'

# Balance Sheet
cash_and_cash_equivalents = '//*[@id="data_i1"]'
total_current_assets = '//*[@id="data_ttg1"]'
total_non_current_assets = '//*[@id="data_ttg2"]'
long_term_debt = '//*[@id="data_i50"]'
total_liabilities = '//*[@id="data_ttg5"]'
common_stock = '//*[@id="data_i82"]'
retained_earnings  ='//*[@id="data_i85"]'
total_sh_equity = '//*[@id="data_ttg8"]'

# Cash Flow
depreciation_amortization = '//*[@id="data_i2"]'
cash_flows_operation = '//*[@id="data_tts1"]'
cash_flows_investing = '//*[@id="data_tts1"]'
cash_flows_financing = '//*[@id="data_tts1"]'
operating_cash_flow = '//*[@id="data_i100"]'
capital_expenditure = '//*[@id="data_i96"]'
free_cash_flow = '//*[@id="data_i97"]'

 

 

05 데이터 크롤링

▼ 이제 필요한 데이터를 크롤링합니다. .find_element 메서드를 사용합니다. 미리 정의해둔 revenue(매출)의 XPath를 파라미터로 합니다. 결과물을 보면 각 연도의 revenue가 '\n'로 구분된 문자열(string) 형태인 것을 알 수 있습니다.

driver.find_element(By.XPATH, revenue).text

※ 약간 오래된 문법이긴 하지만 element를 찾는 데 유용한 도움말이 있습니다. 이보다 업데이트 된 문법이 'By.'을 사용하는 것인데 거기에 대한 사항은 이 글을 보시면 됩니다.

 

▼ 특정 구분자(이 경우 '\n')로 나누어져 있는 수치들을 분리해서 개별 리스트로 저장하기 위해  findall 메서드를 사용합니다. findall은 주어진 문자열 전체에서 특정 패턴을 만족하는 걸 모두 찾아서 list로 반환합니다. 웹 스크래핑이란 이런 프로세스를 반복하는 겁니다.

re.findall('(.*)\n', (driver.find_element(By.XPATH, revenue).text))

 

 

06 Scaling

이번 포스팅에서는 정말 Selenium의 기초만 다루었습니다. 한 개 기업의 재무제표를 구성하는 여러 계정들, 이에 더하여 여러 개의 종목을 스크래핑 하기 위해서는 loop 구문을 작성해야 할 수도 있습니다. 몇몇 기업들의 재무제표의 형식이 다르기 때문에 누락된 데이터를 생략하거나 하는 회피전략을 코드로 구현해야 할 수도 있습니다. Selenium에는 여러 기업의 데이터를 수집하는 경우 임의로 설정한 2초를 기다리는 대신 특정 element가 로드될 때까지 대기하고 재시도할 수 있는 기능도 있습니다.

 

 

 

요약


전체 프로세스를 요약하면 아래와 같습니다:

  1. 개발자도구로 데이터가 출력되는 방식(CSS)을 확인
  2. 무엇을 스크래핑할 건지 계획 수립 
  3. 데이터 스크래핑
  4. 리스트나 데이터 프레임으로 저장 
  5. 문자열을 숫자로 변환
  6. 복수의 기업과 그들의 재무제표를 처리하려면 loop 생성

 

댓글