Naver Finance 크롤러 코드 설명: Pandas와 BeautifulSoup을 활용한 주식 데이터 수집
이 블로그 포스트에서는 Python을 사용해 Naver Finance 웹사이트에서 주식 데이터를 크롤링하는 코드에 대해 자세히 설명하겠습니다. 이 코드는 주식시장 데이터를 자동으로 수집하여 분석 가능한 형태로 변환한 후, 엑셀 파일로 저장하는 기능을 수행합니다. 주로 Pandas, BeautifulSoup, 그리고 requests 라이브러리를 사용합니다.
1. 필요한 라이브러리 임포트
import pandas as pd
import requests
from bs4 import BeautifulSoup
import numpy as np
from datetime import datetime
이 코드는 데이터 분석에 주로 쓰이는 Pandas, 웹 페이지 요청을 위한 requests, HTML 파싱을 위한 BeautifulSoup, 배열 연산을 위한 NumPy 및 날짜 데이터를 위한 datetime 모듈을 사용합니다.
2. 기본 설정
BASE_URL = 'https://finance.naver.com/sise/sise_market_sum.nhn?sosok='
CODES = [0, 1]
fields = []
now = datetime.now()
formattedDate = now.strftime("%Y%m%d")
- BASE_URL: 크롤링하려는 Naver Finance 사이트의 URL입니다.
- CODES: 0은 코스피, 1은 코스닥 시장을 의미합니다. 즉, 이 배열은 코스피와 코스닥 데이터를 모두 수집하기 위한 코드입니다.
- fields: 나중에 수집할 데이터의 필드(컬럼)를 담을 리스트입니다.
- now: 현재 날짜와 시간을 가져오는 코드입니다. 이를 통해 데이터가 언제 수집되었는지 추적할 수 있습니다.
3. 메인 크롤링 함수: execute_crawler()
def execute_crawler():
df_total = []
for code in CODES:
res = requests.get(BASE_URL + str(CODES[0]))
page_soup = BeautifulSoup(res.text, 'lxml')
total_page_num = page_soup.select_one('td.pgRR > a')
total_page_num = int(total_page_num.get('href').split('=')[-1])
ipt_html = page_soup.select_one('div.subcnt_sise_item_top')
global fields
fields = [item.get('value') for item in ipt_html.select('input')]
result = [crawler(code, str(page)) for page in range(1, total_page_num + 1)]
df = pd.concat(result, axis=0, ignore_index=True)
df_total.append(df)
df_total = pd.concat(df_total)
df_total.reset_index(inplace=True, drop=True)
df_total.to_excel('NaverFinance.xlsx')
return df_total
- df_total: 데이터를 담기 위한 빈 리스트입니다.
- requests.get: 각 시장(코스피 또는 코스닥)의 첫 페이지를 요청합니다. CODES[0]은 코스피를 의미하며, 나중에 code로 변경 가능합니다.
- BeautifulSoup: 요청한 페이지의 HTML 데이터를 파싱합니다. lxml 파서가 사용되었습니다.
- total_page_num: 각 시장의 마지막 페이지 번호를 얻기 위해 select_one을 사용합니다. 마지막 페이지의 URL에서 페이지 번호를 추출해 총 페이지 수를 계산합니다.
- fields: 크롤링할 데이터 필드 리스트를 추출합니다. Naver Finance 페이지에서 input 태그의 value 속성으로 필드 정보를 가져옵니다.
- result: 각 페이지에서 데이터를 수집하기 위해 crawler() 함수를 호출하고, 그 결과를 리스트로 저장합니다.
- pd.concat: 여러 페이지에서 가져온 데이터를 하나의 데이터프레임으로 합칩니다.
- to_excel: 수집된 데이터를 엑셀 파일로 저장합니다.
4. 개별 페이지 크롤링 함수: crawler()
def crawler(code, page):
global fields
data = {'menu': 'market_sum',
'fieldIds': fields,
'returnUrl': BASE_URL + str(code) + "&page=" + str(page)}
res = requests.post('https://finance.naver.com/sise/field_submit.nhn', data=data)
page_soup = BeautifulSoup(res.text, 'lxml')
table_html = page_soup.select_one('div.box_type_l')
header_data = [item.get_text().strip() for item in table_html.select('thead th')][1:-1]
inner_data = [item.get_text().strip() for item in table_html.find_all(lambda x:
(x.name == 'a' and
'tltle' in x.get('class', [])) or (x.name == 'td' and
'number' in x.get('class', []))
)]
no_data = [item.get_text().strip() for item in table_html.select('td.no')]
number_data = np.array(inner_data)
number_data.resize(len(no_data), len(header_data))
df = pd.DataFrame(data=number_data, columns=header_data)
return df
이 함수는 개별 페이지에서 주식 데이터를 수집하는 역할을 합니다.
- fields: execute_crawler에서 가져온 필드 정보를 사용합니다.
- requests.post: 각 페이지에 데이터를 요청합니다. field_submit.nhn에 POST 요청을 보내 필요한 데이터를 가져옵니다.
- header_data: 테이블의 헤더 부분(열 이름)을 추출합니다. [1:-1]은 불필요한 첫 번째와 마지막 항목을 제외합니다.
- inner_data: 주식 데이터의 각 항목을 가져옵니다. 종목명(a 태그)과 숫자 데이터(td 태그)를 선택하여 데이터를 수집합니다.
- number_data: NumPy 배열로 변환한 후, 테이블의 행과 열 크기에 맞게 데이터를 조정합니다.
- Pandas 데이터프레임: 수집된 데이터를 Pandas 데이터프레임으로 변환하고, 이후 반환합니다.
5. 전체 프로세스 요약
이 코드는 Naver Finance 사이트에서 코스피 및 코스닥의 여러 페이지에 걸쳐 주식 데이터를 수집하여, 엑셀 파일로 저장하는 간단한 크롤러입니다.
- execute_crawler(): 코스피와 코스닥 시장의 데이터를 각각 크롤링합니다.
- crawler(): 각 페이지의 데이터를 수집하여 Pandas 데이터프레임으로 변환합니다.
- 데이터 저장: 결과는 엑셀 파일(NaverFinance.xlsx)로 저장됩니다.
6. 최종 결과물
이 크롤러를 실행하면, 코스피와 코스닥 주식 데이터가 포함된 엑셀 파일이 생성됩니다. 파일에는 각 종목의 매출액, ROE, PER 등 다양한 재무 데이터가 포함됩니다.
7. 결론
이 Python 코드는 Naver Finance의 주식 데이터를 효과적으로 크롤링하고, Pandas 데이터프레임으로 처리한 후 엑셀 파일로 저장하는 방법을 보여줍니다. 이를 통해 실시간 데이터를 자동으로 수집하고, 데이터 분석 및 투자 전략에 사용할 수 있습니다.
데이터 수집 자동화는 금융 데이터 분석에서 중요한 도구이며, 이를 통해 신속하게 시장 변화를 파악할 수 있습니다.