허깅페이스 스페이스에서의 app.py 개선해주신 이 코드 제대로 작동되네요. 새로고침되어 대화내용이 사라지므로 그냥 이렇게만이라도 보고는 해야 될 것 같아서요. 끝. (굳바이메세지(그냥): OpenAI ChatGPT4o mini Online에서 보다는 시행착오가 적은편; ChatGPT4o mini에서도 Gradio 등이 업그레이드되면서 바뀐 것으로 코드를 수없이 바꾼 후에야 가장 간단한 앱이 만들어졌었죠; 더 많은 기능을 담은 앱으로 만들려면 OpenAI o1 mini나 OpenAI o1이 적합한 것 같아서 첫번째 앱이라고 할 앱을 이곳에서 마무리하려고 했던 것임.)


import gradio as gr
import re
import tempfile

def extract_html_from_mht(file, start_pattern="<!DOCTYPE html", end_pattern="</html>", mode="무효 처리", occurrence=None):
    if file is None:
        return "파일이 업로드되지 않았습니다.", None

    try:
        # 'binary' 타입으로 파일 내용을 직접 디코딩
        file_content = file.decode('utf-8', errors='ignore')
    except Exception as e:
        return f"파일을 읽는 중 오류가 발생했습니다: {e}", None

    # 정규 표현식 패턴 생성
    # 사용자가 입력한 패턴의 특수문자를 이스케이프 처리
    pattern = re.escape(start_pattern) + r'(.*?)' + re.escape(end_pattern)

    matches = re.finditer(pattern, file_content, re.DOTALL | re.IGNORECASE)

    matches_list = [match.group(0) for match in matches]

    if not matches_list:
        return "지정한 패턴에 맞는 내용이 파일에서 발견되지 않았습니다.", None

    if mode == "모두 추출":
        extracted_content = "\n\n".join(matches_list)
    elif mode == "특정 번째 추출":
        if not occurrence:
            return "추출할 Occurrence을 입력해주세요.", None
        try:
            index = int(occurrence) - 1
            if index < 0 or index >= len(matches_list):
                return f"입력한 occurrence({occurrence})가 범위를 벗어났습니다. 총 {len(matches_list)}개의 매치가 있습니다.", None
            extracted_content = matches_list[index]
        except ValueError:
            return "Occurrence은 숫자여야 합니다.", None
    elif mode == "무효 처리":
        if len(matches_list) > 1:
            return f"패턴이 여러 번 발견되었습니다 ({len(matches_list)}회). 무효로 처리됩니다.", None
        extracted_content = matches_list[0]
    else:
        return "유효하지 않은 처리 모드입니다.", None

    # 임시 파일 생성 및 내용 쓰기
    try:
        with tempfile.NamedTemporaryFile(delete=False, suffix=".html", mode='w', encoding='utf-8') as temp_file:
            temp_file.write(extracted_content)
            temp_file_path = temp_file.name
    except Exception as e:
        return f"임시 파일을 생성하는 중 오류가 발생했습니다: {e}", None

    return None, temp_file_path

def toggle_occurrence_visibility(mode):
    return gr.update(visible=(mode == "특정 번째 추출"))

with gr.Blocks() as demo:
    gr.Markdown("# 파일에서 특정 부분 추출 및 다운로드")
    gr.Markdown("""
    이 앱을 사용하면 업로드한 MHT 또는 HTML 파일에서 특정 패턴에 맞는 부분을 추출하여 다운로드할 수 있습니다.
    """)

    with gr.Row():
        with gr.Column():
            file_input = gr.File(
                label="파일 업로드",
                file_types=["text", "html", "mht"],
                type="binary"  # 'binary'로 수정
            )
            start_input = gr.Textbox(
                label="시작 패턴",
                value="<!DOCTYPE html>",
                placeholder="시작 부분을 지정하세요 (예: <!DOCTYPE html>)"
            )
            end_input = gr.Textbox(
                label="끝 패턴",
                value="</html>",
                placeholder="끝 부분을 지정하세요 (예: </html>)"
            )
            mode_dropdown = gr.Dropdown(
                label="매치 처리 방식",
                choices=["무효 처리", "모두 추출", "특정 번째 추출"],
                value="무효 처리"
            )
            occurrence_input = gr.Textbox(
                label="추출할 Occurrence 번호 (mode가 '특정 번째 추출'일 때)",
                placeholder="예: 1",
                visible=False
            )
            extract_button = gr.Button("부분 추출 및 다운로드")

        with gr.Column():
            output_message = gr.Markdown("")
            download_output = gr.File(label="추출된 파일 다운로드")

    mode_dropdown.change(
        fn=toggle_occurrence_visibility,
        inputs=mode_dropdown,
        outputs=occurrence_input
    )

    extract_button.click(
        fn=extract_html_from_mht,
        inputs=[file_input, start_input, end_input, mode_dropdown, occurrence_input],
        outputs=[output_message, download_output]
    )

    demo.launch()