import re import requests import pandas as pd import gradio as gr # 디버깅: 스크래핑 과정을 로그로 확인하기 위함 def debug_print(*args): print("[DEBUG]", *args) def scrape_data(market_type: str): """ market_type (str): '0' -> 코스피, '1' -> 코스닥 네이버 증권의 '상승 종목' 페이지에서 해당 market_type의 정보를 스크래핑. (BeautifulSoup / lxml 없이 정규표현식만 사용) """ # market_type에 따라 URL 설정 # '0'이면 코스피, '1'이면 코스닥 base_url = "https://finance.naver.com/sise/sise_rise.naver?sosok=" url = base_url + market_type debug_print("Requesting URL:", url) response = requests.get(url) debug_print("Status Code:", response.status_code) # HTML 전체 텍스트 html_text = response.text # 1) ~
구간 추출 pattern_table = re.compile( r']*class=["\']type_2["\'][^>]*>(.*?)', re.DOTALL | re.IGNORECASE ) match_table = pattern_table.search(html_text) if not match_table: debug_print("Error: Target table not found.") return [] table_html = match_table.group(1) # 2) table 내부의 단위로 나누기 pattern_tr = re.compile(r']*>(.*?)', re.DOTALL | re.IGNORECASE) rows = pattern_tr.findall(table_html) debug_print(f"Found total {len(rows)} blocks in table.") data_list = [] row_count = 0 for row_html in rows: # 3) 태그 추출 pattern_td = re.compile(r']*>(.*?)', re.DOTALL | re.IGNORECASE) cols = pattern_td.findall(row_html) # 유효한 데이터 열이 아닌 경우(또는 공백행 등) 스킵 if len(cols) < 12: continue # HTML 태그 제거 헬퍼 함수 def clean_html(raw_html): # 모든 태그 제거 text = re.sub(r'<.*?>', '', raw_html, flags=re.DOTALL) return text.strip() rank = clean_html(cols[0]) name = clean_html(cols[1]) current = clean_html(cols[2]) diff = clean_html(cols[3]) change_rate = clean_html(cols[4]) volume = clean_html(cols[5]) buy_price = clean_html(cols[6]) sell_price = clean_html(cols[7]) total_buy = clean_html(cols[8]) total_sell = clean_html(cols[9]) per_ = clean_html(cols[10]) roe_ = clean_html(cols[11]) debug_print(f"[Row {row_count}] rank={rank}, name={name}, current_price={current}") row_count += 1 data_list.append({ "순위": rank, "종목명": name, "현재가": current, "전일비": diff, "등락률": change_rate, "거래량": volume, "매수호가": buy_price, "매도호가": sell_price, "매수총잔량": total_buy, "매도총잔량": total_sell, "PER": per_, "ROE": roe_ }) return data_list def make_table(market_choice): """ market_choice (str): "코스피" 또는 "코스닥" 해당 선택에 따라 scrape_data()를 실행한 뒤 DataFrame으로 반환. """ debug_print(f"Scraping data for market_choice={market_choice}...") # 사용자가 선택박스에서 "코스피" 선택 -> '0' # 사용자가 선택박스에서 "코스닥" 선택 -> '1' market_type = "0" if market_choice == "코스피" else "1" data = scrape_data(market_type) if not data: debug_print("No data retrieved or table not found.") return pd.DataFrame(["데이터를 가져오지 못했습니다."]) debug_print("Scraping done. Converting to DataFrame.") return pd.DataFrame(data) def main(): """ Gradio 인터페이스 실행 """ with gr.Blocks() as demo: gr.Markdown("# 네이버 증권 스크래핑 : 코스피 / 코스닥 선택") # 선택박스: 코스피 / 코스닥 market_choice = gr.Dropdown( label="종목 선택", choices=["코스피", "코스닥"], value="코스피" # 기본값 ) # 버튼과 결과용 DataFrame scrape_btn = gr.Button("데이터 가져오기") output_df = gr.DataFrame(label="스크래핑 결과") # 버튼 클릭 시 스크래핑 함수 호출 scrape_btn.click(fn=make_table, inputs=market_choice, outputs=output_df) demo.launch() if __name__ == "__main__": main()