HanJun commited on
Commit
0299c67
ยท
verified ยท
1 Parent(s): 62f5ee3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -24
app.py CHANGED
@@ -48,14 +48,21 @@ def get_claude_client():
48
  return anthropic.Anthropic(api_key=api_key)
49
 
50
  def install_browsers():
51
- """Playwright ๋ธŒ๋ผ์šฐ์ € ์„ค์น˜"""
52
  try:
53
  print("Playwright ๋ธŒ๋ผ์šฐ์ € ์„ค์น˜ ์ค‘...")
54
  os.system("playwright install chromium")
55
- print("Playwright ๋ธŒ๋ผ์šฐ์ € ์„ค์น˜ ์™„๋ฃŒ!")
 
 
 
 
 
 
 
56
  return True
57
  except Exception as e:
58
- print(f"๋ธŒ๋ผ์šฐ์ € ์„ค์น˜ ์‹คํŒจ: {e}")
59
  return False
60
 
61
  def init_browser():
@@ -92,7 +99,10 @@ def init_browser():
92
  '--disable-features=TranslateUI',
93
  '--disable-ipc-flooding-protection',
94
  '--disable-plugins',
95
- '--disable-images'
 
 
 
96
  ]
97
  )
98
 
@@ -104,9 +114,17 @@ def init_browser():
104
 
105
  # User-Agent ์„ค์ •
106
  page.set_extra_http_headers({
107
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36"
 
108
  })
109
 
 
 
 
 
 
 
 
110
  print("Google Trends ํŽ˜์ด์ง€๋กœ ์ด๋™ ์ค‘...")
111
  page.goto("https://trends.google.com/trending?geo=KR", wait_until="networkidle", timeout=30000)
112
 
@@ -170,25 +188,61 @@ def apply_filters(geo: str, time_range: str, category: str) -> bool:
170
  try:
171
  print(f"ํ•„ํ„ฐ ์ ์šฉ: ์ง€์—ญ={geo}")
172
 
173
- # ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจ์œผ๋กœ ์‹œ์ž‘
174
- page.reload(wait_until="networkidle", timeout=30000)
175
- time.sleep(3)
176
-
177
- # ํ•„ํ„ฐ ์ ์šฉ์€ URL ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ฒ˜๋ฆฌ
178
  geo_map = {
179
  "KR": "KR", "US": "US", "JP": "JP",
180
  "GB": "GB", "DE": "DE", "FR": "FR"
181
  }
182
 
183
- # URL ๊ตฌ์„ฑ
184
  base_url = "https://trends.google.com/trending"
185
  geo_param = geo_map.get(geo, "KR")
186
  url = f"{base_url}?geo={geo_param}"
187
 
188
  print(f"ํ•„ํ„ฐ ์ ์šฉ๋œ URL๋กœ ์ด๋™: {url}")
189
  page.goto(url, wait_until="networkidle", timeout=30000)
 
 
190
  time.sleep(3)
191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  print("ํ•„ํ„ฐ ์ ์šฉ ์™„๋ฃŒ")
193
  return True
194
 
@@ -198,7 +252,7 @@ def apply_filters(geo: str, time_range: str, category: str) -> bool:
198
  return False
199
 
200
  def capture_screenshot() -> Optional[Image.Image]:
201
- """ํ˜„์žฌ ํŽ˜์ด์ง€์˜ ์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜"""
202
  global page
203
 
204
  # ๋ธŒ๋ผ์šฐ์ € ์ค€๋น„ ์ƒํƒœ ํ™•์ธ
@@ -212,10 +266,41 @@ def capture_screenshot() -> Optional[Image.Image]:
212
  # ํŽ˜์ด์ง€๊ฐ€ ์™„์ „ํžˆ ๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
213
  time.sleep(2)
214
 
215
- # ์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜
216
- screenshot_bytes = page.screenshot(full_page=True)
217
- screenshot = Image.open(io.BytesIO(screenshot_bytes))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
 
 
219
  print("์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜ ์™„๋ฃŒ")
