본문 바로가기
방구석코딩/주식 크롤링 분석

[파이썬] 주식 크롤링 매크로화(4) - 파이썬으로 데이터 가져오기 함수정의

by 석세상 2024. 8. 16.
반응형

다음은 파이선에서 주식 데이터를 웹 페이지에서 실제로 파이썬으로 가져오는 작업이다. 이전에 한번 끝까지 실행하는 부분은 파이썬으로 데이터를 가져오는 부분과 동시에 csv 파일로 저장하였는데 이 부분을 분리하여 작업하였다.

 

 

1. 기존 코드 분석

기존 코드를 보면 맨 처음엔 웹 주소, 다음에는 for문에서 네이버 증권 종목들을 1페이지에서 45페이지까지 반복하여 데이터를 df에 저장하고 불필요한 데이터를 제거한다. f_name부터는 파이썬의 데이터를 csv에 저장하는 부분이다.

 

사실 나는 애초에도 for문 부분과 csv에 저장하는 이 두 부분을 따로 분리하여 작업하고 싶었지만 반복문에 그냥 적용하게 되면 df에 덮어쓰기로 진행되어 맨 마지막 반복문의 결과만 df에 나타났다.

 

데이터를 파이썬으로 불러오는 부분과 csv에 저장하는 부분을 따로 분리하고 싶었던 이유는 2가지 작업이 동시에 진행되면 둘 중 하나의 문제가 생겼지만 진행할 수 있기 때문이다.

 

하나의 작업 단위로 분리되어 있는 편이 향후에 문제가 발생했을 경우에 그 부분만 수정하면 되기 때문에 분리하여 작업하는 것이 좋다.

 

하지만 현재 코드의 장점은 파이썬은 메모리에 올려두기 때문에 df라는 같은 이름으로 1페이지씩 가져와서 csv에 저장한 뒤 다시 df에 2페이지의 정보만, 그 다음 반복에서는 3페이지의 정보만 들고있기 때문에 한페이지씩의 정보만큼의 메모리만 쓴다.

 

메모리가 심하게 부족한 성능의 PC라면 괜찮은 방법일 수 있지만 45페이지까지 모든 데이터를 다 가져와도 큰 무리가 없다고 판단해서 코드를 분리해서 작업하도록 변경하겠다.

 

이 부분을 아래에서 해결해 보자.

p_url = 'https://finance.naver.com/sise/sise_market_sum.naver?sosok=0&page='

#############################################
# (1) 1페이지부터 마지막 페이지까지 필요 테이블 불러오기
for idx in range(1, 46) :                        # 마지막 페이지까지 반복, mk_lspg_num 해당 시장 종목 페이지 마지막 번호
    browser.get(p_url + str(idx))                # http 주소는 문자이기 때문에 str을 이용하여 숫자를 문자로 변경해줘야함
    
    # df = pd.read_html(browser.page_source)
    df = pd.read_html(browser.page_source)[1]     # 아래에서 각 테이블 정보를 확인해서 필요한 정보가 들어있는 [1] 테이블의 정보를 가져옴

    
    #############################################
    # (2) 불필요한 데이터 정제
    df.dropna(axis = 'index', how = 'all', inplace = True)
    df.dropna(axis = 'columns', how = 'all', inplace = True)       # columns는 컬럼 기준으로 적용


f_name = '/Users/hd/Documents/python/stock_pgm/01.raw_data/kospi.csv'

# 파일이 있다면 헤더 제외
if os.path.exists(f_name) :
    print("파일이 존재합니다.")
    #info_dt_table.to_csv(f_name, encoding = 'utf-8-sig', index = False, mode = 'w', header = True)
    # 한글 자료로 인해 인코딩이 필요, encoding = 'utf-8-sig'
    # index = False는 맨 왼쪽의 1,2,3,4.. 제외 
    # mode = 'a'는 자료를 아래로 append시킴
    # header = False 헤더 제외

# 파일이 없는 경우 헤더 포함, 첫 파일 생성 시
else :
    info_dt_table.to_csv(f_name, encoding = 'utf-8-sig', index = False, header = True)

 

2. 반복문 데이터 누적하여 생성하기

