본문 바로가기

Data Handling/Data Collecting

pandas.read_html() - 네이버 금융 두바이유 시세 크롤링

크롤링을 하고자 하는 데이터가 table형식으로 되어 있다면 pandas의 read_html()을 이용할 수 있습니다.

 

 

 

예시를 통해서 바로 시작해보겠습니다.

다음은 네이버 금융에서 두바이유를 검색했을때 페이지 화면입니다.

 

여기서 바로 read_html을 통해서 모든 table형식의 데이터를 가져올수 있겠지만,

저희가 필요한 것만 가져오면 시간도 절약되고 처리과정도 줄어들것입니다.

 

 

저희가 필요한 정보를 두바이유의 '일별 시세'라고 가정했을때,

일별 시세만 보이는 url을 찾을 수 있을까요?

네, 가능합니다.

 

 

'일별 시세'의 2페이지를 마우스 우클릭 해보시면 새 탭에서 링크 열기가 보이실 겁니다.

그렇게 링크를 열면 '일별 시세'만 보이는 url에 접근하실 수 있습니다.

사실 2페이지를 누른다는건 2페이지의 url로 들어가겠다는 것인데, 
그 행위를 새 창에서 진행하면서 보이지 않던 url이 보이게 되는 원리입니다.

 

 

 

이제 url을 알았으니 코드를 구현해봅시다.

1 페이지에 있는 데이터 table을 가져와보겠습니다.

import pandas as pd

# url 복사, 붙여넣기
url = 'https://finance.naver.com/marketindex/worldDailyQuote.nhn?marketindexCd=OIL_DU&fdtc=2&page=1'

# 해당 url에 있는 데이터프레임 가져오기
# 한글이 포함되어 있다 : encoding= 'utf-8'
# 원하는 내용이 포함된 데이터프레임만 가져오고 싶다 : match = '원하는 내용'
# 특정 행을 열 명으로 사용하고 싶다 : header = 0
data = pd.read_html(url)

이렇게 가져오면 데이터프레임 뭉텅이들이 리스트 형태로 가져와지게 됩니다.

물론 저희는 데이터프레임이 하나인 url로 접근했기 때문에 리스트에 하나만 들어와 있지만 어쨌든 리스트에 포함되어 있기 때문에 인덱스를 사용하여 꺼내줍니다.

 

 

data_df = data[0]

 

 

주석을 제외하면 총 세 줄에 크롤링을 마쳤습니다. 

하지만 문제는 하나의 데이터프레임만 필요로 하는 작업은 없다는 것입니다.

원하는 날짜까지 페이지를 넘기며 데이터를 가져오고, 데이터가 없는 주말은 결측치 처리를 해주는 등 실제로 사용해보기 위해서는 더 많은 작업이 필요합니다.

 

 


 

 

2018-02-01~ 2020-05-18 사이 두바이유, WTI, 브렌트유 총 세가지 원유가격을 크롤링하는 전체 코드 공유해드립니다.

데이콘의 '김나맥' 님의 크롤링 코드를 참고했으며, 출처는 마지막에 표시하겠습니다.

import time
from datetime import datetime

def get_oil_price(code):
    delay = 0.01
    page = 1
    result = []
    start_date = '2018.02.01'
    end_date = '2020.05.18'
    start_time = datetime.now()
    
    # 수집
    print('[{}] 데이터 수집을 시작합니다. (code: {})'.format(start_time.strftime('%Y/%m/%d %H:%M:%S'), code))
    while(True):
        url = 'https://finance.naver.com/marketindex/worldDailyQuote.nhn?marketindexCd={}&fdtc=2&page={}'.format(code, page)
        data = pd.read_html(url)[0].dropna()
        if page != 1:
            try:
                if start_date in data.iloc[:,0].values:
                    data = data.loc[:data.iloc[:,0].values.tolist().index(start_date),]
                    result.append(data)
                    break
            except:
                break
        result.append(data)
        page += 1
        time.sleep(delay)
    
    # 가공
    oil_price = pd.concat(result).reset_index(drop=True)
    oil_price.columns = ['date', 'price', '전일대비', '등락율']
    oil_price = oil_price.loc[oil_price['date'].tolist().index(end_date):,]
    oil_price['date'] = oil_price['date'].apply(lambda x: datetime.strptime(x, '%Y.%m.%d'))
    oil_price = oil_price[['date', 'price']]
    oil_price.insert(0, 'code', code)
    oil_price = oil_price[::-1].reset_index(drop=True)
    
    end_time = datetime.now()
    print('[{}] 데이터 수집을 종료합니다. (code: {}, 수집시간: {}초, 데이터수: {:,}개)'.format(end_time.strftime('%Y/%m/%d %H:%M:%S'), code, (end_time-start_time).seconds, len(oil_price)))
    return oil_price
    
oil_price_du = get_oil_price('OIL_DU')
oil_price_wti = get_oil_price('OIL_CL')
oil_price_brent = get_oil_price('OIL_BRT')

 

 

 


 

 

- 참고한 자료 출처 : 데이콘 '김나맥' 님

https://dacon.io/competitions/official/235606/codeshare/1037?page=1&dtype=recent&ptype=pub

 

공공 데이터 활용 전력수요 및 SMP 예측 AI 경진대회

출처 : DACON - Data Science Competition

dacon.io