본문 바로가기

프로그래밍/Python

네이버 금융 주식 데이터 웹 크롤링 - 일별시세 csv파일에 저장하기

728x90
반응형

파이썬으로 웹 크롤링

파이썬으로 빅데이터 공부를 하면서 웹 크롤링에 대해 배우게 되었다.

증시 관련 데이터를 크롤링 하려는데 네이버에서 증시 api는 제공하지 않는다.

그래서 html 태그에서 직접 크롤링을 해야했다.

 

from bs4 import BeautifulSoup
import requests
import pandas as pd
from selenium import webdriver
import time

밑의 코드들은 위의 라이브러리를 사용한다.

 

종목 코드 크롤링

주식 데이터를 검색하려면 보통 종목코드를 입력하여 크롤링 하는것이 일반적이다. 하지만 일반 사람들에게는 삼성전자, 구글 이러한 이름이 익숙하기 때문에 먼저 종목 코드 부터 크롤링 할것이다.

 

크롬 네이버에서 삼성 전자를 검색하고 종목코드가 나오는 곳을 마우스 오른쪽 검사를 누르면 자동으로 종목코드가 있는 html 태그 쪽으로 이동한다. <em class="t_nm"> 태그에 종목 코드가 있는 것을 볼 수 있다.

 

https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=1&ie=utf8&query=%EC%82%BC%EC%84%B1%EC%A0%84%EC%9E%90

 

네이버에서 단어를 검색하면 위의 링크로 나오게 되는데 %EC%82%BC%EC%84%B1%EC%A0%84%EC%9E%90 이부분이 삼성전자를 입력했던 부분이다.

 

def searchNameForNaver(name):
    url = "https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=1&ie=utf8&query="
    wd = webdriver.Chrome('./WebDriver/chromedriver.exe')
    wd.get(url+name)
    time.sleep(1) #웹 페이지 연결을 위한 기다림
    
    html = wd.page_source #wd로 웹페이지 소스를 긁어옴
    soup = BeautifulSoup(html, 'html.parser')

    tagEm = soup.find('em', attrs={'class':'t_nm'})
    print(tagEm.string)
    return tagEm.string

 

입력한 단어를 name으로 받아서 url과 합쳐주고 webdriver로 열어준다.

Selenium과 webdriver는 인터넷에 찾으면 나옴

 

BeautifulSoup로 html 객체를 만들고 t_nm 태그의 string만 return 하는 함수를 만들었다.

그러면 종목 코드만 return된다.

 

웹페이지를 열어서 html 태그에서 원하는 정보만 찾는 방법이다.

 

네이버 금융에서 일별시세 크롤링

먼저 일별 시세를 불러오기 전에 csv로 만들거라서 열을 먼저 가져올 것이다.

url = "https://finance.naver.com/item/sise_day.naver?code="
wd = webdriver.Chrome('./WebDriver/chromedriver.exe')
wd.get(url+code)
time.sleep(1)

html = wd.page_source
soup = BeautifulSoup(html, 'html.parser')

thStringList = []

thList = soup.tbody.select('th')

for th in thList:
    thStringList.append(th.string)

 

위에서 했던 것과 마찬가지로 일별시세 헤더가 있는 부분을 찾아서 리스트에 넣었다.

그리고 request.get을 사용해서 데이터들을 불러오는데 전일대비 부분에 이상한 문자열이 들어가서 없애주었다.

 

def searchFinance(code, maxPage):
    url = "https://finance.naver.com/item/sise_day.naver?code="
    wd = webdriver.Chrome('./WebDriver/chromedriver.exe')
    wd.get(url+code)
    time.sleep(1)

    html = wd.page_source
    soup = BeautifulSoup(html, 'html.parser')

	#자동으로 최대 페이지를 찾지만 아직 오류
    '''pgrr = soup.find('td', class_='pgRR')
    pgrr.a["href"].split('=')
    lastPage = int(pgrr.a["href"].split('=')[-1])'''
    
    thStringList = []
    spanStringList = []

    thList = soup.tbody.select('th')
    
    for th in thList:
        thStringList.append(th.string)
    
    #사용자가 정한 페이지 만큼 반복
    for cntPage in range(int(maxPage)):
        pageUrl = url+code+'&page='+str(cntPage+1)
        #페이지 request
        data = requests.get(pageUrl, headers={'User-agent': 'Mozilla/5.0'}).text
        
        soup = BeautifulSoup(data, 'html.parser')
        spanList = soup.select('span')
        #일별시세 제목 제거
        spanList.pop(0)

		#이상한문자열제거
        for span in spanList:
            if span.string.find('\t') != -1:
                tmp = span.string
                tmp = tmp.strip('\n')
                tmp = tmp.strip('\t')
                tmp = tmp.replace('\n', '')
                spanStringList.append(tmp)
                continue

            spanStringList.append(span.string)
    
    #2차원 배열로 만들기
    l = [spanStringList[r*7:(r+1)*7]for r in range(10*int(maxPage))]
    
    return [thStringList, l]

 

최종 코드

from bs4 import BeautifulSoup
import requests
import pandas as pd
from selenium import webdriver
import time



def searchNameForNaver(name):
    url = "https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=1&ie=utf8&query="
    wd = webdriver.Chrome('./WebDriver/chromedriver.exe')
    wd.get(url+name)
    time.sleep(1)
    
    html = wd.page_source
    soup = BeautifulSoup(html, 'html.parser')

    tagEm = soup.find('em', attrs={'class':'t_nm'})
    print(tagEm.string)
    return tagEm.string
    

def searchFinance(code, maxPage):
    url = "https://finance.naver.com/item/sise_day.naver?code="
    wd = webdriver.Chrome('./WebDriver/chromedriver.exe')
    wd.get(url+code)
    time.sleep(1)

    html = wd.page_source
    soup = BeautifulSoup(html, 'html.parser')

    '''pgrr = soup.find('td', class_='pgRR')
    pgrr.a["href"].split('=')
    lastPage = int(pgrr.a["href"].split('=')[-1])'''
    
    thStringList = []
    spanStringList = []

    thList = soup.tbody.select('th')
    
    for th in thList:
        thStringList.append(th.string)
    
    for cntPage in range(int(maxPage)):
        pageUrl = url+code+'&page='+str(cntPage+1)
        data = requests.get(pageUrl, headers={'User-agent': 'Mozilla/5.0'}).text
        
        soup = BeautifulSoup(data, 'html.parser')
        spanList = soup.select('span')
        spanList.pop(0)

        for span in spanList:
            if span.string.find('\t') != -1:
                tmp = span.string
                tmp = tmp.strip('\n')
                tmp = tmp.strip('\t')
                tmp = tmp.replace('\n', '')
                spanStringList.append(tmp)
                continue

            spanStringList.append(span.string)
    
    l = [spanStringList[r*7:(r+1)*7]for r in range(10*int(maxPage))]
    
    return [thStringList, l]


def main():
    result = []
    print("크롤링 시작 >")
    searchName = input('검색 기업을 입력하시오: ')
    maxPage = input('최대 페이지를 입력하시오: ')
    code = searchNameForNaver(searchName)
    result = searchFinance(code, maxPage)
    
    CB_tbl = pd.DataFrame(result[1], columns = tuple(result[0]))
    CB_tbl.to_csv('./today.csv', encoding='cp949', mode='w', index=True)
    

if __name__ == '__main__':
    main()

728x90
반응형