Spaces:
Sleeping
Sleeping
import os | |
import requests | |
from bs4 import BeautifulSoup | |
import pandas as pd | |
import gradio as gr | |
from openpyxl import load_workbook | |
from openpyxl.utils import get_column_letter | |
from openpyxl.styles import Alignment | |
# 스크래핑 함수 | |
def scrape_naver_stock(): | |
url = "https://finance.naver.com/sise/sise_rise.naver?sosok=1" | |
response = requests.get(url) | |
response.encoding = 'euc-kr' | |
# BeautifulSoup으로 HTML 파싱 | |
soup = BeautifulSoup(response.text, 'html.parser') | |
table = soup.find('table', class_='type_2') | |
# 테이블에서 데이터 추출 | |
rows = table.find_all('tr') | |
data = [] | |
for row in rows: | |
cols = row.find_all('td') | |
if len(cols) > 1: | |
rank = cols[0].text.strip() | |
name = cols[1].text.strip() | |
price = cols[2].text.strip().replace(",", "") | |
diff = cols[3].text.strip().replace("상한가", "▲").replace("상승", "▲").replace(",", "") | |
change_rate = cols[4].text.strip().replace("%", "").replace("+", "") | |
volume = cols[5].text.strip().replace(",", "") | |
buy_price = cols[6].text.strip().replace(",", "") | |
sell_price = cols[7].text.strip().replace(",", "") | |
buy_volume = cols[8].text.strip().replace(",", "") | |
sell_volume = cols[9].text.strip().replace(",", "") | |
per = cols[10].text.strip() | |
roe = cols[11].text.strip() | |
data.append([rank, name, price, diff, change_rate, volume, buy_price, sell_price, buy_volume, sell_volume, per, roe]) | |
# Pandas DataFrame으로 변환 | |
df = pd.DataFrame(data, columns=['순위', '종목명', '현재가', '전일비', '등락률', '거래량', '매수호가', '매도호가', '매수총잔량', '매도총잔량', 'PER', 'ROE']) | |
# 숫자 컬럼을 숫자 형식으로 변환 | |
numeric_columns = ['현재가', '전일비', '등락률', '거래량', '매수호가', '매도호가', '매수총잔량', '매도총잔량'] | |
df[numeric_columns] = df[numeric_columns].apply(pd.to_numeric, errors='coerce') | |
return df | |
# 엑셀 파일 저장 및 스타일 적용 함수 | |
def save_to_excel(): | |
df = scrape_naver_stock() | |
directory = "/mnt/data" | |
# 경로가 존재하지 않으면 생성 | |
if not os.path.exists(directory): | |
os.makedirs(directory) | |
file_path = os.path.join(directory, "naver_stock_data.xlsx") | |
# 엑셀로 저장 | |
df.to_excel(file_path, index=False, engine='openpyxl') | |
# 엑셀 파일 불러오기 | |
wb = load_workbook(file_path) | |
ws = wb.active | |
# 숫자 데이터가 있는 열을 우측 정렬로 설정 | |
alignment = Alignment(horizontal='right') | |
# 숫자 형식 적용할 열들 (1번째는 순위이므로 제외) | |
for col in range(3, ws.max_column + 1): | |
for row in range(2, ws.max_row + 1): # 첫 번째 행은 헤더이므로 제외 | |
cell = ws[f"{get_column_letter(col)}{row}"] | |
cell.alignment = alignment | |
# 엑셀 파일 저장 | |
wb.save(file_path) | |
return file_path | |
# 그라디오 UI | |
def display_stocks(): | |
df = scrape_naver_stock() | |
return df | |
# 그라디오 인터페이스 | |
with gr.Blocks() as iface: | |
# 스크래핑된 데이터 테이블 출력 | |
stock_table = gr.DataFrame(label="상승 TOP 종목") | |
download_button = gr.Button("엑셀 파일 다운로드") | |
# 버튼 클릭 시 엑셀 파일 저장 및 다운로드 제공 | |
download_output = gr.File() | |
# 버튼 클릭 시 데이터 업데이트 | |
download_button.click(save_to_excel, outputs=download_output) | |
# 스크래핑된 데이터를 UI에 로드 | |
iface.load(fn=display_stocks, inputs=[], outputs=stock_table) | |
iface.launch(share=True) | |