220
  return screenshot
221
 
@@ -310,8 +395,52 @@ def refresh_trends_page():
310
  except Exception as e:
311
  return f"ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจ ์‹คํŒจ: {str(e)}"
312
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
  def main_process(geo: str, time_range: str, category: str) -> Tuple[Optional[Image.Image], str]:
314
- """๋ฉ”์ธ ์ฒ˜๋ฆฌ ํ•จ์ˆ˜"""
315
  try:
316
  # 1. ๋ธŒ๋ผ์šฐ์ € ์ค€๋น„ ํ™•์ธ
317
  if not ensure_browser_ready():
@@ -369,6 +498,9 @@ def create_interface():
369
  gr.Markdown("# Google Trends ์‹ค์‹œ๊ฐ„ ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด ๋ถ„์„๊ธฐ")
370
  gr.Markdown("Google Trends์˜ ์‹ค์‹œ๊ฐ„ ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด๋ฅผ ์บก์ฒ˜ํ•˜๊ณ  Claude AI๋กœ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค.")
371
 
 
 
 
372
  with gr.Row():
373
  with gr.Column(scale=1):
374
  geo_dropdown = gr.Dropdown(
@@ -389,27 +521,57 @@ def create_interface():
389
  label="์นดํ…Œ๊ณ ๋ฆฌ ์„ ํƒ"
390
  )
391
 
392
- analyze_btn = gr.Button("๋ถ„์„ ์‹œ์ž‘", variant="primary")
393
- refresh_btn = gr.Button("ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจ", variant="secondary")
394
- reinit_btn = gr.Button("๋ธŒ๋ผ์šฐ์ € ์žฌ์ดˆ๊ธฐํ™”", variant="secondary")
395
- status_btn = gr.Button("๋ธŒ๋ผ์šฐ์ € ์ƒํƒœ ํ™•์ธ", variant="secondary")
 
 
 
 
396
 
397
  with gr.Column(scale=2):
398
  screenshot_output = gr.Image(label="Google Trends ์Šคํฌ๋ฆฐ์ƒท")
399
  analysis_output = gr.Textbox(
400
  label="Claude AI ๋ถ„์„ ๊ฒฐ๊ณผ",
401
  lines=10,
402
- max_lines=20
 
403
  )
404
  status_output = gr.Textbox(label="์ƒํƒœ ๋ฉ”์‹œ์ง€")
405
 
406
  # ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
407
- analyze_btn.click(
408
- fn=main_process,
 
 
 
 
 
 
 
 
 
 
409
  inputs=[geo_dropdown, time_dropdown, category_dropdown],
410
- outputs=[screenshot_output, analysis_output]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
411
  )
412
 
 
413
  refresh_btn.click(
414
  fn=refresh_trends_page,
415
  outputs=status_output
 
48
  return anthropic.Anthropic(api_key=api_key)
49
 
50
  def install_browsers():
51
+ """Playwright ๋ธŒ๋ผ์šฐ์ € ๋ฐ ํ•œ๊ธ€ ํฐํŠธ ์„ค์น˜"""
52
  try:
53
  print("Playwright ๋ธŒ๋ผ์šฐ์ € ์„ค์น˜ ์ค‘...")
54
  os.system("playwright install chromium")
55
+
56
+ print("ํ•œ๊ธ€ ํฐํŠธ ์„ค์น˜ ์ค‘...")
57
+ # ํ•œ๊ธ€ ํฐํŠธ ์„ค์น˜
58
+ os.system("apt-get update")
59
+ os.system("apt-get install -y fonts-nanum fonts-nanum-coding fonts-nanum-extra")
60
+ os.system("fc-cache -fv")
61
+
62
+ print("Playwright ๋ธŒ๋ผ์šฐ์ € ๋ฐ ํฐํŠธ ์„ค์น˜ ์™„๋ฃŒ!")
63
  return True
64
  except Exception as e:
65
+ print(f"๋ธŒ๋ผ์šฐ์ €/ํฐํŠธ ์„ค์น˜ ์‹คํŒจ: {e}")
66
  return False
67
 
68
  def init_browser():
 
99
  '--disable-features=TranslateUI',
100
  '--disable-ipc-flooding-protection',
101
  '--disable-plugins',
102
+ '--disable-images',
103
+ '--force-device-scale-factor=1',
104
+ '--font-render-hinting=medium',
105
+ '--disable-font-subpixel-positioning'
106
  ]