먼저 csv 파일을 저장하는 f_name부터는 삭제하고 데이터를 파이썬으로 가져오는 부분만 해결하자. 여기서 문제점은 반복 실행 시 해당 데이터가 덮어쓰기 된다는 것이다. 그러면 이 부분을 누적하여 처리할 수 있지 않을까라는 생각에 많은 자료를 찾아봤다.

 

꽤 오랜시간에 걸쳐 여러자료를 찾아보고 짜집기 해봐서 최종적으로 수정한 코드이다. 실제로 잘 실행되고 데이터가 잘 들어가 있는지까지 확인했다. 

#########################################################################
# 함수 정의
# 04) 데이터 가져오기
#########################################################################

p_url = 'https://finance.naver.com/sise/sise_market_sum.naver?sosok=0&page='

# 반복문을 실행하면서 데이터를 저장할 데이터프레임
# 아래 반복문을 실행하면서 데이터를 저장할 빈 데이터프레임을 생성
info_dt_table = pd.DataFrame()


def data_info_func(mk_url) :             # 시장별 페이지 마지막 번호, 시장별 주소
    global info_dt_table                              # 함수 정의 외부에 있는 변수(테이블(데이터프레임))을 가져오는 것이기 때문에 전역변수로 지정해줘야 함
    df_list = []                                      # 데이터프레임을 저장하기 위한 리스트,왜 필요한지 아래에서 보면서 확인해보자


    #############################################
    # (1) 1페이지부터 마지막 페이지까지 필요 테이블 불러오기
    for idx in range(1, 46) :                         # 마지막 페이지까지 반복, mk_lspg_num 해당 시장 종목 페이지 마지막 번호
        browser.get(mk_url + str(idx))                # http 주소는 문자이기 때문에 str을 이용하여 숫자를 문자로 변경해줘야함
        
        df = pd.read_html(browser.page_source)[1]     # 아래에서 각 테이블 정보를 확인해서 필요한 정보가 들어있는 [1] 테이블의 정보를 가져옴
        df_list.append(df)                            # 리스트에 데이터프레임 추가

        
        #############################################
        # (2) 불필요한 데이터 정제    
        df.dropna(axis = 'index', how = 'all', inplace = True)
        df.dropna(axis = 'columns', how = 'all', inplace = True)       # columns는 컬럼 기준으로 적용
        

    info_dt_table = pd.concat(df_list, ignore_index=True)
    print(f'{idx} 페이지 완료')       # 몇번째 인덱스(페이지)가 실행됐는지 확인

    return info_dt_table

 

먼저 주식 종목이 있는 페이지를 한페이지씩 바꿔주기 위해 p_url 주소를 입력해준다. 다음은 페이지가 변경될 때 1페이지, 2페이지, 3페이지, ... 45페이지까지 정보를 데이터프레임에 저장하기 위해 빈 프레임을 하나 만들어준다.

 

빈 프레임을 만들어주는 이유는 아래에서 세번째 줄에 info_dt_table =  pd.concat(df_list, ignore_index=True) 라는 코드가 있는데 info_dt_table에 뒤에 있는 정보를 입력하라는 뜻이다. 그러려면 info_dt_table라는 데이터프레임이 있어야 한다는 것이다.

 

쉽게 예를 들자면 담는 통이 있어야 그 안에 뭘 담을텐데 담는 통이 없기 때문에 미리 빈통을 만들어두는 것이다.

 

다음으로 def 부분을 보자면 이번에는 mk_url이라는 매개변수가 있는 함수를 만들었다. 코스피 종목만을 생성하면 크게 상관없지만 코스닥 정보까지 가져오기 위해 url 주소를 변경하기 위해 가져온 것이다. 또 추가로 해외종목을 가져오려고 한다면 그때도 사용될 수 있을 것 같다.

 

함수정의 첫 문장을 보면 global info_dt_table가 있는 것을 볼 수 있는데 이건 외부변수를 함수 내에서 사용하기 위해서다. 함수정의에서 사용될 수 있는 변수는 외부변수와 내부변수로 나눌 수 있는데 이는 아래 링크에서 확인하자.

 

[파이썬] 외부변수와 내부변수, 함수 내/외부에서 사용하는 방법(global)

파이썬 뿐 아니라 다른 프로그램을 사용 시에도 내부변수와 외부변수가 구분되는 프로그램이 많다. 하지만 프로그램마다 외부변수와 내부변수를 나누는 기준이 조금씩 다른데 파이썬에서는 함

