import gradio as gr import pandas as pd import re from io import BytesIO import tempfile def process_excel(file_bytes): """ 업로드된 엑셀 파일에서 D4셀부터 D열의 상품명을 추출하여, 각 셀에서 특수문자를 제거한 후 공백 기준으로 키워드를 추출합니다. 한 셀 내에서 중복된 키워드는 한 번만 카운트하고, 전체 셀에 대해 키워드의 빈도를 계산하여 엑셀 파일과 표(데이터프레임)로 결과를 출력합니다. 에러 발생 시, 에러 메시지를 텍스트 파일과 데이터프레임 형태로 반환합니다. """ # 엑셀 파일 읽기 try: df = pd.read_excel(BytesIO(file_bytes), header=None, engine="openpyxl") except Exception as e: error_message = "엑셀 파일을 읽는 중 오류가 발생하였습니다: " + str(e) temp_error = tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="wb") temp_error.write(error_message.encode("utf-8")) temp_error.close() error_df = pd.DataFrame({"에러": [error_message]}) return temp_error.name, error_df # 엑셀 파일 형식 체크 (최소 4열, 최소 4행) if df.shape[1] < 4 or df.shape[0] < 4: error_message = "엑셀 파일의 형식이 올바르지 않습니다." temp_error = tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="wb") temp_error.write(error_message.encode("utf-8")) temp_error.close() error_df = pd.DataFrame({"에러": [error_message]}) return temp_error.name, error_df # D열(4번째 열, 인덱스 3)에서 4행(인덱스 3)부터 데이터를 가져옴 product_names_series = df.iloc[3:, 3] product_names_series = product_names_series.dropna() keyword_counts = {} for cell in product_names_series: # 문자열이 아닌 경우 문자열로 변환 if not isinstance(cell, str): cell = str(cell) # 특수문자 제거 (숫자, 영문, 한글, 공백을 제외한 문자 제거) cleaned = re.sub(r'[^0-9a-zA-Z가-힣\s]', '', cell) # 공백 기준으로 키워드 분리 keywords = cleaned.split() # 하나의 셀 내 중복 키워드는 제거 unique_keywords = set(keywords) for keyword in unique_keywords: keyword_counts[keyword] = keyword_counts.get(keyword, 0) + 1 # 키워드를 빈도 내림차순(빈도가 같으면 키워드 오름차순)으로 정렬 sorted_keywords = sorted(keyword_counts.items(), key=lambda x: (-x[1], x[0])) # 결과를 DataFrame으로 생성 (A1: "키워드", B1: "빈도") result_df = pd.DataFrame(sorted_keywords, columns=["키워드", "빈도"]) # 엑셀 파일 생성 (A1, B1 셀에 헤더 추가) output = BytesIO() try: with pd.ExcelWriter(output, engine="openpyxl") as writer: result_df.to_excel(writer, index=False, startrow=1, header=False) worksheet = writer.sheets["Sheet1"] worksheet.cell(row=1, column=1, value="키워드") worksheet.cell(row=1, column=2, value="빈도") output.seek(0) except Exception as e: error_message = "엑셀 파일을 생성하는 중 오류가 발생하였습니다: " + str(e) temp_error = tempfile.NamedTemporaryFile(delete=False, suffix=".txt", mode="wb") temp_error.write(error_message.encode("utf-8")) temp_error.close() error_df = pd.DataFrame({"에러": [error_message]}) return temp_error.name, error_df # 임시 엑셀 파일 생성 후 경로 반환 temp_excel = tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx", mode="wb") temp_excel.write(output.getvalue()) temp_excel.close() return temp_excel.name, result_df # 그라디오 인터페이스 생성 (엑셀 파일과 결과 표 두 가지 형태로 출력) iface = gr.Interface( fn=process_excel, inputs=gr.File(label="엑셀 파일 업로드", type="binary"), outputs=[ gr.File(label="결과 엑셀 파일"), gr.DataFrame(label="키워드 분석 표") ], title="엑셀 상품명 키워드 추출 및 빈도 분석", description=( "엑셀 파일의 D4셀부터 D열에 있는 상품명 데이터를 분석하여, " "특수문자를 제거한 후 공백 기준으로 키워드를 추출합니다. " "한 셀 내에서 중복된 키워드는 한 번만 카운트하며, 최종적으로 키워드와 빈도를 " "내림차순으로 정리한 결과를 엑셀 파일과 표(데이터프레임)로 출력합니다." ) ) iface.launch()