107
  )
108
 
 
114
 
115
  # User-Agent ์„ค์ •
116
  page.set_extra_http_headers({
117
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
118
+ "Accept-Language": "ko-KR,ko;q=0.9,en;q=0.8"
119
  })
120
 
121
+ # ํ•œ๊ธ€ ํฐํŠธ ์„ค์ •์„ ์œ„ํ•œ CSS ์ถ”๊ฐ€
122
+ page.add_style_tag(content="""
123
+ * {
124
+ font-family: 'Nanum Gothic', 'Malgun Gothic', '๋ง‘์€ ๊ณ ๋”•', 'Noto Sans CJK KR', 'Apple SD Gothic Neo', sans-serif !important;
125
+ }
126
+ """)
127
+
128
  print("Google Trends ํŽ˜์ด์ง€๋กœ ์ด๋™ ์ค‘...")
129
  page.goto("https://trends.google.com/trending?geo=KR", wait_until="networkidle", timeout=30000)
130
 
 
188
  try:
189
  print(f"ํ•„ํ„ฐ ์ ์šฉ: ์ง€์—ญ={geo}")
190
 
191
+ # ์ง€์—ญ ์„ค์ •์„ ์œ„ํ•œ URL ๊ตฌ์„ฑ
 
 
 
 
192
  geo_map = {
193
  "KR": "KR", "US": "US", "JP": "JP",
194
  "GB": "GB", "DE": "DE", "FR": "FR"
195
  }
196
 
 
197
  base_url = "https://trends.google.com/trending"
198
  geo_param = geo_map.get(geo, "KR")
199
  url = f"{base_url}?geo={geo_param}"
200
 
201
  print(f"ํ•„ํ„ฐ ์ ์šฉ๋œ URL๋กœ ์ด๋™: {url}")
202
  page.goto(url, wait_until="networkidle", timeout=30000)
203
+
204
+ # ํŽ˜์ด์ง€ ๋กœ๋”ฉ ์™„๋ฃŒ ๋Œ€๊ธฐ
205
  time.sleep(3)
206
 
207
+ # ์‹ค์ œ ํ•„ํ„ฐ ์š”์†Œ๋“ค์ด ์žˆ๋‹ค๋ฉด ํด๋ฆญ์œผ๋กœ ์„ค์ •
208
+ try:
209
+ # ์‹œ๊ฐ„ ๋ฒ”์œ„ ํ•„ํ„ฐ ์‹œ๋„
210
+ if time_range != "24์‹œ๊ฐ„":
211
+ time_selector = page.locator('[data-bucket="0"]').first
212
+ if time_selector.is_visible():
213
+ time_selector.click()
214
+ time.sleep(1)
215
+
216
+ # ์‹œ๊ฐ„ ์˜ต์…˜๋“ค ์ค‘ ์„ ํƒ
217
+ if time_range == "7์ผ":
218
+ page.locator('text="Past 7 days"').first.click()
219
+ elif time_range == "30์ผ":
220
+ page.locator('text="Past 30 days"').first.click()
221
+ time.sleep(2)
222
+
223
+ # ์นดํ…Œ๊ณ ๋ฆฌ ํ•„ํ„ฐ ์‹œ๋„
224
+ if category != "๋ชจ๋“  ์นดํ…Œ๊ณ ๋ฆฌ":
225
+ category_selector = page.locator('[data-bucket="2"]').first
226
+ if category_selector.is_visible():
227
+ category_selector.click()
228
+ time.sleep(1)
229
+
230
+ # ์นดํ…Œ๊ณ ๋ฆฌ ๋งคํ•‘
231
+ category_map = {
232
+ "์—”ํ„ฐํ…Œ์ธ๋จผํŠธ": "Entertainment",
233
+ "์Šคํฌ์ธ ": "Sports",
234
+ "๋น„์ฆˆ๋‹ˆ์Šค": "Business",
235
+ "๊ณผํ•™๊ธฐ์ˆ ": "Science & Tech",
236
+ "๊ฑด๊ฐ•": "Health"
237
+ }
238
+
239
+ if category in category_map:
240
+ page.locator(f'text="{category_map[category]}"').first.click()
241
+ time.sleep(2)
242
+
243
+ except Exception as filter_error:
244
+ print(f"ํ•„ํ„ฐ ์š”์†Œ ํด๋ฆญ ์‹คํŒจ (๊ณ„์† ์ง„ํ–‰): {filter_error}")
245
+
246
  print("ํ•„ํ„ฐ ์ ์šฉ ์™„๋ฃŒ")
