Tak0000000 commited on
Commit
9485029
·
verified ·
1 Parent(s): a44450a

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +34 -39
  2. news_sources.json +29 -0
app.py CHANGED
@@ -91,43 +91,38 @@ UNSPLASH_POOL = [
91
  # ─────────────────────────────────────────────────────────────────
92
  # 新聞來源定義
93
  # ─────────────────────────────────────────────────────────────────
94
- NEWS_SOURCES: List[Dict] = [
95
- # ── 原有來源 ──
96
  {"name": "科技新報", "type": "rss", "url": "https://technews.tw/feed/"},
97
  {"name": "癮科技", "type": "rss", "url": "https://chinese.engadget.com/rss.xml"},
98
  {"name": "數位時代", "type": "rss", "url": "https://www.bnext.com/rss"},
99
  {"name": "Yahoo 新聞", "type": "rss", "url": "https://hk.news.yahoo.com/rss/"},
100
- {"name": "HKEPC", "type": "html", "url": "https://www.hkepc.com/"},
101
- # ──增:科技/科學類 ──
102
- {"name": "QbitAI 機器之心", "type": "rss", "url": "https://www.jiqizhixin.com/rss"},
103
- {"name": "Inside 科技趨勢", "type": "rss", "url": "https://www.inside.com.tw/feed"},
104
- {"name": "明日科學", "type": "rss", "url": "https://tomorrowsci.com/feed/"},
105
- {"name": "Gizmodo", "type": "rss", "url": "https://gizmodo.com/rss"},
106
- {"name": "Hackaday", "type": "rss", "url": "https://hackaday.com/feed/"},
107
- {"name": "地球圖輯隊", "type": "rss", "url": "https://world.yam.com/rss.php"},
108
- {"name": "冷知識", "type": "rss", "url": "https://misstwocm.com/feed/"},
109
- # ── 新增:國際/財經類 ──
110
- {"name": "鉅亨網 國際政經", "type": "rss", "url": "https://news.cnyes.com/rss/div/global_macro"},
111
- {"name": "阿斯達克財經網", "type": "rss", "url": "https://www.aastocks.com/tc/resources/rss.ashx?type=1"},
112
- {"name": "RTHK 財經新聞", "type": "rss", "url": "https://rthk.hk/rthk/news/rss/c_expressnews_cfinance.xml"},
113
- {"name": "RTHK 本地新聞", "type": "rss", "url": "https://rthk.hk/rthk/news/rss/c_expressnews_clocal.xml"},
114
- {"name": "RTHK 國際新聞", "type": "rss", "url": "https://rthk.hk/rthk/news/rss/c_expressnews_cinternational.xml"},
115
- # ── 新增:材料/工業類 ──
116
- {"name": "Plastics Today", "type": "rss", "url": "https://www.plasticstoday.com/rss.xml"},
117
- {"name": "Metal Miner", "type": "rss", "url": "https://agmetalminer.com/feed/"},
118
- {"name": "AZoM 材料科學", "type": "rss", "url": "https://www.azom.com/azom-news-feed.xml"},
119
- # ── 新增:旅遊/生活類 ──
120
- {"name": "Wave 流行潮流", "type": "rss", "url": "https://www.wavetv.tw/feed/"},
121
- {"name": "U Travel 旅遊", "type": "rss", "url": "https://utravel.com.hk/rss"},
122
- {"name": "Yahoo 旅遊 港台", "type": "rss", "url": "https://travel.yahoo.com.tw/rss/headline/"},
123
- {"name": "Yahoo 旅遊 香港", "type": "rss", "url": "https://hk.news.yahoo.com/rss/travel"},
124
- {"name": "港生活 北上", "type": "rss", "url": "https://hk.ulifestyle.com.hk/rss/travel-main"},
125
- {"name": "香港01 大灣區", "type": "rss", "url": "https://www.hk01.com/rss/category/877"},
126
- # ── 新增:熱搜趨勢類 ──
127
- {"name": "Google Trends 香港", "type": "rss", "url": "https://trends.google.com.hk/trending/rss?geo=HK"},
128
- {"name": "Google Trends 美國", "type": "rss", "url": "https://trends.google.com/trending/rss?geo=US"},
129
  ]
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  # ─────────────���───────────────────────────────────────────────────
132
  # 圖片處理輔助函式
133
  # ─────────────────────────────────────────────────────────────────
@@ -569,13 +564,13 @@ SYSTEM_PROMPT = """你是一個專業的繁體中文新聞編輯秘書。你將
569
  請為每一篇文章完成以下任務:
570
 
571
  1. **語言判斷**:先判斷原文 title 和 content 的主要語言。
572
- - 若為**中文**:直接產出繁體中文的 title 和 summary(單語模式)。
573
  - 若為**英文或其他外語**:自動切換為「中英對照模式」(見第 2 點)。
574
 
575
  2. **中英對照模式**(僅適用於外語原文):
576
  title 和 summary 必須用換行符號 `\n` 分隔上下兩半段:
577
- - **上半段**:流暢、道地的繁體中文翻譯(使用香港/台灣常用表達方式)。
578
- - **下半段**:對應的英文原文(title 對照英文原標題;summary 對照由 AI 生成的流暢英文摘要,30~40 個英文字)。
579
 
580
  對照模式輸出範例:
581
  {
@@ -597,7 +592,7 @@ SYSTEM_PROMPT = """你是一個專業的繁體中文新聞編輯秘書。你將
597
  [
598
  {
599
  "title": "繁體中文標題(外語時:中文\nEnglish)",
600
- "summary": "5065字繁體中文摘要(外語時:中文摘要\nEnglish summary)",
601
  "category": "科技",
602
  "image_url": "https://...",
603
  "source": "來源名稱"
@@ -606,8 +601,8 @@ SYSTEM_PROMPT = """你是一個專業的繁體中文新聞編輯秘書。你將
606
  ]
607
 
608
  注意事項:
609
- - 中文模式摘要必須在 5065 個中文字之間,不可過短
610
- - 對照模式上半段繁體中文摘要同樣 5065 字,下半段英文摘要 30~40 個英文字
611
  - category 必須是列出的 9 個選項之一,不可自行發明
612
  - 所有繁體中文必須使用 zh-TW 習慣用語
613
  - 不可遺漏任何一篇文章
@@ -700,7 +695,7 @@ def summarize_by_deepseek(articles: List[Dict]) -> List[Dict]:
700
  a = articles[i]
701
  completed.append({
702
  "title": a["title"],
703
- "summary": clean_html(a.get("content", a["title"]))[:65],
704
  "category": guess_category(a.get("source", "")),
705
  "image_url": a["image_url"],
706
  "source": a["source"],
@@ -724,7 +719,7 @@ def summarize_by_deepseek(articles: List[Dict]) -> List[Dict]:
724
  for a in articles:
725
  fallback.append({
726
  "title": a["title"],
727
- "summary": clean_html(a.get("content", a["title"]))[:65],
728
  "category": guess_category(a.get("source", "")),
729
  "image_url": a["image_url"],
730
  "source": a["source"],
 
91
  # ─────────────────────────────────────────────────────────────────
92
  # 新聞來源定義
93
  # ─────────────────────────────────────────────────────────────────
94
+ # ── 備用清單(當 news_sources.json 無法讀取時使用)──
95
+ FALLBACK_SOURCES: List[Dict] = [
96
  {"name": "科技新報", "type": "rss", "url": "https://technews.tw/feed/"},
97
  {"name": "癮科技", "type": "rss", "url": "https://chinese.engadget.com/rss.xml"},
98
  {"name": "數位時代", "type": "rss", "url": "https://www.bnext.com/rss"},
99
  {"name": "Yahoo 新聞", "type": "rss", "url": "https://hk.news.yahoo.com/rss/"},
100
+ {"name": "RTHK 本地新聞", "type": "rss", "url": "https://rthk.hk/rthk/news/rss/c_expressnews_clocal.xml"},
101
+ {"name": "RTHK 國際聞", "type": "rss", "url": "https://rthk.hk/rthk/news/rss/c_expressnews_cinternational.xml"},
102
+ {"name": "Gizmodo", "type": "rss", "url": "https://gizmodo.com/rss"},
103
+ {"name": "Hackaday", "type": "rss", "url": "https://hackaday.com/feed/"},
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  ]
105
 
106
+
107
+ def load_news_sources() -> List[Dict]:
108
+ """從 news_sources.json 載入新聞來源清單;失敗時回退到備用清單。"""
109
+ import os as _os
110
+ config_path = _os.path.join(_os.path.dirname(_os.path.abspath(__file__)), "news_sources.json")
111
+ try:
112
+ with open(config_path, "r", encoding="utf-8") as f:
113
+ sources = json.load(f)
114
+ if isinstance(sources, list) and len(sources) > 0:
115
+ print(f"📋 成功載入 news_sources.json({len(sources)} 個來源)", flush=True)
116
+ return sources
117
+ else:
118
+ raise ValueError("news_sources.json 格式無效(需為非空陣列)")
119
+ except Exception as e:
120
+ print(f"⚠️ 無法讀取 news_sources.json:{e},使用備用清單({len(FALLBACK_SOURCES)} 個來源)", flush=True)
121
+ return FALLBACK_SOURCES
122
+
123
+
124
+ NEWS_SOURCES: List[Dict] = load_news_sources()
125
+
126
  # ─────────────���───────────────────────────────────────────────────
127
  # 圖片處理輔助函式
128
  # ─────────────────────────────────────────────────────────────────
 
564
  請為每一篇文章完成以下任務:
565
 
566
  1. **語言判斷**:先判斷原文 title 和 content 的主要語言。
567
+ - 若為**中文**:直接產出繁體中文的 title 和 summary(單語模式,摘要 80~200 字)。
568
  - 若為**英文或其他外語**:自動切換為「中英對照模式」(見第 2 點)。
569
 
570
  2. **中英對照模式**(僅適用於外語原文):
571
  title 和 summary 必須用換行符號 `\n` 分隔上下兩半段:
572
+ - **上半段**:流暢、道地的繁體中文翻譯(使用香港/台灣常用表達方式),摘要 80~200 字
573
+ - **下半段**:對應的英文原文(title 對照英文原標題;summary 對照由 AI 生成的流暢英文摘要,40~70 個英文字)。
574
 
575
  對照模式輸出範例:
576
  {
 
592
  [
593
  {
594
  "title": "繁體中文標題(外語時:中文\nEnglish)",
595
+ "summary": "80200字繁體中文摘要(外語時:中文摘要\nEnglish summary)",
596
  "category": "科技",
597
  "image_url": "https://...",
598
  "source": "來源名稱"
 
601
  ]
602
 
603
  注意事項:
604
+ - 中文模式摘要必須在 80200 個中文字之間,不可過短,也不可超 200 字
605
+ - 對照模式上半段繁體中文摘要同樣 80200 字,下半段英文摘要 40~70 個英文字
606
  - category 必須是列出的 9 個選項之一,不可自行發明
607
  - 所有繁體中文必須使用 zh-TW 習慣用語
608
  - 不可遺漏任何一篇文章
 
695
  a = articles[i]
696
  completed.append({
697
  "title": a["title"],
698
+ "summary": clean_html(a.get("content", a["title"]))[:200],
699
  "category": guess_category(a.get("source", "")),
700
  "image_url": a["image_url"],
701
  "source": a["source"],
 
719
  for a in articles:
720
  fallback.append({
721
  "title": a["title"],
722
+ "summary": clean_html(a.get("content", a["title"]))[:200],
723
  "category": guess_category(a.get("source", "")),
724
  "image_url": a["image_url"],
725
  "source": a["source"],
news_sources.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {"name": "科技新報", "type": "rss", "url": "https://technews.tw/feed/", "category": "科技/AI"},
3
+ {"name": "癮科技", "type": "rss", "url": "https://chinese.engadget.com/rss.xml", "category": "科技/3C"},
4
+ {"name": "數位時代", "type": "rss", "url": "https://www.bnext.com/rss", "category": "科技/商業"},
5
+ {"name": "HKEPC", "type": "html", "url": "https://www.hkepc.com/", "category": "科技/硬體"},
6
+ {"name": "QbitAI 機器之心", "type": "rss", "url": "https://www.jiqizhixin.com/rss", "category": "科技/AI"},
7
+ {"name": "Inside 科技趨勢", "type": "rss", "url": "https://www.inside.com.tw/feed", "category": "科技/趨勢"},
8
+ {"name": "明日科學", "type": "rss", "url": "https://tomorrowsci.com/feed/", "category": "科學/未來"},
9
+ {"name": "Gizmodo", "type": "rss", "url": "https://gizmodo.com/rss", "category": "科技/極客"},
10
+ {"name": "Hackaday", "type": "rss", "url": "https://hackaday.com/feed/", "category": "科技/DIY"},
11
+ {"name": "地球圖輯隊", "type": "rss", "url": "https://world.yam.com/rss.php", "category": "國際/圖文"},
12
+ {"name": "冷知識", "type": "rss", "url": "https://misstwocm.com/feed/", "category": "生活/趣味"},
13
+ {"name": "鉅亨網 國際政經", "type": "rss", "url": "https://news.cnyes.com/rss/div/global_macro", "category": "財經/國際"},
14
+ {"name": "阿斯達克財經網", "type": "rss", "url": "https://www.aastocks.com/tc/resources/rss.ashx?type=1", "category": "財經/港股"},
15
+ {"name": "RTHK 財經新聞", "type": "rss", "url": "https://rthk.hk/rthk/news/rss/c_expressnews_cfinance.xml", "category": "財經/香港"},
16
+ {"name": "RTHK 本地新聞", "type": "rss", "url": "https://rthk.hk/rthk/news/rss/c_expressnews_clocal.xml", "category": "時事/香港"},
17
+ {"name": "RTHK 國際新聞", "type": "rss", "url": "https://rthk.hk/rthk/news/rss/c_expressnews_cinternational.xml", "category": "國際/時事"},
18
+ {"name": "Plastics Today", "type": "rss", "url": "https://www.plasticstoday.com/rss.xml", "category": "材料工業/塑膠"},
19
+ {"name": "Metal Miner", "type": "rss", "url": "https://agmetalminer.com/feed/", "category": "材料工業/金屬"},
20
+ {"name": "AZoM 材料科學", "type": "rss", "url": "https://www.azom.com/azom-news-feed.xml", "category": "材料工業/科學"},
21
+ {"name": "Wave 流行潮流", "type": "rss", "url": "https://www.wavetv.tw/feed/", "category": "生活/潮流"},
22
+ {"name": "U Travel 旅遊", "type": "rss", "url": "https://utravel.com.hk/rss", "category": "旅遊/香港"},
23
+ {"name": "Yahoo 旅遊 港台", "type": "rss", "url": "https://travel.yahoo.com.tw/rss/headline/", "category": "旅遊/港台"},
24
+ {"name": "Yahoo 旅遊 香港", "type": "rss", "url": "https://hk.news.yahoo.com/rss/travel", "category": "旅遊/香港"},
25
+ {"name": "港生活 北上", "type": "rss", "url": "https://hk.ulifestyle.com.hk/rss/travel-main", "category": "旅遊/深圳"},
26
+ {"name": "香港01 大灣區", "type": "rss", "url": "https://www.hk01.com/rss/category/877", "category": "旅遊/大灣區"},
27
+ {"name": "Google Trends 香港","type": "rss", "url": "https://trends.google.com.hk/trending/rss?geo=HK", "category": "熱門趨勢/香港"},
28
+ {"name": "Google Trends 美國","type": "rss", "url": "https://trends.google.com/trending/rss?geo=US", "category": "熱門趨勢/全球"}
29
+ ]