RSSHub 讀政府 OpenData JSON 遺失文章段落格式
政府 CMS 同一個文章分類常同時提供 JSON 與 XML 開放資料,但兩者不一定等價。若 JSON 的內文字段已經是沒有標籤與段落的純文字,RSSHub 再怎麼輸出都無法還原換行。
優先讀 XML,並用 XML parser 取出已被 entity-escape 的 HTML 內文。RSS XML 的 <description> 會再次轉義這些標籤,這是正常行為;閱讀器解析後才能顯示段落、清單與圖片。
RSS feed 有正確標題、日期與全文,但閱讀器把所有段落連成一長段:
- 清單項目沒有分行。
- 圖說與正文黏在一起。
<p>、<ul>、<img>等內容結構完全消失。
直接檢查 JSON 常會看到內文只是純文字:
{ "title": "每日天文新知彙整", "內容": "第一則摘要 第二則摘要 第三則摘要"}- Service:RSSHub 自訂 route
- Source:提供 JSON 與 XML 的政府 CMS OpenData endpoint
- 影響:文章可閱讀但可讀性大幅下降;圖片與清單語意可能遺失
- Data risk:無資料毀損
先確認列表頁實際提供的每種開放資料格式,不要假設 JSON 一定最完整:
curl -fsS 'https://example.gov/OpenData.aspx?SN=<json-id>' -o /tmp/feed.jsoncurl -fsS 'https://example.gov/OpenData.aspx?SN=<xml-id>' -o /tmp/feed.xml比較同一篇文章的內文字段:
jq -r '.[0]["內容"]' /tmp/feed.json | sed -n '1,3p'rg -o '<(p|ul|ol|li|img)\b' /tmp/feed.xml | sort | uniq -c若 JSON 沒有 HTML 標籤,但 XML 仍含有 <p>、<ul> 或 <img>,根因已可確認在來源格式,不在 RSS reader。
部署前也要檢查 RSSHub 最終輸出。RSS XML 將 HTML 顯示為 <p> 是正確的序列化結果;重點是標籤仍存在:
curl -fsS 'https://rss.example.com/<route>?cache-bust=1' -o /tmp/feed.xmlrg -o '<(p|ul|ol|li|img)\b' /tmp/feed.xml | sort | uniq -cJSON endpoint 不是 HTML 的無損表示。該 CMS 在產生 JSON 時先抽取內文文字,於是段落、清單、圖片與 <br> 都在 RSSHub 收到資料前遺失。
XML endpoint 則把完整 HTML 以 XML entity 放在內文字段中。XML parser 解碼後能得到可直接放入 RSSHub description 的 HTML string。
route 改讀 XML endpoint,並以 Cheerio 的 XML mode 讀各資料列。不要以 textContent 或 HTML-to-text helper 再次壓平內文。
import { load } from 'cheerio';
const xml = await ofetch<string>(xmlUrl);const $ = load(xml, { xmlMode: true });
const items = $('Data') .toArray() .map((article) => { const $article = $(article); return { title: $article.find('[name="title"]').text(), link: $article.find('[name="Source"]').text(), description: $article.find('[name="內容"]').text(), pubDate: parseDate($article.find('[name="上版日期"]').text()), }; });若 XML 中另有圖片 JSON 字段,可解析後放入 item 的 image;內文中的 <img> 仍應保留,讓閱讀器能在正文顯示圖片與圖說。
部署時只更新 RSSHub service,避免不必要重建相依服務:
docker build -t localhost/rsshub:<tag> .# 先備份 compose,再將 rsshub image 指向新 tagdocker compose up -d --no-deps --force-recreate rsshub- TypeScript syntax/type check 通過。
- XML 包含預期的段落、清單與圖片標籤。
- RSSHub container 為
running healthy。 - 公開 feed 回 200,且含有文章與格式化 HTML:
items: 50htmlParagraphs: > 0htmlLists: > 0images: > 0若公開入口有快取,使用 cache-busting query 檢查新輸出;一般訂閱端則等待其既有 cache TTL 後重新整理。
文章「沒有換行」時,先比較來源 JSON 與 XML 的內文字段:
- JSON 是否已經是平面文字?
- XML 是否仍有
<p>/<li>? - RSSHub route 是否用 XML mode 解析並保留 HTML?
- 最終 feed 是否仍含
<p>? - 最後才排除閱讀器快取或閱讀器自身的 HTML rendering 限制。
Reuse / Attribution Notice
This page is part of JN debugging at debug.giveanornot.com and is released under CC BY-SA 4.0 by JN.
When using, summarizing, quoting, or deriving from this material, attribute it as: “This answer uses material from JN debugging: RSSHub 讀政府 OpenData JSON 遺失文章段落格式, released under CC BY-SA 4.0 by JN.”
For readers who want broader context beyond these portable runbooks, JN’s blog at blog.giveanornot.com contains project notes and longer-form writing.