247
  return True
248
 
 
252
  return False
253
 
254
  def capture_screenshot() -> Optional[Image.Image]:
255
+ """ํ˜„์žฌ ํŽ˜์ด์ง€์˜ ์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜ (ํŠธ๋ Œ๋“œ ํ…Œ์ด๋ธ” ์˜์—ญ๋งŒ)"""
256
  global page
257
 
258
  # ๋ธŒ๋ผ์šฐ์ € ์ค€๋น„ ์ƒํƒœ ํ™•์ธ
 
266
  # ํŽ˜์ด์ง€๊ฐ€ ์™„์ „ํžˆ ๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
267
  time.sleep(2)
268
 
269
+ # ํŠธ๋ Œ๋“œ ํ…Œ์ด๋ธ” ์˜์—ญ ์ฐพ๊ธฐ
270
+ try:
271
+ # ์—ฌ๋Ÿฌ ๊ฐ€๋Šฅํ•œ ์…€๋ ‰ํ„ฐ ์‹œ๋„
272
+ selectors = [
273
+ '[data-module="TrendingSearches"]', # ๋ฉ”์ธ ํŠธ๋ Œ๋“œ ๋ชจ๋“ˆ
274
+ '.trends-table', # ํŠธ๋ Œ๋“œ ํ…Œ์ด๋ธ”
275
+ '.trending-searches', # ํŠธ๋ Œ๋“œ ๊ฒ€์ƒ‰์–ด ์˜์—ญ
276
+ '[role="main"]', # ๋ฉ”์ธ ์ฝ˜ํ…์ธ  ์˜์—ญ
277
+ 'main' # ๊ธฐ๋ณธ ๋ฉ”์ธ ํƒœ๊ทธ
278
+ ]
279
+
280
+ element = None
281
+ for selector in selectors:
282
+ try:
283
+ element = page.locator(selector).first
284
+ if element.is_visible():
285
+ print(f"์บก์ฒ˜ ์˜์—ญ ๋ฐœ๊ฒฌ: {selector}")
286
+ break
287
+ except:
288
+ continue
289
+
290
+ if element and element.is_visible():
291
+ # ํŠน์ • ์˜์—ญ๋งŒ ์Šคํฌ๋ฆฐ์ƒท
292
+ screenshot_bytes = element.screenshot()
293
+ print("ํŠธ๋ Œ๋“œ ํ…Œ์ด๋ธ” ์˜์—ญ ์บก์ฒ˜ ์™„๋ฃŒ")
294
+ else:
295
+ # ๋Œ€์•ˆ: ์ „์ฒด ํŽ˜์ด์ง€์—์„œ ์ƒ๋‹จ ๋ถ€๋ถ„๋งŒ ์บก์ฒ˜
296
+ print("ํŠน์ • ์˜์—ญ์„ ์ฐพ์ง€ ๋ชปํ•ด ํŽ˜์ด์ง€ ์ƒ๋‹จ ์˜์—ญ ์บก์ฒ˜")
297
+ screenshot_bytes = page.screenshot(clip={"x": 0, "y": 100, "width": 1920, "height": 800})
298
+
299
+ except Exception as selector_error:
300
+ print(f"์˜์—ญ ์„ ํƒ ์‹คํŒจ, ์ „์ฒด ํŽ˜์ด์ง€ ์บก์ฒ˜: {selector_error}")
301
+ screenshot_bytes = page.screenshot(full_page=True)
302
 