gusugi.tistory.com

 

 

그 다음은 df_list라는 이름으로 빈 리스트를 생성해준다. 리스트 형태의 자료는 어떤 형태의 자료든 담을 수 있다는 장점이 있다.

 

함수정의 안에 보면 df_list.append(df) 명령문이 중간에 추가된 것을 볼 수 있는데 df에서 생성한 종목 정보를 페이지를 누적하여 리스트에 저장한다.

 

다음으로 데이터 정제하는 부분은 이전과 동일한 내용이므로 생략하고 info_dt_table = pd.concat(df_list, ignore_index=True)은 함수 밖에서 정의한 info_dt_table이라는 이름의 데이터프레임에 df_list에 있는 정보를 결합한다.

 

여기서 pd.concat은 데이터를 결합하는데 사용되는 명령문이다. 자세한 내용은 아래 링크를 참고하길 바란다.

 

[파이썬] 데이터 결합 핸들링 - concat, merge, join, append

다음은 파이썬에서 데이터프레임을 결합할 때 사용되는 concat, merge, join, append 명령어에 대해 알아보겠다. 데이터를 결합하는 명령어는 중요한 명령어 중 하나로 결합을 잘못하는 경우 원하지 않

gusugi.tistory.com

 

 

다음 print문은 45페이지까지 반복하기 때문에 어디까지 실행되고 있는지 확인하기 위해 한페이지씩 실행될때마다 몇페이지가 실행되고 있는지 체크하기 위한 문장이다.

 

문제없이 잘 실행되고 있을때는 확인할 필요가 없지만 중간에 웹 페이지가 끊기거나 오류가 발생되어 중단될 경우 어디까지 실행되었는지 확인할 수 있는 부분이다.

 

마지막으로 return info_dt_table이라는 명령문이 중요하고 또 처음에는 아무리 여러번 봐도 잘 이해가되지 않는 문장일 수 있다.

 

return문은 함수안에서 실행된 결과를 함수 외부에서 사용할 수 있는 명령문이다. 이렇게 얘기하면 앞에서 만들었던 체크박스 해제, 체크박스 선택 및 적용을 위한 함수에서는 왜 return문이 없을까?

 

여기서 생각해보면 체크박스 해제나 선택은 어떤 동작을 실행하는 것이지 그 안에서 새로운 데이터나 값들이 생성되는 것이 아니다. 만약 생성되는 새로운 값이 있더라도 함수 그 안에서 생성하는 것이 제 역할을 다하는 것이라면 return문이 필요없다.

 

return문은 함수 안에서 생성된 어떤 데이터나 값들을 함수 외부에서 불러와서 사용하기 위한 명령문이라고 생각하면 된다.

728x90

우리는 info_dt_table이라는 데이터프레임에 있는 값을 함수 외부에서 가져와 csv라는 파일에 저장해야하기 때문에 return문으로 info_dt_table이라는 결과를 return문으로 정의한 것이다.

 

그 외 함수 내부에서 만들어지는 정보 중 필요한 다른 정보가 또 있다면 return 정보1, 정보2, ... 이렇게 입력해주면 함수 외부에서 해당 정보를 사용할 수 있다.

 

return문에 대해 좀 더 자세하게 알아보고 싶다면 아래 링크를 참고해보자.

 

[파이썬] return문 사용하기, 결과 생성 명령어

파이썬에서 결과 생성을 위한 함수는 어떤게 있을까요? 앞의 내용들에서는 print문을 이용해서 출력만 해봤는데요. 출력문은 사실 결과를 보여주기 보다는 그냥 해당 부분을 사람이 확인할 수 있

gusugi.tistory.com

 

여기까지 데이터를 가져오는 부분에 대해 함수정의하는 것에 대해 알아보았다. 이번 내용은 조금 어려울 수도 있지만 혼자서 내가 만든다면 이라는 생각으로 하나 실행해보고, 변경해보고 하면 조금 더 이해하기 쉬울 것이다. 

 

또 내가 만든 코드가 무조건 옳은 것이 아니기 때문에 더 좋고 쉬운 방법으로도 만들 수 있을것이다. 다음 내용에서는 csv 파일로 저장하는 부분을 함수정의하는 방법에 대해 알아보도록 하겠다.

 

728x90
반응형

댓글