unnastyle's picture
Update app.py
8a995e4 verified
# app.py
import gradio as gr
from bs4 import BeautifulSoup
import re
import logging
import requests # ์ถ”๊ฐ€์ฝ”๋“œ์—์„œ ์‚ฌ์šฉ
# ๋””๋ฒ„๊น… ๋กœ๊น… ์„ค์ • (์ „์ฒด ํ†ตํ•ฉ์„ ์œ„ํ•ด ํฌ๋งท ํฌํ•จ)
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
# ---------- [๋ชจ๋“ˆ1: ๊ธฐ๋ณธ์ฝ”๋“œ] ์‹œ์ž‘ ----------
# ์˜์–ด ์›”์„ ํ•œ๊ตญ์–ด ์›”๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ ์œ„ํ•œ ๋งคํ•‘
month_mapping = {
"January": "1์›”",
"February": "2์›”",
"March": "3์›”",
"April": "4์›”",
"May": "5์›”",
"June": "6์›”",
"July": "7์›”",
"August": "8์›”",
"September": "9์›”",
"October": "10์›”",
"November": "11์›”",
"December": "12์›”"
}
def convert_date_range(date_range_str):
"""
์ž…๋ ฅ๋œ '6 January - 12 January' ํ˜•ํƒœ์˜ ๋‚ ์งœ ๋ฌธ์ž์—ด์„
'1์›” 6์ผ ~ 1์›” 12์ผ' ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜.
"""
logging.debug("์›๋ณธ ๋‚ ์งœ ๋ฒ”์œ„: %s", date_range_str)
parts = date_range_str.split('-')
if len(parts) != 2:
logging.debug("๋‚ ์งœ ๋ฒ”์œ„ ํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์Œ: %s", date_range_str)
return date_range_str
start = parts[0].strip() # ์˜ˆ: "6 January"
end = parts[1].strip() # ์˜ˆ: "12 January"
start_parts = start.split()
end_parts = end.split()
if len(start_parts) < 2 or len(end_parts) < 2:
logging.debug("๋‚ ์งœ ๊ตฌ์„ฑ์š”์†Œ ๋ถ€์กฑ: %s, %s", start, end)
return date_range_str
start_day = start_parts[0]
start_month_en = start_parts[1]
end_day = end_parts[0]
end_month_en = end_parts[1]
start_month = month_mapping.get(start_month_en, start_month_en)
end_month = month_mapping.get(end_month_en, end_month_en)
converted = f"{start_month} {start_day}์ผ ~ {end_month} {end_day}์ผ"
logging.debug("๋ณ€ํ™˜๋œ ๋‚ ์งœ ๋ฒ”์œ„: %s", converted)
return converted
def process_html(html_text):
"""
์ „์ฒด ํŽ˜์ด์ง€ HTML ์ž…๋ ฅ์„ ๋ฐ›์•„์„œ ๊ณผ๋ชฉ๋ช…๊ณผ ๊ฐ ์„น์…˜๋ณ„ ๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก์„ ์ถ”์ถœํ•˜๋Š” ํ•จ์ˆ˜.
์ถ”์ถœ ๊ทœ์น™:
1. ๊ณผ๋ชฉ๋ช…: <h1> ํƒœ๊ทธ ๋‚ด์˜ ํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉ.
2. ์„น์…˜:
- <li> ํƒœ๊ทธ์˜ id๊ฐ€ "section-X"์ธ ํ•ญ๋ชฉ๋“ค์„ ์ˆœํšŒ.
- section-0๋Š” ์Šคํ‚ต.
- section-1์€ "Introduction"์œผ๋กœ ํ‘œ๊ธฐ.
- section-2 ์ด์ƒ์€ (section ๋ฒˆํ˜ธ - 1)์ฃผ์ฐจ๋กœ ํ‘œ๊ธฐ.
- ๊ฐ ์„น์…˜์˜ <h3 class="sectionname"> ๋‚ด๋ถ€ <a> ํƒœ๊ทธ์˜ ํ…์ŠคํŠธ์—์„œ ๋‚ ์งœ ๋ฒ”์œ„๋ฅผ ์ถ”์ถœํ•˜์—ฌ ๋ณ€ํ™˜.
- ๊ฐ ์„น์…˜ ๋‚ด์˜ ๋ชจ๋“  <iframe> ํƒœ๊ทธ์˜ src ์†์„ฑ ๊ฐ’์„ ๋™์˜์ƒ ๊ฐ•์˜ URL๋กœ ์ถ”์ถœ.
"""
logging.debug("์ž…๋ ฅ HTML ์ฒ˜๋ฆฌ ์‹œ์ž‘")
soup = BeautifulSoup(html_text, "html.parser")
# 1. ๊ณผ๋ชฉ๋ช… ์ถ”์ถœ (h1 ํƒœ๊ทธ ์‚ฌ์šฉ)
subject_elem = soup.find("h1")
subject_name = ""
if subject_elem:
subject_name = subject_elem.get_text(strip=True)
logging.debug("์ถ”์ถœ๋œ ๊ณผ๋ชฉ๋ช…: %s", subject_name)
else:
logging.debug("h1 ํƒœ๊ทธ๋ฅผ ์ฐพ์ง€ ๋ชปํ•จ")
# 2. ์„น์…˜๋ณ„ ๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก ์ถ”์ถœ
sections_output = ""
section_elements = soup.find_all("li", id=re.compile(r"^section-\d+"))
logging.debug("์ฐพ์€ ์„น์…˜ ๊ฐœ์ˆ˜: %d", len(section_elements))
for section in section_elements:
section_id = section.get("id")
logging.debug("์ฒ˜๋ฆฌ ์ค‘์ธ ์„น์…˜ ID: %s", section_id)
sec_match = re.search(r"section-(\d+)", section_id)
if not sec_match:
continue
sec_num = int(sec_match.group(1))
if sec_num == 0:
logging.debug("section-0 ์€ ์Šคํ‚ต")
continue
# ์„น์…˜ ๋ผ๋ฒจ ์ง€์ •
if sec_num == 1:
section_label = "Introduction"
else:
week_num = sec_num - 1 # section-2๋ถ€ํ„ฐ 1์ฃผ์ฐจ, section-3์€ 2์ฃผ์ฐจ ๋“ฑ
section_label = f"{week_num}์ฃผ์ฐจ"
# ์„น์…˜ ํ—ค๋”์—์„œ ๋‚ ์งœ ๋ฒ”์œ„ ์ถ”์ถœ (h3 ํƒœ๊ทธ ๋‚ด <a> ํƒœ๊ทธ ํ…์ŠคํŠธ)
h3_elem = section.find("h3", class_="sectionname")
date_range_text = ""
if h3_elem and h3_elem.find("a"):
header_text = h3_elem.find("a").get_text(strip=True)
logging.debug("ํ—ค๋” ํ…์ŠคํŠธ: %s", header_text)
date_match = re.search(r'(\d+\s+[A-Za-z]+\s*-\s*\d+\s+[A-Za-z]+)', header_text)
if date_match:
raw_date_range = date_match.group(1)
date_range_text = convert_date_range(raw_date_range)
else:
logging.debug("๋‚ ์งœ ๋ฒ”์œ„ ํŒจํ„ด ๋งค์นญ ์‹คํŒจ: %s", header_text)
else:
logging.debug("h3 ๋˜๋Š” h3 ๋‚ด a ํƒœ๊ทธ๋ฅผ ์ฐพ์ง€ ๋ชปํ•จ for section: %s", section_id)
if sec_num == 1:
section_heading = f"์„น์…˜ : {section_label}"
else:
if date_range_text:
section_heading = f"์„น์…˜ : {section_label} ({date_range_text})"
else:
section_heading = f"์„น์…˜ : {section_label}"
sections_output += section_heading + "\n"
# ํ•ด๋‹น ์„น์…˜ ๋‚ด iframe ํƒœ๊ทธ๋กœ๋ถ€ํ„ฐ ๋™์˜์ƒ ๊ฐ•์˜ URL ์ถ”์ถœ
iframes = section.find_all("iframe")
logging.debug("์„น์…˜ %s ๋‚ด ์ฐพ์€ iframe ๊ฐœ์ˆ˜: %d", section_id, len(iframes))
for idx, iframe in enumerate(iframes, start=1):
video_url = iframe.get("src", "").strip()
if video_url:
sections_output += f"๊ฐ•์˜{idx} : {video_url}\n"
logging.debug("์ถ”์ถœ๋œ ๋™์˜์ƒ ๊ฐ•์˜ URL: %s", video_url)
sections_output += "\n"
logging.debug("HTML ์ฒ˜๋ฆฌ ์™„๋ฃŒ")
return subject_name, sections_output
# Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ (๋ชจ๋“ˆ1)
iface = gr.Interface(
fn=process_html,
inputs=gr.Textbox(label="์ „์ฒด ํŽ˜์ด์ง€ HTML ์ž…๋ ฅ", lines=20, placeholder="HTML ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”..."),
outputs=[
gr.Textbox(label="๊ณผ๋ชฉ๋ช…"),
gr.Textbox(label="๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก")
],
description="์ „์ฒด ํŽ˜์ด์ง€ HTML์„ ์ž…๋ ฅํ•˜๋ฉด ๊ณผ๋ชฉ๋ช…๊ณผ ๊ฐ ์„น์…˜๋ณ„ ๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก์„ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค. (๋””๋ฒ„๊น… ์ •๋ณด๋Š” ์ฝ˜์†”์— ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.)"
)
# ---------- [๋ชจ๋“ˆ1: ๊ธฐ๋ณธ์ฝ”๋“œ] ๋ ----------
# ---------- [๋ชจ๋“ˆ2: ์ถ”๊ฐ€์ฝ”๋“œ] ์‹œ์ž‘ ----------
def fetch_page_source(url):
try:
logging.debug(f"๊ฐ•์˜ ํŽ˜์ด์ง€๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ค‘: {url}")
response = requests.get(url)
response.raise_for_status()
logging.debug("ํŽ˜์ด์ง€ ์†Œ์Šค๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๊ฐ€์ ธ์˜ด")
return response.text
except Exception as e:
logging.error(f"ํŽ˜์ด์ง€ ์†Œ์Šค ๊ฐ€์ ธ์˜ค๊ธฐ ์˜ค๋ฅ˜: {e}")
return "์˜ค๋ฅ˜ ๋ฐœ์ƒ: " + str(e)
def create_script_url(lecture_url):
"""
์ž…๋ ฅ๋ฐ›์€ ๊ฐ•์˜ URL์˜ ํŽ˜์ด์ง€ ์†Œ์Šค์—์„œ ์Šคํฌ๋ฆฝํŠธ ํƒœ๊ทธ ์˜ˆ์‹œ ๋ถ€๋ถ„์„ ์ฐพ์•„
"text_tracks" ๋‚ด๋ถ€์˜ "url" ๊ฐ’์„ ์ถ”์ถœํ•œ ํ›„, 'https://player.vimeo.com'์„ ์•ž์— ๋ถ™์—ฌ์„œ ์Šคํฌ๋ฆฝํŠธ URL์„ ์™„์„ฑํ•จ.
"""
page_source = fetch_page_source(lecture_url)
pattern = r'"text_tracks"\s*:\s*\[\s*\{[^}]*"url"\s*:\s*"([^"]+)"'
match = re.search(pattern, page_source)
if match:
relative_url = match.group(1)
script_url = "https://player.vimeo.com" + relative_url
logging.debug(f"์Šคํฌ๋ฆฝํŠธ URL ์™„์„ฑ: {script_url}")
return script_url
else:
logging.debug("ํŽ˜์ด์ง€ ์†Œ์Šค์—์„œ ์Šคํฌ๋ฆฝํŠธ ํƒœ๊ทธ ์˜ˆ์‹œ ๋ถ€๋ถ„์„ ์ฐพ์ง€ ๋ชปํ•จ")
return ""
def fetch_script(script_url):
try:
logging.debug(f"์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ค‘: {script_url}")
response = requests.get(script_url)
response.raise_for_status()
logging.debug("์Šคํฌ๋ฆฝํŠธ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๊ฐ€์ ธ์˜ด")
return response.text
except Exception as e:
logging.error(f"์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ ์˜ค๋ฅ˜: {e}")
return "์˜ค๋ฅ˜ ๋ฐœ์ƒ: " + str(e)
def remove_timeline(script_text, lecture_number):
"""
[๊ทœ์น™์ˆ˜์ •]
1. ๋ฒˆํ˜ธ, ์‹œ๊ฐ„(ํƒ€์ž„๋ผ์ธ) ๋“ฑ์„ ์ œ์™ธํ•œ ๋‚ด์šฉ๋งŒ์œผ๋กœ ์ž‘์„ฑํ•  ๊ฒƒ.
2. ์•„๋ž˜์œ„ ๋ฌธ์žฅ ์‚ฌ์ด ์ค„ ๊ฐ„๊ฒฉ์ด ์—†๋„๋ก ๋ชจ๋‘ ๋ถ™์—ฌ ์ถœ๋ ฅํ•  ๊ฒƒ.
3. ๋งˆ์นจํ‘œ(.) ๋‹ค์Œ์—๋Š” ๋ฐ˜๋“œ์‹œ ์—ฌ๋ฐฑ 1์นธ์ด ์žˆ์–ด์•ผ ํ•˜๋ฉฐ, ์—ฌ๋ฐฑ ์—†์ด ๋‚ด์šฉ์ด ์ด์–ด์ง„ ๊ฒฝ์šฐ ๋งˆ์นจํ‘œ ๋‹ค์Œ ์—ฌ๋ฐฑ์„ ์ถ”๊ฐ€ํ•  ๊ฒƒ.
4. ๊ธ€ ๊ฐ€์žฅ ์•ž์— ์žˆ๋Š” "WEBVTT"๋Š” ์‚ญ์ œํ•  ๊ฒƒ.
5. ์ ˆ๋Œ€ ๋‚ด์šฉ์„ ์ค„์ด๊ฑฐ๋‚˜ ์š”์•ฝํ•˜๊ฑฐ๋‚˜ ๋ฐ”๊พธ์ง€ ๋ง๊ฒƒ.
"""
lines = script_text.splitlines()
valid_lines = []
for line in lines:
stripped_line = line.strip()
if stripped_line == "":
continue
# ๋ฒˆํ˜ธ๋งŒ ์žˆ๋Š” ์ค„ ์ œ๊ฑฐ
if re.match(r'^\d+$', stripped_line):
continue
# ํƒ€์ž„๋ผ์ธ ํ˜•์‹ ์ œ๊ฑฐ (์˜ˆ: 00:00:00.000 --> 00:00:02.000)
if re.match(r'^\d{1,2}:\d{2}(?::\d{2}(?:\.\d{3})?)?\s*-->\s*\d{1,2}:\d{2}(?::\d{2}(?:\.\d{3})?)?$', stripped_line):
continue
valid_lines.append(stripped_line)
cleaned_text = "".join(valid_lines)
# ๋งˆ์นจํ‘œ(.) ๋‹ค์Œ์— ์—ฌ๋ฐฑ์ด ์—†์œผ๋ฉด ์—ฌ๋ฐฑ ์ถ”๊ฐ€
cleaned_text = re.sub(r'\.(\S)', r'. \1', cleaned_text)
# ๊ธ€ ๊ฐ€์žฅ ์•ž์— ์žˆ๋Š” "WEBVTT" ์ œ๊ฑฐ
cleaned_text = re.sub(r'^WEBVTT\s*', '', cleaned_text)
return cleaned_text
with gr.Blocks() as additional_demo:
# ๋ชจ๋“ˆ2 ์ƒ๋‹จ ์•ˆ๋‚ด ๋ฌธ๊ตฌ
gr.Markdown("โ€ป ์•„๋ž˜ ์ˆœ์„œ๋Œ€๋กœ ๊ฐ ๋‹จ๊ณ„๋ณ„ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์ง„ํ–‰ํ•˜์„ธ์š”.")
with gr.Row():
url1 = gr.Textbox(label="๊ฐ•์˜1 URL", elem_id="url1")
url2 = gr.Textbox(label="๊ฐ•์˜2 URL", elem_id="url2")
url3 = gr.Textbox(label="๊ฐ•์˜3 URL", elem_id="url3")
with gr.Row():
gen_url_btn1 = gr.Button("์Šคํฌ๋ฆฝํŠธ URL ๋งŒ๋“ค๊ธฐ", elem_id="gen_url_btn1")
gen_url_btn2 = gr.Button("์Šคํฌ๋ฆฝํŠธ URL ๋งŒ๋“ค๊ธฐ", elem_id="gen_url_btn2")
gen_url_btn3 = gr.Button("์Šคํฌ๋ฆฝํŠธ URL ๋งŒ๋“ค๊ธฐ", elem_id="gen_url_btn3")
with gr.Row():
script_url1 = gr.Textbox(label="๊ฐ•์˜1 ์Šคํฌ๋ฆฝํŠธ URL", interactive=False, elem_id="script_url1")
script_url2 = gr.Textbox(label="๊ฐ•์˜2 ์Šคํฌ๋ฆฝํŠธ URL", interactive=False, elem_id="script_url2")
script_url3 = gr.Textbox(label="๊ฐ•์˜3 ์Šคํฌ๋ฆฝํŠธ URL", interactive=False, elem_id="script_url3")
with gr.Row():
fetch_btn1 = gr.Button("์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ", elem_id="fetch_btn1")
fetch_btn2 = gr.Button("์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ", elem_id="fetch_btn2")
fetch_btn3 = gr.Button("์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ", elem_id="fetch_btn3")
with gr.Row():
script1 = gr.Textbox(label="๊ฐ•์˜1 ์Šคํฌ๋ฆฝํŠธ", lines=10, elem_id="script1")
script2 = gr.Textbox(label="๊ฐ•์˜2 ์Šคํฌ๋ฆฝํŠธ", lines=10, elem_id="script2")
script3 = gr.Textbox(label="๊ฐ•์˜3 ์Šคํฌ๋ฆฝํŠธ", lines=10, elem_id="script3")
with gr.Row():
remove_btn1 = gr.Button("ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", elem_id="remove_btn1")
remove_btn2 = gr.Button("ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", elem_id="remove_btn2")
remove_btn3 = gr.Button("ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", elem_id="remove_btn3")
with gr.Row():
cleaned1 = gr.Textbox(label="๊ฐ•์˜1 ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", lines=10, interactive=False, elem_id="cleaned1")
cleaned2 = gr.Textbox(label="๊ฐ•์˜2 ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", lines=10, interactive=False, elem_id="cleaned2")
cleaned3 = gr.Textbox(label="๊ฐ•์˜3 ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", lines=10, interactive=False, elem_id="cleaned3")
with gr.Row():
copy_btn1 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌ", elem_id="copy_btn1")
copy_btn2 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌ", elem_id="copy_btn2")
copy_btn3 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌ", elem_id="copy_btn3")
with gr.Row():
copy_result1 = gr.Textbox(label="๊ฐ•์˜ ๋ณต์‚ฌ ๊ฒฐ๊ณผ", interactive=False, elem_id="copy_result1")
copy_result2 = gr.Textbox(label="๊ฐ•์˜ ๋ณต์‚ฌ ๊ฒฐ๊ณผ", interactive=False, elem_id="copy_result2")
copy_result3 = gr.Textbox(label="๊ฐ•์˜ ๋ณต์‚ฌ ๊ฒฐ๊ณผ", interactive=False, elem_id="copy_result3")
gen_url_btn1.click(fn=lambda url: create_script_url(url), inputs=url1, outputs=script_url1)
gen_url_btn2.click(fn=lambda url: create_script_url(url), inputs=url2, outputs=script_url2)
gen_url_btn3.click(fn=lambda url: create_script_url(url), inputs=url3, outputs=script_url3)
fetch_btn1.click(fn=lambda url: fetch_script(url), inputs=script_url1, outputs=script1)
fetch_btn2.click(fn=lambda url: fetch_script(url), inputs=script_url2, outputs=script2)
fetch_btn3.click(fn=lambda url: fetch_script(url), inputs=script_url3, outputs=script3)
remove_btn1.click(fn=lambda script: remove_timeline(script, 1), inputs=script1, outputs=cleaned1)
remove_btn2.click(fn=lambda script: remove_timeline(script, 2), inputs=script2, outputs=cleaned2)
remove_btn3.click(fn=lambda script: remove_timeline(script, 3), inputs=script3, outputs=cleaned3)
custom_script = """
<script>
function setupCopy(copyBtnId, textBoxId, resultBoxId) {
const copyBtn = document.getElementById(copyBtnId);
if (!copyBtn) {
console.error("๋ฒ„ํŠผ " + copyBtnId + "๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
return;
}
copyBtn.addEventListener("click", function(){
const textBoxElem = document.getElementById(textBoxId);
const resultBoxElem = document.getElementById(resultBoxId);
if(textBoxElem && resultBoxElem) {
const textarea = textBoxElem.querySelector("textarea");
const resultTextarea = resultBoxElem.querySelector("textarea");
if(textarea && resultTextarea) {
var text = textarea.value;
if(text.trim() === ""){
resultTextarea.value = "๋ณต์‚ฌํ•  ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.";
} else {
navigator.clipboard.writeText(text).then(function(){
resultTextarea.value = "๋ณต์‚ฌ์™„๋ฃŒ";
}, function(err){
resultTextarea.value = "๋ณต์‚ฌ ์‹คํŒจ";
});
}
}
}
});
}
document.addEventListener("DOMContentLoaded", function(){
setupCopy("copy_btn1", "cleaned1", "copy_result1");
setupCopy("copy_btn2", "cleaned2", "copy_result2");
setupCopy("copy_btn3", "cleaned3", "copy_result3");
});
</script>
"""
gr.HTML(custom_script)
gr.Markdown("๋””๋ฒ„๊น… ๋ชจ๋“œ ํ™œ์„ฑํ™”๋จ: ๋กœ๊ทธ๊ฐ€ ์ฝ˜์†”์— ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.")
# ---------- [๋ชจ๋“ˆ2: ์ถ”๊ฐ€์ฝ”๋“œ] ๋ ----------
# ---------- ํ†ตํ•ฉ Gradio ์•ฑ ๊ตฌ์„ฑ (ํ•œ ํŽ˜์ด์ง€์— ๋ชจ๋‘ ํ‘œ์‹œ) ----------
with gr.Blocks() as app:
gr.Markdown("# ์บ๋กค๋ผ์ธ๋Œ€ํ•™ ๊ฐ•์˜ ์ถ”์ถœ๊ธฐ")
gr.Markdown("์ „์ฒด ํŽ˜์ด์ง€ HTML์„ ์ž…๋ ฅํ•˜๋ฉด ๊ณผ๋ชฉ๋ช…๊ณผ ๊ฐ ์„น์…˜๋ณ„ ๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก์„ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค. (๋””๋ฒ„๊น… ์ •๋ณด๋Š” ์ฝ˜์†”์— ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.)")
gr.HTML(
"""
<div style="background-color: #f0f0f0; padding: 10px; margin-bottom: 20px;">
<strong>์‚ฌ์šฉ๋ฐฉ๋ฒ•</strong>
<ol>
<li>์ถ”์ถœ์„ ์›ํ•˜๋Š” ๊ฐ•์˜ ํŽ˜์ด์ง€์—์„œ "Ctrl + U"๋ฅผ ๋ˆ„๋ฅด๊ณ  "ํŽ˜์ด์ง€ ์†Œ์Šค ๋ณด๊ธฐ" ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
๋˜๋Š” ํ•ด๋‹นํŽ˜์ด์ง€์—์„œ ๋งˆ์šฐ์Šค ์šฐํด๋ฆญ ํ›„ "ํŽ˜์ด์ง€ ์†Œ์Šค ๋ณด๊ธฐ" ํด๋ฆญ (์—ฃ์ง€์˜ ๊ฒฝ์šฐ "ํŽ˜์ด์ง€ ์›๋ณธ ๋ณด๊ธฐ")</li>
<li>"ํŽ˜์ด์ง€ ์†Œ์Šค ๋ณด๊ธฐ" ํŽ˜์ด์ง€์—์„œ ์ „์ฒด ๋ณต์‚ฌ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. "Ctrl+A" ๋‹ค์Œ "Ctrl + C"</li>
<li>"์ „์ฒด ํŽ˜์ด์ง€ HTML ์ž…๋ ฅ"์ฐฝ์— ๋ณต์‚ฌํ•œ ๋‚ด์šฉ์„ ๋ถ™ํ˜€๋„ฃ๊ธฐ ํ•ฉ๋‹ˆ๋‹ค. "Ctrl + V"</li>
<li>"Submit" ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก์ด ๋‚˜์˜ต๋‹ˆ๋‹ค.</li>
<li>๋‚ด์šฉ ์ถ”์ถœ์„ ์›ํ•˜๋Š” ๊ฐ•์˜ URL์„ ๋ณต์‚ฌํ•ด์„œ ์•„๋ž˜ "๊ฐ•์˜ URL" ์ฐฝ์— ๋ถ™ํ˜€๋„ฃ๊ธฐ ํ•ฉ๋‹ˆ๋‹ค.</li>
<li>์ˆœ์„œ๋Œ€๋กœ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ์˜์ƒ์˜ ๊ฐ•์˜ ๋‚ด์šฉ์„ ์ถ”์ถœ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.</li>
<li>๊ฐ๊ฐ ์ถ”์ถœ๋œ ๊ฐ•์˜ ๋‚ด์šฉ์„ "ChatGPT"์— ์ „์ฒด ๋ถ™ํ˜€๋„ฃ๊ณ  ๊ฐ•์˜ ์š”์•ฝ์„ ์ง€์‹œํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.</li>
</ol>
</div>
"""
)
iface.render()
# Module1์˜ Submit ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ Module2 ๋‚ด์šฉ ์ง€์šฐ๊ธฐ ์œ„ํ•œ JavaScript
gr.HTML(
"""
<script>
function clearModule2Fields() {
var ids = ["url1", "url2", "url3", "script_url1", "script_url2", "script_url3", "script1", "script2", "script3", "cleaned1", "cleaned2", "cleaned3", "copy_result1", "copy_result2", "copy_result3"];
ids.forEach(function(id) {
var elem = document.getElementById(id);
if (elem) {
var textarea = elem.querySelector("textarea");
if (textarea) {
textarea.value = "";
} else {
elem.value = "";
}
}
});
}
document.addEventListener("DOMContentLoaded", function(){
var buttons = document.getElementsByTagName("button");
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].textContent.trim() === "Submit") {
buttons[i].addEventListener("click", function(){
clearModule2Fields();
});
}
}
});
</script>
"""
)
gr.Markdown("---")
gr.Markdown("๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก์—์„œ ํ•„์š”ํ•œ ๊ฐ•์˜์˜ URL์„ ๋ณต์‚ฌํ•ด์„œ ๋„ฃ์–ด์ฃผ์„ธ์š”")
additional_demo.render()
if __name__ == "__main__":
logging.debug("ํ†ตํ•ฉ Gradio ์•ฑ ์‹คํ–‰ ์ค‘")
app.launch(debug=True)