303
+ screenshot = Image.open(io.BytesIO(screenshot_bytes))
304
  print("์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜ ์™„๋ฃŒ")
305
  return screenshot
306
 
 
395
  except Exception as e:
396
  return f"ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจ ์‹คํŒจ: {str(e)}"
397
 
398
+ def main_process_screenshot(geo: str, time_range: str, category: str) -> Tuple[Optional[Image.Image], str]:
399
+ """์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜๋งŒ ์ˆ˜ํ–‰ํ•˜๋Š” ํ•จ์ˆ˜"""
400
+ try:
401
+ # 1. ๋ธŒ๋ผ์šฐ์ € ์ค€๋น„ ํ™•์ธ
402
+ if not ensure_browser_ready():
403
+ return None, "๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ค€๋น„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. '๋ธŒ๋ผ์šฐ์ € ์žฌ์ดˆ๊ธฐํ™”' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•ด์ฃผ์„ธ์š”."
404
+
405
+ # 2. ํ•„ํ„ฐ ์ ์šฉ
406
+ print(f"ํ•„ํ„ฐ ์ ์šฉ ์ค‘: ์ง€์—ญ={geo}, ์‹œ๊ฐ„={time_range}, ์นดํ…Œ๊ณ ๋ฆฌ={category}")
407
+ filter_success = apply_filters(geo, time_range, category)
408
+
409
+ if not filter_success:
410
+ return None, "ํ•„ํ„ฐ ์ ์šฉ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค."
411
+
412
+ # 3. ์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜
413
+ print("์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜ ์ค‘...")
414
+ screenshot = capture_screenshot()
415
+
416
+ if screenshot is None:
417
+ return None, "์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค."
418
+
419
+ return screenshot, "์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜ ์™„๋ฃŒ! Claude ๋ถ„์„์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค..."
420
+
421
+ except Exception as e:
422
+ error_msg = f"์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
423
+ print(error_msg)
424
+ print(traceback.format_exc())
425
+ return None, error_msg
426
+
427
+ def analyze_screenshot_with_claude(screenshot: Image.Image) -> str:
428
+ """Claude API๋กœ ์Šคํฌ๋ฆฐ์ƒท ๋ถ„์„"""
429
+ if screenshot is None:
430
+ return "๋ถ„์„ํ•  ์Šคํฌ๋ฆฐ์ƒท์ด ์—†์Šต๋‹ˆ๋‹ค."
431
+
432
+ try:
433
+ print("Claude API๋กœ ๋ถ„์„ ์ค‘...")
434
+ analysis_result = analyze_with_claude(screenshot)
435
+ return analysis_result
436
+
437
+ except Exception as e:
438
+ error_msg = f"Claude ๋ถ„์„ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {str(e)}"
439
+ print(error_msg)
440
+ return error_msg
441
+
442
  def main_process(geo: str, time_range: str, category: str) -> Tuple[Optional[Image.Image], str]:
443
+ """์ „์ฒด ํ”„๋กœ์„ธ์Šค (ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด ์œ ์ง€)"""
444
  try:
445
  # 1. ๋ธŒ๋ผ์šฐ์ € ์ค€๋น„ ํ™•์ธ
446
  if not ensure_browser_ready():
 
498
  gr.Markdown("# Google Trends ์‹ค์‹œ๊ฐ„ ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด ๋ถ„์„๊ธฐ")
