크롤링을 하고자 하는 데이터가 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
'Data Handling > Data Collecting' 카테고리의 다른 글
selenium - 지하철역 인근 점포 수(카페, 호프집, 제과점 등) 크롤링 (0) | 2020.11.03 |
---|---|
selenium - 부킹닷컴 객실 가격 크롤링 (5) | 2020.06.03 |
beautifulsoup - 부킹닷컴 호텔 이름, 평점 크롤링 (0) | 2020.06.03 |
공공데이터포털 API - 대한민국 국경일 및 공휴일 (0) | 2020.06.02 |
API의 필요성 (0) | 2020.06.02 |