khjhs60199 commited on
Commit
99f90dc
·
verified ·
1 Parent(s): 4420a59

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -34
app.py CHANGED
@@ -27,28 +27,61 @@ flask_app = Flask(__name__)
27
  class NewsApp:
28
  def __init__(self):
29
  self.db = NewsDatabase()
30
- self.sentiment_analyzer = SentimentAnalyzer()
31
- self.crawler = CnYesNewsCrawler(
32
- sentiment_analyzer=self.sentiment_analyzer,
33
- database=self.db
34
- )
35
- self.scheduler = NewsScheduler(self.db, self.crawler, self.sentiment_analyzer)
36
 
37
  # 進度追蹤
38
- self.current_progress = "系統已就緒"
39
  self.is_crawling = False
 
40
 
41
- # 設置爬蟲進度回調
42
- self.crawler.set_progress_callback(self.update_progress)
43
 
44
- # 啟動背景排程器
45
- self.scheduler.start()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
- logger.info("新聞應用程式初始化完成")
 
 
48
 
49
  def update_progress(self, message: str):
50
  """更新進度信息"""
51
- self.current_progress = f"{datetime.now().strftime('%H:%M:%S')} - {message}"
 
52
  logger.info(f"進度更新: {message}")
53
 
54
  def get_progress(self) -> str:
@@ -60,7 +93,7 @@ class NewsApp:
60
  try:
61
  news_data = self.db.get_recent_news(category=category, limit=limit)
62
  if not news_data:
63
- return "📰 暫無新聞資料,請稍後再試"
64
 
65
  return format_news_for_display(news_data)
66
 
@@ -70,6 +103,9 @@ class NewsApp:
70
 
71
  def manual_crawl(self) -> str:
72
  """手動觸發爬蟲"""
 
 
 
73
  if self.is_crawling:
74
  return "⚠️ 爬蟲正在運行中,請稍後再試"
75
 
@@ -179,6 +215,12 @@ def api_get_stats():
179
  def api_manual_crawl():
180
  """手動觸發爬蟲API"""
181
  try:
 
 
 
 
 
 
182
  if app.is_crawling:
183
  return jsonify({
184
  'success': False,
@@ -206,9 +248,17 @@ def api_get_progress():
206
  """獲取爬蟲進度API"""
207
  return jsonify({
208
  'progress': app.get_progress(),
209
- 'is_crawling': app.is_crawling
 
210
  })
211
 
 
 
 
 
 
 
 
212
  # 創建 Gradio 介面
213
  def create_interface():
214
  with gr.Blocks(
@@ -223,7 +273,7 @@ def create_interface():
223
  .positive-badge { background: #28a745; color: white; }
224
  .negative-badge { background: #dc3545; color: white; }
225
  .neutral-badge { background: #6c757d; color: white; }
226
- .progress-box { background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 5px; padding: 10px; font-family: monospace; }
227
  """
228
  ) as interface:
229
 
@@ -253,21 +303,20 @@ def create_interface():
253
 
254
  # 進度顯示
255
  progress_display = gr.Textbox(
256
- label="📊 即時進度",
257
  value=app.get_progress(),
258
  interactive=False,
259
- elem_classes=["progress-box"]
 
260
  )
261
 
262
  news_display = gr.HTML(label="新聞內容")
263
  crawl_result = gr.Textbox(label="爬取結果", visible=False)
264
 
265
- # 自動重新整理進度
266
- def update_progress_display():
267
- return app.get_progress()
268
-
269
- def auto_refresh():
270
- return app.get_latest_news("all")
271
 
272
  def refresh_news(category):
273
  return app.get_latest_news(category)
@@ -278,11 +327,11 @@ def create_interface():
278
  news = app.get_latest_news("all")
279
  return result, news
280
 
281
- # 定期更新進度
282
- interface.load(
283
- lambda: [app.get_progress(), app.get_latest_news("all")],
284
- outputs=[progress_display, news_display],
285
- every=5 # 每5秒更新一次
286
  )
287
 
288
  # 綁定事件
@@ -295,6 +344,9 @@ def create_interface():
295
  outputs=[crawl_result]
296
  )
297
  category_radio.change(refresh_news, inputs=[category_radio], outputs=[news_display])
 
 
 
298
 
299
  with gr.Tab("📊 統計資訊"):
300
  stats_display = gr.Markdown()
@@ -350,7 +402,7 @@ def create_interface():
350
  POST /api/crawl
351
  ```
352
 
353
- #### 4. 獲取爬蟲進度
354
  ```
355
  GET /api/progress
356
  ```
@@ -362,12 +414,16 @@ def create_interface():
362
  import requests
363
 
364
  # 獲取所有新聞
365
- response = requests.get('http://localhost:7860/api/news')
366
  news_data = response.json()
367
 
368
  # 獲取美股新聞
369
- response = requests.get('http://localhost:7860/api/news?category=us_stock&limit=10')
370
  us_news = response.json()
 
 
 
 
371
  ```
372
 
373
  **JavaScript:**
@@ -398,6 +454,7 @@ def create_interface():
398
  - **模型**: `uer/roberta-base-finetuned-jd-binary-chinese`
399
  - **分類**: 正面 (綠色) / 負面 (紅色) / 中性 (灰色)
400
  - **準確性**: 針對中文金融新聞優化
 
401
 
402
  ### 🕷️ 新聞爬蟲
403
  - **來源**: 鉅亨網 (cnyes.com)
@@ -419,8 +476,9 @@ def create_interface():
419
 
420
  ---
421
 
422
- 💡 **提示**:
423
- - 首次啟動可能需要幾分鐘下載模型
 
424
  - 建議使用SSD硬碟提升SQLite性能
425
  - API接口可用於整合其他應用系統
426
  """)
@@ -438,6 +496,11 @@ if __name__ == "__main__":
438
  flask_thread = threading.Thread(target=run_flask, daemon=True)
439
  flask_thread.start()
440
 
 
 
 
 
 
441
  # 啟動Gradio介面
442
  interface = create_interface()
443
  interface.launch(
 
27
  class NewsApp:
28
  def __init__(self):
29
  self.db = NewsDatabase()
30
+
31
+ # 延遲初始化情緒分析器
32
+ self.sentiment_analyzer = None
33
+ self.crawler = None
34
+ self.scheduler = None
 
35
 
36
  # 進度追蹤
37
+ self.current_progress = "正在初始化系統..."
38
  self.is_crawling = False
39
+ self.is_initialized = False
40
 
41
+ # 在背景初始化重型組件
42
+ self._initialize_components()
43
 
44
+ logger.info("新聞應用程式開始初始化")
45
+
46
+ def _initialize_components(self):
47
+ """在背景初始化重型組件"""
48
+ def init_task():
49
+ try:
50
+ self.update_progress("正在載入情緒分析模型...")
51
+ self.sentiment_analyzer = SentimentAnalyzer()
52
+
53
+ self.update_progress("正在初始化爬蟲...")
54
+ self.crawler = CnYesNewsCrawler(
55
+ sentiment_analyzer=self.sentiment_analyzer,
56
+ database=self.db
57
+ )
58
+
59
+ self.update_progress("正在設置排程器...")
60
+ self.scheduler = NewsScheduler(self.db, self.crawler, self.sentiment_analyzer)
61
+
62
+ # 設置爬蟲進度回調
63
+ self.crawler.set_progress_callback(self.update_progress)
64
+
65
+ # 啟動背景排程器
66
+ self.scheduler.start()
67
+
68
+ self.is_initialized = True
69
+ self.update_progress("系統初始化完成,已就緒")
70
+ logger.info("所有組件初始化完成")
71
+
72
+ except Exception as e:
73
+ error_msg = f"初始化失敗: {str(e)}"
74
+ self.update_progress(error_msg)
75
+ logger.error(error_msg)
76
 
77
+ # 在背景線程中初始化
78
+ init_thread = threading.Thread(target=init_task, daemon=True)
79
+ init_thread.start()
80
 
81
  def update_progress(self, message: str):
82
  """更新進度信息"""
83
+ timestamp = datetime.now().strftime('%H:%M:%S')
84
+ self.current_progress = f"[{timestamp}] {message}"
85
  logger.info(f"進度更新: {message}")
86
 
87
  def get_progress(self) -> str:
 
93
  try:
94
  news_data = self.db.get_recent_news(category=category, limit=limit)
95
  if not news_data:
96
+ return "📰 暫無新聞資料,請先執行爬蟲任務"
97
 
98
  return format_news_for_display(news_data)
99
 
 
103
 
104
  def manual_crawl(self) -> str:
105
  """手動觸發爬蟲"""
106
+ if not self.is_initialized:
107
+ return "⚠️ 系統還在初始化中,請稍後再試"
108
+
109
  if self.is_crawling:
110
  return "⚠️ 爬蟲正在運行中,請稍後再試"
111
 
 
215
  def api_manual_crawl():
216
  """手動觸發爬蟲API"""
217
  try:
218
+ if not app.is_initialized:
219
+ return jsonify({
220
+ 'success': False,
221
+ 'message': '系統還在初始化中'
222
+ })
223
+
224
  if app.is_crawling:
225
  return jsonify({
226
  'success': False,
 
248
  """獲取爬蟲進度API"""
249
  return jsonify({
250
  'progress': app.get_progress(),
251
+ 'is_crawling': app.is_crawling,
252
+ 'is_initialized': app.is_initialized
253
  })
254
 
255
+ # 定期更新函數
256
+ def periodic_update():
257
+ """定期更新進度和新聞"""
258
+ while True:
259
+ time.sleep(3) # 每3秒更新一次
260
+ yield [app.get_progress(), app.get_latest_news("all")]
261
+
262
  # 創建 Gradio 介面
263
  def create_interface():
264
  with gr.Blocks(
 
273
  .positive-badge { background: #28a745; color: white; }
274
  .negative-badge { background: #dc3545; color: white; }
275
  .neutral-badge { background: #6c757d; color: white; }
276
+ .progress-box { background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 5px; padding: 10px; font-family: monospace; font-size: 14px; }
277
  """
278
  ) as interface:
279
 
 
303
 
304
  # 進度顯示
305
  progress_display = gr.Textbox(
306
+ label="📊 系統狀態與進度",
307
  value=app.get_progress(),
308
  interactive=False,
309
+ elem_classes=["progress-box"],
310
+ lines=2
311
  )
312
 
313
  news_display = gr.HTML(label="新聞內容")
314
  crawl_result = gr.Textbox(label="爬取結果", visible=False)
315
 
316
+ # 更新函數
317
+ def update_all():
318
+ """更新所有信息"""
319
+ return app.get_progress(), app.get_latest_news("all")
 
 
320
 
321
  def refresh_news(category):
322
  return app.get_latest_news(category)
 
327
  news = app.get_latest_news("all")
328
  return result, news
329
 
330
+ # 使用定時器替代 every 參數
331
+ timer = gr.Timer(value=3) # 每3秒觸發一次
332
+ timer.tick(
333
+ fn=update_all,
334
+ outputs=[progress_display, news_display]
335
  )
336
 
337
  # 綁定事件
 
344
  outputs=[crawl_result]
345
  )
346
  category_radio.change(refresh_news, inputs=[category_radio], outputs=[news_display])
347
+
348
+ # 初始載入
349
+ interface.load(update_all, outputs=[progress_display, news_display])
350
 
351
  with gr.Tab("📊 統計資訊"):
352
  stats_display = gr.Markdown()
 
402
  POST /api/crawl
403
  ```
404
 
405
+ #### 4. 獲取系統狀態
406
  ```
407
  GET /api/progress
408
  ```
 
414
  import requests
415
 
416
  # 獲取所有新聞
417
+ response = requests.get('http://localhost:5000/api/news')
418
  news_data = response.json()
419
 
420
  # 獲取美股新聞
421
+ response = requests.get('http://localhost:5000/api/news?category=us_stock&limit=10')
422
  us_news = response.json()
423
+
424
+ # 檢查系統狀態
425
+ response = requests.get('http://localhost:5000/api/progress')
426
+ status = response.json()
427
  ```
428
 
429
  **JavaScript:**
 
454
  - **模型**: `uer/roberta-base-finetuned-jd-binary-chinese`
455
  - **分類**: 正面 (綠色) / 負面 (紅色) / 中性 (灰色)
456
  - **準確性**: 針對中文金融新聞優化
457
+ - **後台載入**: 模型在背景載入,不阻塞介面啟動
458
 
459
  ### 🕷️ 新聞爬蟲
460
  - **來源**: 鉅亨網 (cnyes.com)
 
476
 
477
  ---
478
 
479
+ 💡 **使用提示**:
480
+ - 首次啟動會在背景下載模型,請耐心等待
481
+ - 系統狀態會顯示初始化進度
482
  - 建議使用SSD硬碟提升SQLite性能
483
  - API接口可用於整合其他應用系統
484
  """)
 
496
  flask_thread = threading.Thread(target=run_flask, daemon=True)
497
  flask_thread.start()
498
 
499
+ print("🚀 啟動股市新聞情緒分析器...")
500
+ print("📊 網頁介面: http://localhost:7860")
501
+ print("🔌 API接口: http://localhost:5000")
502
+ print("💡 首次啟動需要下載模型,請耐心等待...")
503
+
504
  # 啟動Gradio介面
505
  interface = create_interface()
506
  interface.launch(