Yahoo Finance에서 주식 데이터를 실시간으로 수집하기
시시각각 변하는 주식 시장! 실시간으로 주식 데이터를 수집해 주기적으로 저장하고 싶다면 어떻게 해야 할까요?
이번 수업에서는 Selenium
을 활용하여 Yahoo Finance에서 주식 데이터를 동적으로 추출하는 방법을 알아보겠습니다.
동적 데이터 추출하기
동적 데이터는 웹 페이지의 두뇌 역할을 하는 JavaScript
로 생성되는 데이터로, 사용자가 웹사이트에 접속한 후에 생성되거나 특정 행동을 취하면 변경될 수 있습니다.
이와 같은 동적 데이터는 BeautifulSoup
과 Requests
로는 가져올 수 없습니다.
하지만 Selenium
을 사용하면 웹 페이지에서 JavaScript를 실행하고, 동적 데이터를 가져올 수 있습니다.
실습 화면의 코드를 단계별로 살펴보겠습니다.
실습 코드내 이해하기 어려운 부분은 학습 도구의 AI 튜터
를 활용해 질문해 보세요.
1. 필요한 패키지 불러오기
-
selenium
: 웹 페이지에서 동적인 데이터를 가져옵니다. -
pandas
: 데이터를 표 형태로 정리하고 처리합니다. -
webdriver
: Selenium을 사용해 웹 브라우저를 제어합니다. -
By
: 웹 페이지에서 요소를 찾는 방법을 지정합니다. -
ActionChains
: 웹 페이지에서 마우스와 키보드 동작을 수행합니다. -
EC
: 웹 페이지에서 요소가 나타날 때까지 기다립니다.
2. 웹 브라우저 열기
# Chrome 웹드라이버를 실행하여 브라우저 창 열기
driver = webdriver.Chrome()
# Yahoo Finance의 'Markets' 페이지로 이동
driver.get('https://finance.yahoo.com/markets/')
크롬 브라우저를 실행하고 Yahoo Finance
의 'Markets' 페이지로 이동합니다.
참고로 Selenium은 크롬, 파이어폭스 등 다양한 브라우저를 지원합니다.
3. 페이지가 완전히 로드될 때까지 대기
# 페이지가 완전히 로드될 때까지 대기 (최대 10초 대기)
wait = WebDriverWait(driver, 10)
웹 페이지가 완전히 로드될 때까지 최대 10초 동안 기다립니다.
웹 페이지는 로드 시간이 필요할 수 있기 때문에, 요소들이 준비될 때까지 기다리는 시간을 설정합니다.
4. 'Americas' 섹션을 찾고, 스크롤 이동하기
# 'Americas'라는 텍스트를 가진 h3 태그 찾기
americas_section = wait.until(EC.presence_of_element_located((By.XPATH, "//h3[text()='Americas']")))
# 'Americas' 섹션까지 스크롤 이동
actions = ActionChains(driver)
# 'Americas' 섹션으로 마우스 이동
actions.move_to_element(americas_section).perform()
XPATH
는 XML 문서의 특정 부분을 찾기 위한 경로 표현 방법입니다.
예를 들어 위와 같이 'Americas'라는 텍스트를 가진 h3 요소
는 /h3[text()='Americas']
로 표현할 수 있습니다.
XPATH는 웹 페이지에서 요소를 찾을 때 사용하는 방법 중 하나입니다.
move_to_element
는 'Americas' 섹션으로 화면을 스크롤합니다.
5. 'Americas' 섹션에서 테이블 찾기
# 'Americas' 섹션의 부모 요소에서 테이블 찾기
parent_section = americas_section.find_element(By.XPATH, "./ancestor::section[contains(@data-testid, 'world-indices')]")
# 테이블 찾기
table = parent_section.find_element(By.XPATH, ".//table")
"Americas" 섹션이 속한 상위 section
태그에서 table
요소를 찾습니다.
"./ancestor::section[contains(@data-testid, 'world-indices')]"
는 "Americas" 섹션의 부모 요소인 section
태그를 찾는 XPATH입니다.
이 테이블에는 우리가 필요한 데이터(예: 지수 이름, 가격 등)가 포함되어 있습니다.
6. 테이블의 헤더와 데이터 수집
# 테이블의 헤더 추출
headers = [header.text for header in table.find_elements(By.XPATH, ".//th")]
# 테이블의 행 추출
rows = table.find_elements(By.XPATH, ".//tbody/tr")
table.find_elements(By.XPATH, ".//th")
는 테이블 내에서 th
태그를 찾아 헤더를 추출합니다.
th(Table Header) 태그는 테이블의 열 이름(예: "Name", "Price")을 나타내는 HTML 태그입니다.
테이블의 각 열(th
)에 해당하는 헤더(예: "Name", "Price")를 리스트에 저장합니다.
tbody/tr
을 통해 테이블의 각 행(tr
, table row)에 있는 데이터를 추출합니다.
7. 각 행에서 'Name'과 'Price' 값을 추출하여 저장
# 데이터 저장을 위한 리스트 초기화
table_data = []
# 각 행의 열 데이터를 추출하여 리스트에 추가
for row in rows:
# 각 행의 열 데이터를 추출
columns = row.find_elements(By.XPATH, ".//td")
row_data = {} # 먼저 빈 딕셔너리 생성
# headers 리스트와 columns 리스트의 길이가 같다고 가정
for i in range(len(headers)):
# headers 리스트의 i번째 요소를 가져옴
header = headers[i]
# columns 리스트의 i번째 요소의 텍스트를 가져옴
column_value = columns[i].text
# header를 키로, column_value를 값으로 하여 딕셔너리에 추가
row_data[header] = column_value
# 데이터를 리스트에 추가
table_data.append(row_data)
각 행에 있는 데이터를 반복(for
문)하면서, td
태그에 있는 데이터(열 값들)를 추출합니다.
이 데이터를 row_data
변수에 딕셔너리 형태로 저장합니다.
딕셔너리의 키는 header
(헤더)이고, 값은 column_value
(열 값)입니다.
마지막으로, table_data
리스트에 딕셔너리를 추가합니다.
8. pandas를 사용해 데이터프레임으로 변환
# 추출된 데이터를 판다스 데이터프레임으로 변환
df = pd.DataFrame(table_data)
# 'Symbol'과 'Price' 컬럼만 선택하여 정렬된 데이터프레임 출력
df_filtered = df[['Symbol', 'Price']]
# 정렬된 데이터 출력
print(df_filtered)
추출한 데이터를 pandas.DataFrame
으로 변환합니다.
데이터 프레임에는 테이블의 데이터가 아래와 같이 저장됩니다.
Name | Price |
---|---|
... | ... |
... | ... |
9. 'Name'과 'Price' 컬럼만 선택하고 정렬
df_filtered = df[['Symbol', 'Price']]
데이터프레임에서 'Name'과 'Price' 컬럼만 선택하고, 'Name' 컬럼을 기준으로 정렬합니다.
다음 내용이 궁금하다면?
코드프렌즈 PLUS 멤버십 가입 or 강의를 등록해 주세요!