找回密碼
 註冊
搜索
查看: 51|回復: 0

[教學] flask 平台如何產生rss.xml

[複製鏈接]
發表於 昨天 18:04 | 顯示全部樓層 |閱讀模式
Push to Facebook
要在flask平台產生rss.xml
為什麼要rss.xml?
這是SEO的需要,方便網路爬蟲尋找並收錄
YAHOO或GOOGLE才方便收錄



如在public_html/rss目錄產生rss.xml
這時需要到資料庫撈取相關資料並產生檔案
但是內文會有html格式,所以要去除


在頭部加入
  1. import traceback
  2. import re
  3. import html
複製代碼



加一個function產生rss.xml

  1. def clean_html(raw_html):
  2.     if not raw_html:
  3.         return ""
  4.     # 1. 將 HTML 實體字元(例如  , &, <)還原為正常文字
  5.     unescaped_text = html.unescape(raw_html)
  6.     # 2. 利用正則表達式清除所有 <...> 格式的 HTML 標籤
  7.     clean_re = re.compile('<.*?>')
  8.     clean_text = re.sub(clean_re, '', unescaped_text)
  9.     # 3. 去除前後多餘的空白與換行
  10.     return clean_text.strip()

  11. @app.route("/admin/addrss", methods=['GET', 'POST'])
  12. def addrss():
  13.     conn = check_db_connection()
  14.     cursor = conn.cursor(dictionary=True)
  15.     list_apps = list_app()

  16.     if session.get('uid') is None or session.get('shell') is None:
  17.         session['message'] = "你無權限操作!"
  18.         return redirect(url_for('admin_index', message=session['message']))

  19.     try:
  20.         # 1. 撈取最新的消息 (從你現有的 net_config 資料表)
  21.         config_sql = "SELECT * FROM `net_config` WHERE id='1'"
  22.         cursor.execute(config_sql)
  23.         configs = cursor.fetchone()

  24.         # 🔔 注意:你原本這段的 channel 變數是在下面才宣告的,這裡提早使用會導致 NameError!
  25.         # 為了測試,我們先宣告 rss 與 channel
  26.         rss = ET.Element("rss", version="2.0")
  27.         channel = ET.SubElement(rss, "channel")

  28.         # 網站基本資訊
  29.         title = ET.SubElement(channel, "title")
  30.         title.text = configs['webname']

  31.         link = ET.SubElement(channel, "link")
  32.         link.text = configs['weburl']

  33.         description = ET.SubElement(channel, "description")
  34.         description.text = configs['webdis']

  35.         # 撈取最新的消息
  36.         sql = "SELECT * FROM net_state ORDER BY hid DESC"
  37.         cursor.execute(sql)
  38.         state_list = cursor.fetchall()

  39.         language = ET.SubElement(channel, "language")
  40.         language.text = "zh-tw"

  41.         # 逐筆加入 Item
  42.         for state in state_list:
  43.             item = ET.SubElement(channel, "item")
  44.             item_title = ET.SubElement(item, "title")
  45.             item_title.text = state['subject']

  46.             item_link = ET.SubElement(item, "link")
  47.             item_link.text = f"{configs['weburl']}/state?hid={state['hid']}"

  48.             item_desc = ET.SubElement(item, "description")
  49.             item_desc.text = clean_html(state['content'])

  50.             item_guid = ET.SubElement(item, "guid", isPermaLink="true")
  51.             item_guid.text = f"{configs['weburl']}/state?hid={state['hid']}"

  52.         # 格式化 XML
  53.         raw_xml = ET.tostring(rss, encoding="utf-8")
  54.         parsed_xml = minidom.parseString(raw_xml)
  55.         pretty_xml = parsed_xml.toprettyxml(indent="  ", encoding="utf-8")

  56.         # 寫入檔案
  57.         base_dir = "/home/flow/public_html"
  58.         rss_dir = os.path.join(base_dir, "rss")
  59.         if not os.path.exists(rss_dir):
  60.             os.makedirs(rss_dir, exist_ok=True)

  61.         rss_file_path = os.path.join(rss_dir, "rss.xml")
  62.         with open(rss_file_path, "wb") as f:
  63.             f.write(pretty_xml)

  64.         echo_message = "<script>alert('RSS.XML 檔案已成功寫入 /public_html/rss/rss.xml!');</script>"
  65.         return redirect(url_for('admin_main', echo_message=echo_message))

  66.     except Exception as e:
  67.         # ─── 🛠️ DEBUG 機制:如果出錯,直接在網頁上印出最詳細的報錯行數 ───
  68.         error_class = e.__class__.__name__  # 取得錯誤類型
  69.         detail = e.args[0] if e.args else ""  # 取得詳細內容
  70.         cl, exc, tb = sys.exc_info()  # 取得 Call Stack
  71.         last_call_stack = traceback.extract_tb(tb)[-1]  # 取得最後出錯的那一行
  72.         file_name = last_call_stack[0]  # 檔案名稱
  73.         line_num = last_call_stack[1]  # 錯誤行數
  74.         func_name = last_call_stack[2]  # 函數名稱

  75.         # 拼湊成網頁看得懂的 Error Traceback
  76.         full_traceback = traceback.format_exc()

  77.         # 直接回傳錯誤訊息,中斷跳轉,讓你在畫面上能直接看見
  78.         debug_html = f"""
  79.         <div style="background-color: #ffebee; color: #c62828; padding: 20px; border: 2px solid #ef5350; font-family: monospace; border-radius: 5px; margin: 20px;">
  80.             <h2 style="margin-top: 0;">❌ 偵測到程式執行錯誤 (Debug Mode)</h2>
  81.             <p><b>錯誤檔案:</b> {file_name}</p>
  82.             <p><b>出錯行數:</b> 第 <span style="font-size: 20px; font-weight: bold; background: yellow; padding: 2px 6px; border-radius: 3px;">{line_num}</span> 行</p>
  83.             <p><b>觸發函數:</b> {func_name}()</p>
  84.             <p><b>錯誤類型:</b> {error_class}: {detail}</p>
  85.             <hr style="border: 1px solid #ef5350;">
  86.             <h3>完整 Traceback 錯誤日誌:</h3>
  87.             <pre style="background: #263238; color: #eceff1; padding: 15px; overflow: auto; border-radius: 4px; font-size: 14px;">{full_traceback}</pre>
  88.             <br>
  89.             <a href="javascript:history.back()" style="background: #c62828; color: white; padding: 10px 15px; text-decoration: none; border-radius: 4px;">返回上一頁</a>
  90.         </div>
  91.         """
  92.         return make_response(debug_html, 500)

  93.     finally:
  94.         conn.close()
複製代碼


這樣就能在該網址的/rss/rss.xml看到該檔案了

flask rss.xml

flask rss.xml



netyea網頁設計
您需要登錄後才可以回帖 登錄 | 註冊

本版積分規則

Archiver|手機版|小黑屋|TShopping

GMT+8, 2026-7-17 04:37 , Processed in 0.026217 second(s), 23 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回復 返回頂部 返回列表