작성
·
309
0
import time
import pandas as pd
def get_item_info(item_code):
item_url = f'https://finance.naver.com/item/main.naver?code={item_code}'
tables = pd.read_html(item_url, encoding='cp949')
# if len(tables) == 13: # 코넥스를 거르기 위해 추가함
# continue
item_info = [] # 빈 리스트 생성
finance_info = tables[3].iloc[:,[0,-2]]
finance_info.columns = [0,1] # 합치기 전 칼럼명 일치시켜주기
item_info.append(finance_info)
for t in tables:
if t.shape[1] == 2:
item_info.append(t)
df_item = pd.concat(item_info)
df_item = df_item.set_index(0).T
time.sleep(0.2) # 과부하 막기 위한 지연 조회, 최소 0.1 이상.
return df_item
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt # 한글폰트 위함
import datetime
plt.style.use("seaborn-v0_8-talk")
font_family = "Malgun Gothic"
plt.rc("font", family = font_family)
plt.rc("axes", unicode_minus=False)
url = 'https://finance.naver.com/sise/sise_group_detail.naver?type=upjong&no=282'
table = pd.read_html(url, encoding='cp949')
raw = table[2]
raw = raw.dropna(how='all').dropna(axis=1, how='all') #추가해서 칼럼도 모두 결측치시 삭제.
today = datetime.datetime.today()
today = today.strftime('%y%m%d')
raw['종목명전처리'] = raw['종목명'].str.replace('*','', regex=True) # 문자치환
raw['종목명전처리'] = raw['종목명전처리'].str.strip() # 앞뒤 공백 제거
import FinanceDataReader as fdr
df_krx = fdr.StockListing('KRX')
# print(df_krx[['Code','Name']])
df_item_code_name = df_krx[['Code','Name']]
# 위의 종목명_전처리 칼럼과 Name 칼럼을 연결지어서 코드 잡아준다.
df_item_code_name.columns = ['종목코드', '종목명전처리']
raw = raw.merge(df_item_code_name) # 강의에서 df에 해당함
# progress_apply는 map의 사용방법을 되짚어보면서 봐라. 일괄적으로 함수 적용시 사용.
# 진행사항을 보려면 progress_apply을 사용하면 된다.
from tqdm.auto import tqdm
tqdm.pandas()
result = raw['종목코드'].progress_apply(get_item_info)
# result로 받아서 데이터프레임 형식으로 concat 해줘야해서 tolist() 사용함
df_item_info = pd.concat(result.tolist())
# print(df_item_info['종목코드']) # 출력해보면 종목코드가 없다. 그래서 넣기
# df_item_info['종목코드'] = raw['종목코드'] # 아래의 reset_index를 위해 비활성화함
# print(df_item_info['종목코드'])
# 위에서 index값이 1로 모두 같아 종목코드가 모두 동일 하므로 아래처럼 인덱스 다시 적용
df_item_info = df_item_info.reset_index()
df_item_info['종목코드'] = raw['종목코드']
# print(df_item_info['종목코드'])
# 위와 같이 작업 후 index라는 칼럼을 삭제해 준다.
del df_item_info['index']
# print(raw.shape)
df_info = raw.merge(df_item_info) # 따로 지정 안해줘도 종목코드가 같기에 합쳐진다.
# 파일명 만들기
file_name_1 = url.split('=')[1].replace('&','_')
file_name_2 = url.split('=')[2]
file_name = f'{file_name_1}_{file_name_2}.csv'
# 저장하기
df_info.to_csv(file_name, index=False, encoding='cp949')
위와 같이 코드를 작성하고
실행 했는데요.
제목과 같은 오류가 발생 했습니다.
원인을 찾아 본 결과.
코넥스 종목이 포함되어 있어서
칼럼명이 맞지 않아 발생하는 것으로 보입니다.
위의 이미지와 같이 코넥스 종목은
코스닥, 코스피 종목 처럼
table 개수 13개 보다 적게 나오므로
if문으로 table개수가 13개 이하이면
건너띄어 데이터를 받게 하면 오류가 발생하지
않을 것 같은데요.
if 문을 함수 어느 위치에 넣으면 좋을지 모르겠어서
질문 드립니다.
어느 위치에 if문을 넣어서 해결하면 좋을까요?
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
코넥스 종목으로 인한 ‘Reindexing only valid with uniquely valued Index objects’ 오류가 발생하는 부분을 해결하려면, 코넥스 종목의 테이블 개수가 일반적인 종목과 다른 점을 감지하여 해당 종목의 처리를 건너뛸 수 있도록 get_item_info
함수 내에 조건문을 추가하는 것이 좋습니다. 이 경우, 함수가 각 종목 정보를 가져오는 과정에서 적절한 테이블 개수를 확인하고 처리할 수 있도록 로직을 구성해야 합니다.
오류 메시지가 나타나는 원인 중 하나는 합치려는 DataFrame들의 인덱스 값이 중복되어 pandas가 올바른 결과를 생성할 수 없기 때문입니다. 테이블 개수를 확인하여, 코넥스 종목일 경우(테이블 개수가 13개 이하일 경우) 그 처리를 건너뛰려면, get_item_info
함수 내에서 테이블 개수를 확인하는 조건문을 삽입해야 합니다.
다음은 수정할 수 있는 코드의 일부입니다:
def get_item_info(item_code):
...
tables = pd.read_html(item_url, encoding='cp949')
# 코넥스 종목이라면 건너뛰기 위한 조건문 추가
if len(tables) < 13: # 예외 처리: 코넥스 종목일 경우 건너뛰기
return pd.DataFrame() # 빈 데이터프레임 반환
# 기존의 처리 로직 계속...
...
이렇게 수정하면, get_item_info
함수는 코넥스 종목에 대해서는 빈 데이터프레임을 반환하고 일반적인 처리 과정을 건너뛰게 됩니다. 이 후의 코드에서는 반환된 빈 데이터프레임을 concat 하더라도 오류가 발생하지 않을 것입니다.
코드 중간에 주어진 이미지 URL을 참조하셔서 오류 발생 상황과 관련된 데이터 구조를 더 정확히 이해하고 필요에 따라 조건문을 적절히 조정하시면 됩니다. 이미지의 원본 URL도 함께 참고하실 수 있습니다:
- 이미지 URL: https://cdn.inflearn.com/public/files/posts/c36b0951-bfa5-421f-bfd3-f6d800705851/2024-03-05_3-17-06.png
- 원본 URL: 정보가 제공되지 않았습니다.
참고로, 제공된 이미지는 특정 종목에 대한 증권 시세 페이지의 스크린샷으로, 한국 증권 거래소(KOSPI 또는 KOSDAQ)에서 거래되는 회사의 종목으로 보입니다. 이미지는 2023년 4월 3일에 촬영된 것으로 보이며, 주식의 가격 하락을 나타내는 정보와 차트를 포함하고 있습니다.
추가적인 질문이 있으시면 언제든지 문의해 주세요.