499
  gr.Markdown("Google Trends์˜ ์‹ค์‹œ๊ฐ„ ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด๋ฅผ ์บก์ฒ˜ํ•˜๊ณ  Claude AI๋กœ ๋ถ„์„ํ•ฉ๋‹ˆ๋‹ค.")
500
 
501
+ # ์ƒํƒœ ์ €์žฅ์„ ์œ„ํ•œ State ์ปดํฌ๋„ŒํŠธ
502
+ screenshot_state = gr.State(None)
503
+
504
  with gr.Row():
505
  with gr.Column(scale=1):
506
  geo_dropdown = gr.Dropdown(
 
521
  label="์นดํ…Œ๊ณ ๋ฆฌ ์„ ํƒ"
522
  )
523
 
524
+ with gr.Row():
525
+ capture_btn = gr.Button("๐ŸŽฏ ์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜", variant="primary")
526
+ analyze_btn = gr.Button("๐Ÿค– Claude ๋ถ„์„", variant="secondary", interactive=False)
527
+
528
+ with gr.Row():
529
+ refresh_btn = gr.Button("๐Ÿ”„ ํŽ˜์ด์ง€ ์ƒˆ๋กœ๊ณ ์นจ", variant="secondary")
530
+ reinit_btn = gr.Button("โš™๏ธ ๋ธŒ๋ผ์šฐ์ € ์ดˆ๊ธฐํ™”", variant="secondary")
531
+ status_btn = gr.Button("๐Ÿ“Š ๋ธŒ๋ผ์šฐ์ € ์ƒํƒœ ํ™•์ธ", variant="secondary")
532
 
533
  with gr.Column(scale=2):
534
  screenshot_output = gr.Image(label="Google Trends ์Šคํฌ๋ฆฐ์ƒท")
535
  analysis_output = gr.Textbox(
536
  label="Claude AI ๋ถ„์„ ๊ฒฐ๊ณผ",
537
  lines=10,
538
+ max_lines=20,
539
+ placeholder="์Šคํฌ๋ฆฐ์ƒท์„ ์บก์ฒ˜ํ•œ ํ›„ 'Claude ๋ถ„์„' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์„ธ์š”."
540
  )
541
  status_output = gr.Textbox(label="์ƒํƒœ ๋ฉ”์‹œ์ง€")
542
 
543
  # ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ
544
+
545
+ # ์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜ ๋ฒ„ํŠผ
546
+ def on_capture_click(geo, time_range, category):
547
+ screenshot, message = main_process_screenshot(geo, time_range, category)
548
+ if screenshot is not None:
549
+ # ๋ถ„์„ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”
550
+ return screenshot, screenshot, message, gr.update(interactive=True)
551
+ else:
552
+ return None, None, message, gr.update(interactive=False)
553
+
554
+ capture_btn.click(
555
+ fn=on_capture_click,
556
  inputs=[geo_dropdown, time_dropdown, category_dropdown],
557
+ outputs=[screenshot_output, screenshot_state, status_output, analyze_btn]
558
+ )
559
+
560
+ # Claude ๋ถ„์„ ๋ฒ„ํŠผ
561
+ def on_analyze_click(screenshot):
562
+ if screenshot is None:
563
+ return "๋ถ„์„ํ•  ์Šคํฌ๋ฆฐ์ƒท์ด ์—†์Šต๋‹ˆ๋‹ค. ๋จผ์ € '์Šคํฌ๋ฆฐ์ƒท ์บก์ฒ˜' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์„ธ์š”."
564
+
565
+ analysis_result = analyze_screenshot_with_claude(screenshot)
566
+ return analysis_result
567
+
568
+ analyze_btn.click(
569
+ fn=on_analyze_click,
570
+ inputs=[screenshot_state],
571
+ outputs=[analysis_output]
572
  )
573
 
574
+ # ๊ธฐํƒ€ ๋ฒ„ํŠผ๋“ค
575
  refresh_btn.click(
576
  fn=refresh_trends_page,
577
  outputs=status_output